Index: /indexers/branches/3.03a/Makefile.in
===================================================================
--- /indexers/branches/3.03a/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/Makefile.in	(revision 14757)
@@ -0,0 +1,93 @@
+###########################################################################
+#
+# Makefile -- Makefile for indexers used by Greenstone
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2007 New Zealand Digital Library Project
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# INDEXERDIRS contains the packages that we want to make and install.  It
+# is assumed that each package will have at least four rules: all, install,
+# clean, and distclean.
+
+ENABLE_ACCENTFOLD=@ENABLE_ACCENTFOLD@
+ifeq ($(ENABLE_ACCENTFOLD), 1)
+UNAC=packages/unac
+else
+UNAC=
+endif
+
+INDEXERDIRS = $(UNAC) mg mgpp lucene-gs 
+
+all install clean:
+	for odir in $(INDEXERDIRS); do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+
+nojava:
+	for odir in $(UNAC); do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) all) || exit 1; \
+        done
+	for odir in mg mgpp; do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+
+install-nojava:
+	for odir in $(UNAC); do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) install) || exit 1; \
+        done
+	for odir in mg mgpp; do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+
+javaonly:
+	for odir in mg mgpp; do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+	for odir in lucene-gs; do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) all) || exit 1; \
+        done
+
+install-javaonly:
+	for odir in mg mgpp; do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+	for odir in lucene-gs; do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) install) || exit 1; \
+        done
+
+
+distclean:
+	for odir in $(INDEXERDIRS); do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+	rm -f Makefile config.status config.log
Index: /indexers/branches/3.03a/README.txt
===================================================================
--- /indexers/branches/3.03a/README.txt	(revision 14757)
+++ /indexers/branches/3.03a/README.txt	(revision 14757)
@@ -0,0 +1,1 @@
+A temporary readme file for new indexers project for greenstone.
Index: /indexers/branches/3.03a/config.guess
===================================================================
--- /indexers/branches/3.03a/config.guess	(revision 14757)
+++ /indexers/branches/3.03a/config.guess	(revision 14757)
@@ -0,0 +1,1298 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+#   Free Software Foundation, Inc.
+
+timestamp='2001-07-12'
+
+# This file 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# Please send patches to <config-patches@gnu.org>.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script.
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int dummy(){}" > $dummy.c ;
+	for c in cc gcc c89 ; do
+	  ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
+	  if test $? = 0 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	rm -f $dummy.c $dummy.o $dummy.rel ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# Netbsd (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	# Determine the machine/vendor (is the vendor relevant).
+	case "${UNAME_MACHINE}" in
+	    amiga) machine=m68k-unknown ;;
+	    arm32) machine=arm-unknown ;;
+	    atari*) machine=m68k-atari ;;
+	    sun3*) machine=m68k-sun ;;
+	    mac68k) machine=m68k-apple ;;
+	    macppc) machine=powerpc-apple ;;
+	    hp3[0-9][05]) machine=m68k-hp ;;
+	    ibmrt|romp-ibm) machine=romp-ibm ;;
+	    *) machine=${UNAME_MACHINE}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE}" in
+	    i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit 0 ;;
+    alpha:OSF1:*:*)
+	if test $UNAME_RELEASE = "V4.0"; then
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+	fi
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	cat <<EOF >$dummy.s
+	.data
+\$Lformat:
+	.byte 37,100,45,37,120,10,0	# "%d-%x\n"
+
+	.text
+	.globl main
+	.align 4
+	.ent main
+main:
+	.frame \$30,16,\$26,0
+	ldgp \$29,0(\$27)
+	.prologue 1
+	.long 0x47e03d80 # implver \$0
+	lda \$2,-1
+	.long 0x47e20c21 # amask \$2,\$1
+	lda \$16,\$Lformat
+	mov \$0,\$17
+	not \$1,\$18
+	jsr \$26,printf
+	ldgp \$29,0(\$26)
+	mov 0,\$16
+	jsr \$26,exit
+	.end main
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+	if test "$?" = 0 ; then
+		case `./$dummy` in
+			0-0)
+				UNAME_MACHINE="alpha"
+				;;
+			1-0)
+				UNAME_MACHINE="alphaev5"
+				;;
+			1-1)
+				UNAME_MACHINE="alphaev56"
+				;;
+			1-101)
+				UNAME_MACHINE="alphapca56"
+				;;
+			2-303)
+				UNAME_MACHINE="alphaev6"
+				;;
+			2-307)
+				UNAME_MACHINE="alphaev67"
+				;;
+		esac
+	fi
+	rm -f $dummy.s $dummy
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit 0 ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit 0 ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit 0;;
+    amiga:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit 0 ;;
+    arc64:OpenBSD:*:*)
+	echo mips64el-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    arc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    hkmips:OpenBSD:*:*)
+	echo mips-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    pmax:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sgi:OpenBSD:*:*)
+	echo mips-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit 0;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit 0 ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit 0 ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    i86pc:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit 0 ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit 0 ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    sun3*:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mac68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+	echo m88k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit 0 ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit 0 ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.c -o $dummy \
+	  && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+	  && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit 0 ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit 0 ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit 0 ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit 0 ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit 0 ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit 0 ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit 0 ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+	exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit 0 ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		eval $set_cc_for_build
+		$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+		rm -f $dummy.c $dummy
+		echo rs6000-ibm-aix3.2.5
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit 0 ;;
+    *:AIX:*:[45])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+              case "${HPUX_REV}" in
+                11.[0-9][0-9])
+                  if [ -x /usr/bin/getconf ]; then
+                    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                        esac ;;
+                    esac
+                  fi ;;
+              esac
+              if [ "${HP_ARCH}" = "" ]; then
+              sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+	eval $set_cc_for_build
+	(CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
+	if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+	rm -f $dummy.c $dummy
+	fi ;;
+	esac
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    3050*:HI-UX:*:*)
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	echo unknown-hitachi-hiuxwe2
+	exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit 0 ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit 0 ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit 0 ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit 0 ;;
+    hppa*:OpenBSD:*:*)
+	echo hppa-unknown-openbsd
+	exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*X-MP:*:*:*)
+	echo xmp-cray-unicos
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3D:*:*:*)
+	echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY-2:*:*:*)
+	echo cray2-cray-unicos
+        exit 0 ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    hp300:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:FreeBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit 0 ;;
+    *:OpenBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	exit 0 ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit 0 ;;
+    i*:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit 0 ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit 0 ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i386-pc-interix
+	exit 0 ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit 0 ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit 0 ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    *:GNU:*:*)
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit 0 ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit 0 ;;
+    arm*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux
+	exit 0 ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    mips:Linux:*:*)
+	case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in
+	  big)    echo mips-unknown-linux-gnu && exit 0 ;;
+	  little) echo mipsel-unknown-linux-gnu && exit 0 ;;
+	esac
+	;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit 0 ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev67 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit 0 ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit 0 ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit 0 ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	ld_supported_targets=`cd /; ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit 0 ;;		
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit 0 ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+		exit 0 ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	cat >$dummy.c <<EOF
+#include <features.h>
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+#ifdef __ELF__
+# ifdef __GLIBC__
+#  if __GLIBC__ >= 2
+    printf ("%s-pc-linux-gnu\n", argv[1]);
+#  else
+    printf ("%s-pc-linux-gnulibc1\n", argv[1]);
+#  endif
+# else
+   printf ("%s-pc-linux-gnulibc1\n", argv[1]);
+# endif
+#else
+  printf ("%s-pc-linux-gnuaout\n", argv[1]);
+#endif
+  return 0;
+}
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit 0 ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit 0 ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit 0 ;;
+    i*86:*:5:[78]*)
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit 0 ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit 0 ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit 0 ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit 0 ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit 0 ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit 0 ;;
+    M68*:*:R3V[567]*:*)
+	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit 0 ;;
+    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                           # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit 0 ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit 0 ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit 0 ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit 0 ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit 0 ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit 0 ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit 0 ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Darwin:*:*)
+	echo `uname -p`-apple-darwin${UNAME_RELEASE}
+	exit 0 ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	if test "${UNAME_MACHINE}" = "x86pc"; then
+		UNAME_MACHINE=pc
+	fi
+	echo `uname -p`-${UNAME_MACHINE}-nto-qnx
+	exit 0 ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit 0 ;;
+    NSR-[KW]:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit 0 ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit 0 ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit 0 ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit 0 ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit 0 ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit 0 ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit 0 ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit 0 ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+eval $set_cc_for_build
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit 0 ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit 0 ;;
+    c34*)
+	echo c34-convex-bsd
+	exit 0 ;;
+    c38*)
+	echo c38-convex-bsd
+	exit 0 ;;
+    c4*)
+	echo c4-convex-bsd
+	exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /indexers/branches/3.03a/config.sub
===================================================================
--- /indexers/branches/3.03a/config.sub	(revision 14757)
+++ /indexers/branches/3.03a/config.sub	(revision 14757)
@@ -0,0 +1,1375 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+#   Free Software Foundation, Inc.
+
+timestamp='2001-06-08'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \
+	        | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \
+		| pyramid | mn10200 | mn10300 | tron | a29k \
+		| 580 | i960 | h8300 \
+		| x86 | ppcbe | mipsbe | mipsle | shbe | shle \
+		| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
+		| hppa64 \
+		| alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \
+		| alphaev6[78] \
+		| we32k | ns16k | clipper | i370 | sh | sh[34] \
+		| powerpc | powerpcle \
+		| 1750a | dsp16xx | pdp10 | pdp11 \
+		| mips16 | mips64 | mipsel | mips64el \
+		| mips64orion | mips64orionel | mipstx39 | mipstx39el \
+		| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
+		| mips64vr5000 | mips64vr5000el | mcore | s390 | s390x \
+		| sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \
+		| v850 | c4x \
+		| thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \
+		| pj | pjl | h8500 | z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	# FIXME: clean up the formatting here.
+	vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
+	      | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \
+	      | arm-*  | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \
+	      | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+	      | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
+	      | xmp-* | ymp-* \
+	      | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \
+	      | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \
+	      | hppa2.0n-* | hppa64-* \
+	      | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \
+	      | alphaev6[78]-* \
+	      | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
+	      | clipper-* | orion-* \
+	      | sparclite-* | pdp10-* | pdp11-* | sh-* | sh[34]-* | sh[34]eb-* \
+	      | powerpc-* | powerpcle-* | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \
+	      | mips16-* | mips64-* | mipsel-* \
+	      | mips64el-* | mips64orion-* | mips64orionel-* \
+	      | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
+	      | mipstx39-* | mipstx39el-* | mcore-* \
+	      | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \
+	      | [cjt]90-* \
+	      | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
+	      | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \
+	      | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*)
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	cray2)
+		basic_machine=cray2-cray
+		os=-unicos
+		;;
+	[cjt]90)
+		basic_machine=${basic_machine}-cray
+		os=-unicos
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mipsel*-linux*)
+		basic_machine=mipsel-unknown
+		os=-linux-gnu
+		;;
+	mips*-linux*)
+		basic_machine=mips-unknown
+		os=-linux-gnu
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	mmix*)
+		basic_machine=mmix-knuth
+		os=-mmixware
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+        pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pentium | p5 | k5 | k6 | nexgen)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2)
+		basic_machine=i686-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+	        ;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+	        ;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sparclite-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=t3e-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	windows32)
+		basic_machine=i386-pc
+		os=-windows32-msvcrt
+		;;
+	xmp)
+		basic_machine=xmp-cray
+		os=-unicos
+		;;
+        xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	mips)
+		if [ x$os = x-linux-gnu ]; then
+			basic_machine=mips-unknown
+		else
+			basic_machine=mips-mips
+		fi
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh3 | sh4)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv9 | sparcv9b)
+		basic_machine=sparc-sun
+		;;
+        cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	c4x*)
+		basic_machine=c4x-none
+		os=-coff
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto*)
+		os=-nto-qnx
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-ns2 )
+	        os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+	        os=-mint
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	pdp10-*)
+		os=-tops20
+		;;
+        pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+        *-gould)
+		os=-sysv
+		;;
+        *-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+        *-sgi)
+		os=-irix
+		;;
+        *-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-vxsim* | -vxworks*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /indexers/branches/3.03a/configure
===================================================================
--- /indexers/branches/3.03a/configure	(revision 14757)
+++ /indexers/branches/3.03a/configure	(revision 14757)
@@ -0,0 +1,2367 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="mgpp/text/MGQuery.cpp"
+ac_subdirs_all="$ac_subdirs_all packages/unac"
+ac_subdirs_all="$ac_subdirs_all mg mgpp"
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS ENABLE_ACCENTFOLD subdirs LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+	      localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$0" : 'X\(//\)[^/]' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+			  [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+			  [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-accentfold    Disable Accent Folding support
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-unac=dir       Use specified unac directory
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+	   test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+	"s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=$`echo $ac_var`
+	echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+	       sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+	ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --enable-accentfolding or --disable-accentfolding was given.
+if test "${enable_accentfolding+set}" = set; then
+  enableval="$enable_accentfolding"
+  ENABLE_ACCENTFOLD=0
+else
+  ENABLE_ACCENTFOLD=1
+fi;
+cat >>confdefs.h <<_ACEOF
+#define ENABLE_ACCENTFOLD $ENABLE_ACCENTFOLD
+_ACEOF
+
+
+
+
+# Check whether --with-unac or --without-unac was given.
+if test "${with_unac+set}" = set; then
+  withval="$with_unac"
+  UNAC_DIR=$withval
+fi;
+
+if test $ENABLE_ACCENTFOLD = 1; then
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+
+
+subdirs="$subdirs packages/unac"
+
+fi
+
+
+
+subdirs="$subdirs mg mgpp"
+
+
+          ac_config_files="$ac_config_files Makefile"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[	 ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[	 ]*$//;
+}'
+fi
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then we branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+cat >confdef2opt.sed <<\_ACEOF
+t clear
+: clear
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\),-D\1=\2,g
+t quote
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\),-D\1=\2,g
+t quote
+d
+: quote
+s,[	 `~#$^&*(){}\\|;'"<>?],\\&,g
+s,\[,\\&,g
+s,\],\\&,g
+s,\$,$$,g
+p
+_ACEOF
+# We use echo to avoid assuming a particular line-breaking character.
+# The extra dot is to prevent the shell from consuming trailing
+# line-breaks from the sub-command output.  A line-break within
+# single-quotes doesn't work because, if this script is created in a
+# platform that uses two characters for line-breaks (e.g., DOS), tr
+# would break.
+ac_LF_and_DOT=`echo; echo .`
+DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
+rm -f confdef2opt.sed
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+	 sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+		   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@ENABLE_ACCENTFOLD@,$ENABLE_ACCENTFOLD,;t t
+s,@subdirs@,$subdirs,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+	cat >$tmp/stdin
+	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+				     sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+	 # Absolute (can't be DOS-style, as IFS=:)
+	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 echo "$f";;
+      *) # Relative
+	 if test -f "$f"; then
+	   # Build tree
+	   echo "$f"
+	 elif test -f "$srcdir/$f"; then
+	   # Source tree
+	   echo "$srcdir/$f"
+	 else
+	   # /dev/null tree
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+#
+# CONFIG_SUBDIRS section.
+#
+if test "$no_recursion" != yes; then
+
+  # Remove --cache-file and --srcdir arguments so they do not pile up.
+  ac_sub_configure_args=
+  ac_prev=
+  for ac_arg in $ac_configure_args; do
+    if test -n "$ac_prev"; then
+      ac_prev=
+      continue
+    fi
+    case $ac_arg in
+    -cache-file | --cache-file | --cache-fil | --cache-fi \
+    | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+      ac_prev=cache_file ;;
+    -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+    | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \
+    | --c=*)
+      ;;
+    --config-cache | -C)
+      ;;
+    -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+      ac_prev=srcdir ;;
+    -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+      ;;
+    -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+      ac_prev=prefix ;;
+    -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+      ;;
+    *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;;
+    esac
+  done
+
+  # Always prepend --prefix to ensure using the same prefix
+  # in subdir configurations.
+  ac_sub_configure_args="--prefix=$prefix $ac_sub_configure_args"
+
+  ac_popdir=`pwd`
+  for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue
+
+    # Do not complain, so a configure script can configure whichever
+    # parts of a large source tree are present.
+    test -d $srcdir/$ac_dir || continue
+
+    { echo "$as_me:$LINENO: configuring in $ac_dir" >&5
+echo "$as_me: configuring in $ac_dir" >&6;}
+    { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+    cd $ac_dir
+
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      ac_sub_configure="$SHELL '$ac_srcdir/configure.gnu'"
+    elif test -f $ac_srcdir/configure; then
+      ac_sub_configure="$SHELL '$ac_srcdir/configure'"
+    elif test -f $ac_srcdir/configure.in; then
+      ac_sub_configure=$ac_configure
+    else
+      { echo "$as_me:$LINENO: WARNING: no configuration information is in $ac_dir" >&5
+echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;}
+      ac_sub_configure=
+    fi
+
+    # The recursion is here.
+    if test -n "$ac_sub_configure"; then
+      # Make the cache file name correct relative to the subdirectory.
+      case $cache_file in
+      [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;;
+      *) # Relative path.
+	ac_sub_cache_file=$ac_top_builddir$cache_file ;;
+      esac
+
+      { echo "$as_me:$LINENO: running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5
+echo "$as_me: running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;}
+      # The eval makes quoting arguments work.
+      eval $ac_sub_configure $ac_sub_configure_args \
+	   --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir ||
+	{ { echo "$as_me:$LINENO: error: $ac_sub_configure failed for $ac_dir" >&5
+echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+    cd $ac_popdir
+  done
+fi
+
+
+
Index: /indexers/branches/3.03a/configure.ac
===================================================================
--- /indexers/branches/3.03a/configure.ac	(revision 14757)
+++ /indexers/branches/3.03a/configure.ac	(revision 14757)
@@ -0,0 +1,23 @@
+dnl
+dnl Disable accent folding
+dnl
+
+AC_INIT(mgpp/text/MGQuery.cpp)
+AC_ARG_ENABLE(accentfolding, [  --disable-accentfold    Disable Accent Folding support], ENABLE_ACCENTFOLD=0, ENABLE_ACCENTFOLD=1)
+AC_DEFINE_UNQUOTED(ENABLE_ACCENTFOLD, $ENABLE_ACCENTFOLD)
+AC_SUBST(ENABLE_ACCENTFOLD)
+
+dnl
+dnl Specify location of unac - if specified, will be passed to cascading configures
+dnl
+AC_ARG_WITH(unac, [  --with-unac=dir       Use specified unac directory], UNAC_DIR=$withval)
+
+if test $ENABLE_ACCENTFOLD = 1; then
+AC_CONFIG_SUBDIRS(packages/unac)
+fi
+
+AC_CONFIG_SUBDIRS(mg mgpp)
+
+AC_OUTPUT(Makefile)
+
+
Index: /indexers/branches/3.03a/install-sh
===================================================================
--- /indexers/branches/3.03a/install-sh	(revision 14757)
+++ /indexers/branches/3.03a/install-sh	(revision 14757)
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
Index: /indexers/branches/3.03a/lucene-gs/Makefile
===================================================================
--- /indexers/branches/3.03a/lucene-gs/Makefile	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/Makefile	(revision 14757)
@@ -0,0 +1,21 @@
+LUCENE_JAR = ./lib/lucene-core-2.0.0.jar
+CLASSPATH = $(LUCENE_JAR):classes
+
+all: compile jar
+
+compile:
+	mkdir -p classes
+	javac -classpath $(CLASSPATH):. -d classes -sourcepath src/ src/org/greenstone/LuceneWrapper/*.java
+
+jar:
+	cd classes && jar xf ../$(LUCENE_JAR)
+	jar cvf LuceneWrapper.jar -C classes .
+
+install:
+
+clean:
+	/bin/rm -f classes/org/greenstone/LuceneWrapper/*.class
+
+distclean: clean
+	if test -e classes; then /bin/rm -r classes; fi
+	if test -e LuceneWrapper.jar; then /bin/rm -r LuceneWrapper.jar; fi
Index: /indexers/branches/3.03a/lucene-gs/lib/lucene-license.txt
===================================================================
--- /indexers/branches/3.03a/lucene-gs/lib/lucene-license.txt	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/lib/lucene-license.txt	(revision 14757)
@@ -0,0 +1,204 @@
+Lucene v 1.4.1 is licensed under the Apache Software License 2.0
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
Index: /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2IndexModifier.java
===================================================================
--- /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2IndexModifier.java	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2IndexModifier.java	(revision 14757)
@@ -0,0 +1,132 @@
+/** @file GS2IndexModifier.java
+ *
+ *  Extends the standard IndexModifier so that a use can retrieve documents and
+ *  the underlying IndexReader and IndexWriter. 
+ *
+ *  Addresses the problem that the Lucene standard IndexModifier can't actually
+ *  return a specified Document object, nor does it expose the IndexReader and
+ *  IndexWriter so the user can access their methods instead.
+ *
+ *  A component of the Greenstone digital library software from the New Zealand 
+ *  Digital Library Project at the University of Waikato, New Zealand.
+ *
+ *  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 of the License, 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 program; if not, write to the Free Software Foundation, Inc., 675
+ *  Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Copyright (c) 2006 DL Consulting Ltd., New Zealand
+ */
+
+package org.greenstone.LuceneWrapper;
+
+import java.io.IOException;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.IndexModifier;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermPositions;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.IndexSearcher;
+
+/**
+ */
+public class GS2IndexModifier
+    extends IndexModifier
+{
+    /** **/
+    private boolean debug = true;
+
+    /**
+     */
+    public GS2IndexModifier (String dir_name, Analyzer analyzer)
+        throws IOException
+    {
+        super(dir_name, analyzer, false);
+    }
+    /** GS2IndexModifier() **/
+
+    /**
+     */
+    protected void debug(String message)
+    {
+        if(debug)
+            {
+                System.err.println(message);
+            }
+    }
+    /** debug() **/
+
+    /**
+     */
+    public Document document(int n)
+        throws IOException
+    {
+        // Ensure the reader exists
+        createIndexReader();
+        return indexReader.document(n);
+    }
+    /** document() **/
+
+    /**
+     */
+    public int getDocNumByNodeID(int node_id)
+        throws IOException
+    {
+        debug("GS2IndexModifier.getDocument(" + node_id + ")");
+        int doc_num = -1;
+        // Create a new term to encapsulate this node id
+        Term term = new Term("nodeID", String.valueOf(node_id));
+        debug("Searching using term: " + term.toString());
+        // Ensure the indexReader exists
+        createIndexReader();
+        // We can return an enumeration of docNums which contains this term
+        TermPositions term_positions = indexReader.termPositions(term);
+        // If the size of term_positions is not 1 then somethings gone wrong in
+        // that the original terms did not uniquely identify a document.
+        if (term_positions.next())
+            {
+                doc_num = term_positions.doc();
+            }
+        else
+            {
+                debug("Term doesn't exists in index");
+            }
+        term_positions.close();
+        // To the garbage collection with thee
+        term_positions = null;
+        term = null;
+        // Done
+        return doc_num;
+    }
+    /** getDocumentByNodeID() **/
+
+    /**
+     */
+    public IndexReader getIndexReader()
+    {
+        return indexReader;
+    }
+    /** getIndexReader() **/
+
+    /**
+     */
+    public IndexWriter getIndexWriter()
+    {
+        return indexWriter;
+    }
+    /** getIndexWriter() **/
+}
+/** GS2IndexModifier **/
Index: /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneDelete.java
===================================================================
--- /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneDelete.java	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneDelete.java	(revision 14757)
@@ -0,0 +1,191 @@
+/** @file GS2LuceneDelete.java
+ *
+ *  Provides a wrapper to the document deleting features of Lucene. 
+ *
+ *  This java application makes use of the existing Lucene class IndexModifier 
+ *  to access and make changes to the information stored about documents in a
+ *  Lucene database. This is an essential component of the IncrementalBuilder
+ *  PERL module, and endevours to make editing the text and metadata of 
+ *  documents without having to rebuild the entire collection a reality (in
+ *  other words, true incremental/dynamic building).
+ *
+ *  A component of the Greenstone digital library software from the New Zealand 
+ *  Digital Library Project at the University of Waikato, New Zealand.
+ *
+ *  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 of the License, 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 program; if not, write to the Free Software Foundation, Inc., 675
+ *  Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Copyright (c) 2006 DL Consulting Ltd., New Zealand
+ */
+
+package org.greenstone.LuceneWrapper;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+
+
+/** Contains methods for deleting a document that has previously been indexed
+ *  into a Lucene database.
+ *  @author John Thompson, DL Consulting Ltd. (unless stated otherwise)
+ */
+public class GS2LuceneDelete
+{
+    /** This is the main entry point to the deletor and is responsible for 
+     *  parsing the arguments and creating an instance of the deletor class.
+     *
+     *  @param  args The arguments passed into the application as a string
+     *               array
+     *  @return An integer describing the exit state of the application
+     *  @throws Exception on any fatal error state
+     */
+    static public void main (String args[])
+        throws Exception
+    {
+        // Parse arguments
+        int node_id = -1;
+        String index_path = "";
+
+        for (int i = 0; i < args.length; i += 2)
+            {
+                if (args[i].equals("--index"))
+                    {
+                        index_path = args[i + 1];
+                    }
+                else if (args[i].equals("--nodeid"))
+                    {
+                        String temp = args[i + 1];
+                        node_id = Integer.parseInt(temp);
+                        temp = null; // Off to the gc with you!
+                    }
+                else 
+                    {
+                        System.out.println("Error! Unknown argument: " + args[i]);
+                        GS2LuceneDelete.printUsage();
+                    }
+            }
+
+        // Check arguments
+        if(index_path.equals(""))
+            {
+                System.out.println("Error! Missing index path");
+                GS2LuceneDelete.printUsage();
+            }
+        if(node_id == -1)
+            {
+                System.out.println("Error! Missing or invalid Node ID");
+                GS2LuceneDelete.printUsage();
+            }
+
+
+        // Instantiate deletor, and perform the delete
+        GS2LuceneDelete deletor = new GS2LuceneDelete(index_path);
+        deletor.deleteDocument(node_id);
+        deletor.destroy();
+        deletor = null;
+    }
+    /** main() **/
+
+    /** **/
+    private boolean debug = true;
+
+    /** **/
+    private GS2IndexModifier index_modifier;
+
+    /** Constructor which takes the path to the Lucene index to be edited.
+     *
+     *  @param  index_path The full path to the index directory as a String
+     */
+    public GS2LuceneDelete(String index_path)
+        throws IOException
+    {
+        Analyzer analyzer = new StandardAnalyzer();
+        index_modifier = new GS2IndexModifier(index_path, analyzer);
+    }
+    /** GS2LuceneDelete **/
+
+    /** When called prints a debug message but only if debugging is enabled.
+     */
+    public void debug(String message)
+    {
+        if(debug)
+            {
+                System.err.println(message);
+            }
+    }
+    /** debug() **/
+
+    /** Destructor which unallocates connection to Lucene.
+     */
+    public void destroy()
+        throws IOException
+    {
+        index_modifier.close();
+        index_modifier = null;
+    }
+
+    /** Delete the indicated document from the Lucene index. This process is
+     *  very similar to the initial step of index editing.
+     *
+     *  @param  node_id   The unique identifier of a Lucene document as an
+     *                    integer
+     */
+    public void deleteDocument(int node_id)
+        throws IOException
+    {
+        debug("GS2LuceneDelete.deleteDocument(" + node_id + ")");
+        debug("- Initial number of documents in index: " + index_modifier.docCount());
+        // Retrieve the document requested
+        int doc_num = index_modifier.getDocNumByNodeID(node_id);
+        if (doc_num != -1)
+            {
+                debug("* Found document #" + doc_num);
+                // Retrieve the actual document
+                Document document = index_modifier.document(doc_num);
+                // Remove the document from the index before modifying
+                index_modifier.deleteDocument(doc_num);
+                debug("* Removed document from index");
+            }
+        else
+            {
+                debug("- No such document!");
+            }
+        debug("- Final number of documents in index: " + index_modifier.docCount());
+    }
+    /** editIndex() **/
+
+    /** Display program usage message.
+     */
+    static public void printUsage()
+    {
+        System.out.println("usage: GS2LuceneDelete --index <path> --nodeid <int>");
+        System.out.println("");
+        System.out.println("where:");
+        System.out.println("  index    - is the full path to the directory containing the directory");
+        System.out.println("             to edit, including the level (ie didx, sidx)");
+        System.out.println("  nodeid   - the unique identifier of the document to delete. This is the");
+        System.out.println("             same as the docnum in the GDBM");
+        System.out.println("");
+        System.exit(0);
+    }
+    /** printUsage() **/
+
+}
+/** class GS2LuceneDelete **/
Index: /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneEditor.java
===================================================================
--- /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneEditor.java	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneEditor.java	(revision 14757)
@@ -0,0 +1,358 @@
+/** @file GS2LuceneEditor.java
+ *
+ *  Provides a wrapper to the index/document editing features of Lucene. 
+ *
+ *  This java application makes use of the existing Lucene class IndexModifier 
+ *  to access and make changes to the information stored about documents in a
+ *  Lucene database. This is an essential component of the IncrementalBuilder
+ *  PERL module, and endevours to make editing the text and metadata of 
+ *  documents without having to rebuild the entire collection a reality (in
+ *  other words, true incremental/dynamic building).
+ *
+ *  A component of the Greenstone digital library software from the New Zealand 
+ *  Digital Library Project at the University of Waikato, New Zealand.
+ *
+ *  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 of the License, 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 program; if not, write to the Free Software Foundation, Inc., 675
+ *  Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Copyright (c) 2006 DL Consulting Ltd., New Zealand
+ */
+
+package org.greenstone.LuceneWrapper;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+
+
+/** Contains methods for modifying a document that has previously been indexed
+ *  into a Lucene database.
+ *  @author John Thompson, DL Consulting Ltd.
+ */
+public class GS2LuceneEditor
+{
+    /** This is the main entry point to the editor and is responsible for 
+     *  parsing the arguments and creating an instance of the editor class.
+     *
+     *  @param  args The arguments passed into the application as a string
+     *               array
+     *  @return An integer describing the exit state of the application
+     *  @throws Exception on any fatal error state
+     *
+     *  @author John Thompson, DL Consulting Ltd.
+     */
+    static public void main (String args[])
+        throws Exception
+    {
+        // Parse arguments
+        int node_id = -1;
+        String field = "";
+        String index_path = "";
+        String new_value = "";
+        String old_value = "";
+
+        for (int i = 0; i < args.length; i += 2)
+            {
+                if (args[i].equals("--index"))
+                    {
+                        index_path = args[i + 1];
+                    }
+                else if (args[i].equals("--nodeid"))
+                    {
+                        String temp = args[i + 1];
+                        node_id = Integer.parseInt(temp);
+                        temp = null; // Off to the gc with you!
+                    }
+                else if (args[i].equals("--field"))
+                    {
+                        field = args[i + 1];
+                    }
+                else if (args[i].equals("--oldvalue"))
+                    {
+                        old_value = args[i + 1];
+                    }
+                else if (args[i].equals("--newvalue"))
+                    {
+                        new_value = args[i + 1];
+                    }
+                else 
+                    {
+                        System.out.println("Error! Unknown argument: " + args[i]);
+                        GS2LuceneEditor.printUsage();
+                    }
+            }
+
+        // Check arguments
+        if(index_path.equals(""))
+            {
+                System.out.println("Error! Missing index path");
+                GS2LuceneEditor.printUsage();
+            }
+        if(field.equals(""))
+            {
+                System.out.println("Error! Missing field");
+                GS2LuceneEditor.printUsage();
+            }
+        if(node_id == -1)
+            {
+                System.out.println("Error! Missing or invalid Node ID");
+                GS2LuceneEditor.printUsage();
+            }
+        if(old_value.equals("") && new_value.equals(""))
+            {
+                System.out.println("Error! No modification requested");
+                GS2LuceneEditor.printUsage(); 
+            }
+
+
+        // Instantiate editor, and perform the edit
+        GS2LuceneEditor editor = new GS2LuceneEditor(index_path);
+        editor.editIndex(node_id, field, old_value, new_value);
+        editor.destroy();
+        editor = null;
+    }
+    /** main() **/
+
+    /** **/
+    private boolean debug = true;
+
+    /** **/
+    private GS2IndexModifier index_modifier;
+
+    /** Constructor which takes the path to the Lucene index to be edited.
+     *
+     *  @param  index_path The full path to the index directory as a String
+     *
+     *  @author John Thompson, DL Consulting Ltd.
+     */
+    public GS2LuceneEditor(String index_path)
+        throws IOException
+    {
+        Analyzer analyzer = new StandardAnalyzer();
+        // create an index in /tmp/index, overwriting an existing one:
+        index_modifier = new GS2IndexModifier(index_path, analyzer);
+    }
+    /** GS2LuceneEditor **/
+
+    /**
+     */
+    public void debug(String message)
+    {
+        if(debug)
+            {
+                System.err.println(message);
+            }
+    }
+    /** debug() **/
+
+    /** Destructor which unallocates connection to Lucene.
+     */
+    public void destroy()
+        throws IOException
+    {
+        index_modifier.close();
+        index_modifier = null;
+    }
+
+    /** Make an edit to a Lucene index.
+     *
+     *  @param  oid       The unique identifier of a Lucene document as an
+     *                    integer
+     *  @param  field     The field to be modified as a String
+     *  @param  old_value The existing value to be changed or removed as a 
+     *                    String
+     *  @param  old_value The replacement value to be changed or added as a 
+     *                    String
+     *
+     *  @author John Thompson, DL Consulting Ltd.
+     */
+    public void editIndex(int node_id, String field, String old_value, String new_value)
+        throws IOException
+    {
+        debug("GS2LuceneEditor.editIndex(" + node_id + ",'" + field + "','" + old_value + "','" + new_value + "')");
+        debug("- Initial number of documents in index: " + index_modifier.docCount());
+        // Retrieve the document requested
+        int doc_num = index_modifier.getDocNumByNodeID(node_id);
+        if (doc_num != -1)
+            {
+                debug("* Found document #" + doc_num);
+                // Retrieve the actual document
+                Document document = index_modifier.document(doc_num);
+                // Remove the document from the index before modifying
+                index_modifier.deleteDocument(doc_num);
+                debug("* Removed document from index prior to editing");
+                // Retrieve the requested fields values, and turn it into a 
+                // vector
+                debug("* Modifying the value of the field: " + field);
+                doEdit(document, field, old_value, new_value);
+
+                // We have to do a similar modification to the ZZ field
+                // too
+                debug("* Modifying the value of the field: ZZ");
+                doEdit(document, "ZZ", old_value, new_value);
+
+                // Re-index document
+                index_modifier.addDocument(document);
+                debug("* Reindexing modified document");
+            }
+        else
+            {
+                debug("- No such document!");
+                Document document = new Document();
+
+                // Retrieve the requested fields values, and turn it into a 
+                // vector
+                debug("* Adding the value to the field: " + field);
+                doEdit(document, field, old_value, new_value);
+
+                // We have to do a similar modification to the ZZ field
+                // too
+                debug("* Adding the value to the field: ZZ");
+                doEdit(document, "ZZ", old_value, new_value);
+
+                // We also have to initialize the nodeId value
+                document.add(new Field("nodeID", String.valueOf(node_id), Field.Store.YES, Field.Index.TOKENIZED));
+
+                // Re-index document
+                index_modifier.addDocument(document);
+                debug("* Indexing new document");
+            }
+
+
+    }
+    /** editIndex() **/
+
+    /**
+     */
+    protected void doEdit(Document document, String field, String old_value, String new_value)
+    {
+        if (debug)
+            {
+                debug("GS2LuceneEditor.doEdit(Document, \"" + field + "\", \"" + old_value + "\", \"" + new_value + "\")");
+            }
+
+        String values_raw[] = document.getValues(field);
+        if(values_raw != null)
+            {
+                Vector values = new Vector(Arrays.asList(values_raw));
+                // Remove all the values for this field (no other safe way to
+                // do this
+                document.removeFields(field);
+                // DEBUG
+                if (debug)
+                    {
+                        debug("- Before modification:");
+                        for(int i = 0; i < values.size(); i++)
+                            {
+                                debug("\t" + field + "[" + i + "]: " + values.get(i));
+                            }
+                    }
+                // If old_value is set, remove it from the values array
+                if(!old_value.equals(""))
+                    {
+                        // Remove all occurances of this metadata - this means
+                        // it becomes a bit dangerous to have multiple pieces
+                        // of metadata with exactly the same metadata - but
+                        // this is only for indexing purposes so its not so
+                        // bad.
+                        while(values.contains(old_value))
+                            {
+                                values.remove(old_value);
+                            }
+                    }                
+                // If new_value is set, add it to the values array
+                if(!new_value.equals("") && !values.contains(new_value))
+                    {
+                        values.add(new_value);
+                    }
+                // DEBUG
+                if(debug)
+                    {
+                        debug("- After modification:");
+                        for(int i = 0; i < values.size(); i++)
+                            {
+                                debug("\t" + field + "[" + i + "]: " + values.get(i));
+                            }
+                    }
+                // Add all the values for this field
+                for(int i = 0; i < values.size(); i++)
+                    {
+                        document.add(new Field(field, (String)values.get(i), Field.Store.YES, Field.Index.TOKENIZED));
+                    }
+                values.clear();
+                values = null;
+            }
+        // We may be adding a value to a field that current has no values
+        else if (!new_value.equals(""))
+            {
+                Vector values = new Vector();
+                values.add(new_value);
+                // DEBUG
+                if(debug)
+                    {
+                        debug("- Brand spanking new values:");
+                        for(int i = 0; i < values.size(); i++)
+                            {
+                                debug("\t" + field + "[" + i + "]: " + values.get(i));
+                            }
+                    }
+                // Add all the values for this field
+                for(int i = 0; i < values.size(); i++)
+                    {
+                        document.add(new Field(field, (String)values.get(i), Field.Store.YES, Field.Index.TOKENIZED));
+                    }
+                values.clear();
+                values = null;
+            }
+        // Can't do a removal unless something exists
+        else
+            {
+                debug("- No such field for this document: " + field);
+            }
+        values_raw = null;
+    }
+    /** doEdit() **/
+
+    /**
+     */
+    static public void printUsage()
+    {
+        System.out.println("usage: GS2LuceneEditor --index <path> --nodeid <int> --field <string>");
+        System.out.println("                      [--oldvalue <string>] [--newvalue <string>]");
+        System.out.println("");
+        System.out.println("where:");
+        System.out.println("  index    - is the full path to the directory containing the directory");
+        System.out.println("             to edit, including the level (ie didx, sidx)");
+        System.out.println("  nodeid   - the unique identifier of the document to change. This is the");
+        System.out.println("             same as the docnum in the GDBM");
+        System.out.println("  field    - the two letter code of the metadata field to edit. These can");
+        System.out.println("             found in the build.cfg file. ZZ is not a valid field as it");
+        System.out.println("             is handled as a special case");
+        System.out.println("  oldvalue - the current value of the metadata field if it is to be");
+        System.out.println("             replaced or removed");
+        System.out.println("  newvalue - the new value for the metadata field if it is to be replaced");
+        System.out.println("             or added");
+        System.out.println("");
+        System.exit(0);
+    }
+    /** printUsage() **/
+
+}
+/** class GS2LuceneEditor **/
Index: /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneIndexer.java
===================================================================
--- /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneIndexer.java	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneIndexer.java	(revision 14757)
@@ -0,0 +1,127 @@
+/**********************************************************************
+ *
+ * GS2LuceneIndexer.java 
+ *
+ * Copyright 2004 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+package org.greenstone.LuceneWrapper;
+
+
+import java.io.*;
+import java.util.Vector;
+
+/**
+ * class for indexing XML generated by lucenebuildproc.pm
+  */
+
+public class GS2LuceneIndexer {
+
+    public static void main (String args[]) throws Exception 
+    { 
+
+	int verbosity = 1;
+	boolean create = false;
+
+	Vector filtered_args = new Vector();
+
+	int argc = args.length;
+	int i = 0;
+	while (i<argc) {
+	    if (args[i].startsWith("-")) {
+
+		// -create causes build to be incremental
+		if (args[i].equals("-create")) {
+		    create = true;
+		}
+
+		// -verbosity [num]
+		else if (args[i].equals("-verbosity")) {
+		    i++;
+		    if (i<argc) {
+			verbosity = Integer.parseInt(args[i]);
+		    }
+		}
+		else {
+		    System.out.println("Unrecognised option: " + args[i]);
+		}
+	    }
+	    else {
+		filtered_args.add((Object)args[i]);
+	    }
+	    i++;
+	}
+
+	if (filtered_args.size() != 3) {
+	    System.out.println("Usage: java GS2LuceneIndexer [-create|-verbosity [num]] doc-tag-level building_dir index");
+	    return;
+	}
+ 
+	String doc_tag_level     = (String)filtered_args.get(0);
+	String building_dirname  = (String)filtered_args.get(1);
+	String index_dirname     = (String)filtered_args.get(2);
+
+	String import_dirname = building_dirname + File.separator + "text";
+
+	File import_dir   = new File(import_dirname);
+	File building_dir = new File(building_dirname);
+
+	if (!import_dir.exists()) {
+	    System.out.println("Couldn't find import directory: "+import_dirname);
+	    return;
+	}
+
+	File idx_dir = new File(building_dir.getPath()+File.separator+index_dirname+File.separator);
+	idx_dir.mkdir();
+	
+	// Set up indexer
+	IndexXML indexer = new IndexXML(doc_tag_level,idx_dir, create);
+	indexer.init();	
+
+	// Read from stdin the files to process
+	try {
+	    InputStreamReader isr = new InputStreamReader(System.in, "UTF-8");
+	    BufferedReader brin = new BufferedReader(isr);
+
+	    StringBuffer xml_text = new StringBuffer(1024);
+	    String line = null;
+	    while ((line = brin.readLine()) != null) {
+		xml_text.append(line);
+		if (line.startsWith("</Doc>")) {
+		    indexer.indexFile(xml_text.toString());
+		    xml_text = new StringBuffer(1024);
+		}
+		//File xml_file = new File(import_dir + File.separator + line);
+		//indexer.indexFile(xml_file); // ****
+	    }
+
+	    brin.close();
+	    isr.close();
+
+	} catch (IOException e) {
+	    System.err.println("Error: unable to read from stdin");
+	    e.printStackTrace();
+	}
+
+	indexer.finish();
+    }
+}
Index: /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneQuery.java
===================================================================
--- /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneQuery.java	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneQuery.java	(revision 14757)
@@ -0,0 +1,599 @@
+/**********************************************************************
+ *
+ * GS2LuceneQuery.java 
+ *
+ * Copyright 2004 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+package org.greenstone.LuceneWrapper;
+
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermDocs;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.BooleanQuery.TooManyClauses;
+import org.apache.lucene.search.Filter;
+import org.apache.lucene.search.Hit;
+import org.apache.lucene.search.Hits;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.RangeFilter;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.TopFieldDocs;
+
+
+public class GS2LuceneQuery
+{
+
+
+    static private String TEXTFIELD = "TX";
+
+    // Use the standard set of English stop words by default
+    static private String[] stop_words = StandardAnalyzer.STOP_WORDS;
+
+    private String full_indexdir="";
+    private String default_conjunction_operator = "OR";
+    private String fuzziness = null;
+    private String sort_field = null;
+    private Sort sorter=new Sort();
+    private String filter_string = null;
+    private Filter filter = null;
+    private int start_results=1;
+    private int end_results=Integer.MAX_VALUE;
+
+    private QueryParser query_parser = null;
+    private QueryParser query_parser_no_stop_words = null;
+    private Searcher searcher = null;
+    private IndexReader reader = null;
+    
+    public GS2LuceneQuery() {
+
+	// Create one query parser with the standard set of stop words, and one with none
+
+	query_parser = new QueryParser(TEXTFIELD, new StandardAnalyzer(stop_words));
+    	query_parser_no_stop_words = new QueryParser(TEXTFIELD, new StandardAnalyzer(new String[] { }));
+    }
+    
+    
+    public boolean initialise() {
+
+    	if (full_indexdir==null || full_indexdir.length()==-1){
+	    System.out.println("Index directory is not indicated ");
+	    return false;
+    	}
+        try {
+    	    searcher = new IndexSearcher(full_indexdir);
+    	    reader = ((IndexSearcher) searcher).getIndexReader();
+	    
+	}
+	catch (IOException exception) {
+    	    exception.printStackTrace();
+	    return false;
+    	}
+	return true;
+
+    }
+    
+    public LuceneQueryResult runQuery(String query_string) {
+	
+	if (query_string == null || query_string.equals("")) {
+	    System.out.println("The query word is not indicated ");
+	    return null;
+	}
+
+ 	LuceneQueryResult lucene_query_result=new LuceneQueryResult();
+	lucene_query_result.clear();
+	    
+	try {    	        
+	    Query query_including_stop_words = query_parser_no_stop_words.parse(query_string);
+	    query_including_stop_words = query_including_stop_words.rewrite(reader);
+		
+	    Query query = parseQuery(reader, query_parser, query_string, fuzziness);
+	    query = query.rewrite(reader);
+		
+	    // Get the list of expanded query terms and their frequencies 
+	    // num docs matching, and total frequency	    
+	    HashSet terms = new HashSet();
+	    query.extractTerms(terms);
+	    
+	    Iterator iter = terms.iterator();
+	    while (iter.hasNext()) {
+		    
+		Term term = (Term) iter.next();
+		
+		// Get the term frequency over all the documents
+		TermDocs term_docs = reader.termDocs(term);
+		int term_freq = term_docs.freq();
+		int match_docs = 0;
+		if (term_freq != 0) match_docs++;
+		while (term_docs.next()) {
+		    term_freq += term_docs.freq();
+		    if (term_docs.freq()!= 0) {
+			match_docs++;
+		    }
+		}
+
+		// Create a term 
+		lucene_query_result.addTerm(term.text(), term.field(), match_docs, term_freq);
+	    }
+	
+	    // Get the list of stop words removed from the query
+	    HashSet terms_including_stop_words = new HashSet();
+	    query_including_stop_words.extractTerms(terms_including_stop_words);
+	    Iterator terms_including_stop_words_iter = terms_including_stop_words.iterator();
+	    while (terms_including_stop_words_iter.hasNext()) {
+		Term term = (Term) terms_including_stop_words_iter.next();
+		if (!terms.contains(term)) {
+		    lucene_query_result.addStopWord(term.text());
+		}
+	    }
+	    
+	    // do the query
+	    // Simple case for getting all the matching documents
+	    if (end_results == Integer.MAX_VALUE) {
+		// Perform the query (filter and sorter may be null)
+		Hits hits = searcher.search(query, filter, sorter);
+		lucene_query_result.setTotalDocs(hits.length());
+
+		// Output the matching documents
+		lucene_query_result.setStartResults(start_results);
+		lucene_query_result.setEndResults(hits.length());
+
+		for (int i = start_results; i <= hits.length(); i++) {
+		    Document doc = hits.doc(i - 1);
+		    lucene_query_result.addDoc(Long.parseLong(doc.get("nodeID").trim()), hits.score(i-1));
+		}
+	    }
+
+	    // Slightly more complicated case for returning a subset of the matching documents
+	    else {
+		// Perform the query (filter may be null)
+		TopFieldDocs hits = searcher.search(query, filter, end_results, sorter);
+		lucene_query_result.setTotalDocs(hits.totalHits);
+		
+		lucene_query_result.setStartResults(start_results);
+		lucene_query_result.setEndResults(end_results < hits.scoreDocs.length ? end_results: hits.scoreDocs.length);
+
+		// Output the matching documents
+		for (int i = start_results; (i <= hits.scoreDocs.length && i <= end_results); i++) {
+		    Document doc = reader.document(hits.scoreDocs[i - 1].doc);
+		    lucene_query_result.addDoc(Long.parseLong(doc.get("nodeID").trim()), hits.scoreDocs[i-1].score);
+		}
+	    }
+	}
+	
+	catch (ParseException parse_exception) {
+	    lucene_query_result.setError(LuceneQueryResult.PARSE_ERROR);
+	}
+	catch (TooManyClauses too_many_clauses_exception) {
+	    lucene_query_result.setError(LuceneQueryResult.TOO_MANY_CLAUSES_ERROR);
+	}
+	catch (IOException exception) {
+	    lucene_query_result.setError(LuceneQueryResult.IO_ERROR);
+	    exception.printStackTrace();
+	}
+	catch (Exception exception) {
+	    lucene_query_result.setError(LuceneQueryResult.OTHER_ERROR);
+	    exception.printStackTrace();
+	}
+	return lucene_query_result;
+    }
+
+    public void setDefaultConjunctionOperator(String default_conjunction_operator) {
+	this.default_conjunction_operator = default_conjunction_operator.toUpperCase();
+	if (default_conjunction_operator.equals("AND")) {
+	    query_parser.setDefaultOperator(query_parser.AND_OPERATOR);
+	    query_parser_no_stop_words.setDefaultOperator(query_parser.AND_OPERATOR);
+	} else { // default is OR
+	    query_parser.setDefaultOperator(query_parser.OR_OPERATOR);
+	    query_parser_no_stop_words.setDefaultOperator(query_parser.OR_OPERATOR);
+	}
+    }
+    
+    public String getDefaultConjunctionOperator() {
+	return this.default_conjunction_operator;
+    }
+    
+    public void setEndResults(int end_results) {
+	this.end_results = end_results;
+    }
+    public int getEndResults() {
+	return this.end_results;
+    }
+        
+    public void setFilterString(String filter_string) {
+	this.filter_string = filter_string;
+	this.filter = parseFilterString(filter_string);
+    }
+    public String getFilterString() {
+	return this.filter_string ;
+    }
+    
+    public Filter getFilter() {
+	return this.filter;
+    }
+
+    public void setIndexDir(String full_indexdir) {
+	this.full_indexdir = full_indexdir;
+    }
+    
+    public void setFuzziness(String fuzziness) {
+	this.fuzziness = fuzziness;
+    }
+    public String getFuzziness() {
+	return this.fuzziness;
+    }
+    
+    public void setSortField(String sort_field) {
+	this.sort_field = sort_field;
+	if (sort_field == null) {
+	    this.sorter = new Sort();
+	} else {
+	    this.sorter = new Sort(sort_field);
+	}
+    }
+    public String getSortField() {
+	return this.sort_field;
+    }
+        
+    public void setStartResults(int start_results) {
+	if (start_results < 1) {
+	    start_results = 1;
+	}
+	this.start_results = start_results;
+    }
+    public int getStartResults() {
+	return this.start_results;
+    }
+        
+    public void cleanUp() {
+	try {
+	    if (searcher != null) {
+		searcher.close();
+	    }
+	} catch (IOException exception) {
+	    exception.printStackTrace();
+	}
+    }
+
+    private Query parseQuery(IndexReader reader, QueryParser query_parser, String query_string, String fuzziness)
+	throws java.io.IOException, org.apache.lucene.queryParser.ParseException
+    {
+	// Split query string into the search terms and the filter terms
+	// * The first +(...) term contains the search terms so count
+	//   up '(' and stop when we finish matching ')'
+	int offset = 0;
+	int paren_count = 0;
+	boolean seen_paren = false;
+	while (offset < query_string.length() && (!seen_paren || paren_count > 0)) {
+	    if (query_string.charAt(offset) == '(') {
+		paren_count++;
+		seen_paren = true;
+	    }
+	    if (query_string.charAt(offset) == ')') {
+		paren_count--;
+	    }
+	    offset++;
+	}
+	String query_prefix = query_string.substring(0, offset);
+	String query_suffix = query_string.substring(offset);
+	
+	///ystem.err.println("Prefix: " + query_prefix);
+	///ystem.err.println("Suffix: " + query_suffix);
+	
+	Query query = query_parser.parse(query_prefix);
+	query = query.rewrite(reader);
+	
+	// If this is a fuzzy search, then we need to add the fuzzy
+	// flag to each of the query terms
+	if (fuzziness != null && query.toString().length() > 0) {
+	    
+	    // Revert the query to a string
+	    System.err.println("Rewritten query: " + query.toString());
+	    // Search through the string for TX:<term> query terms
+	    // and append the ~ operator. Note that this search will
+	    // not change phrase searches (TX:"<term> <term>") as
+	    // fuzzy searching is not possible for these entries.
+	    // Yahoo! Time for a state machine!
+	    StringBuffer mutable_query_string = new StringBuffer(query.toString());
+	    int o = 0; // Offset
+	    // 0 = BASE, 1 = SEEN_T, 2 = SEEN_TX, 3 = SEEN_TX:
+	    int s = 0; // State
+	    while(o < mutable_query_string.length()) {
+		char c = mutable_query_string.charAt(o);
+		if (s == 0 && c == TEXTFIELD.charAt(0)) {
+		    ///ystem.err.println("Found T!");
+		    s = 1;
+		}
+		else if (s == 1) {
+		    if (c == TEXTFIELD.charAt(1)) {
+			///ystem.err.println("Found X!");
+			s = 2;
+		    }
+		    else {
+			s = 0; // Reset
+		    }
+		}
+		else if (s == 2) {
+		    if (c == ':') {
+			///ystem.err.println("Found TX:!");
+			s = 3;
+		    }
+		    else {
+			s = 0; // Reset
+		    }
+		}
+		else if (s == 3) {
+		    // Don't process phrases
+		    if (c == '"') {
+			///ystem.err.println("Stupid phrase...");
+			s = 0; // Reset
+		    }
+		    // Found the end of the term... add the
+		    // fuzzy search indicator
+		    // Nor outside the scope of parentheses
+		    else if (Character.isWhitespace(c) || c == ')') {
+			///ystem.err.println("Yahoo! Found fuzzy term.");
+			mutable_query_string.insert(o, '~' + fuzziness);
+			o++;
+			s = 0; // Reset
+		    }
+		}
+		o++;
+	    }
+	    // If we were in the state of looking for the end of a
+	    // term - then we just found it!
+	    if (s == 3) {
+		    
+		mutable_query_string.append('~' + fuzziness);
+	    }
+	    // Reparse the query
+	    ///ystem.err.println("Fuzzy query: " + mutable_query_string.toString() + query_suffix);
+	    query = query_parser.parse(mutable_query_string.toString() + query_suffix);
+	}
+	else {
+	    query = query_parser.parse(query_prefix + query_suffix);
+	}
+	
+	return query;
+    }
+
+    private Filter parseFilterString(String filter_string)
+    {
+	Filter result = null;
+	Pattern pattern = Pattern.compile("\\s*\\+(\\w+)\\:([\\{\\[])(\\d+)\\s+TO\\s+(\\d+)([\\}\\]])\\s*");
+	Matcher matcher = pattern.matcher(filter_string);
+	if (matcher.matches()) {
+	    String field_name = matcher.group(1);
+	    boolean include_lower = matcher.group(2).equals("[");
+	    String lower_term = matcher.group(3);
+	    String upper_term = matcher.group(4);
+	    boolean include_upper = matcher.group(5).equals("]");
+	    result = new RangeFilter(field_name, lower_term, upper_term, include_lower, include_upper);
+	}
+	else {
+	    System.err.println("Error: Could not understand filter string \"" + filter_string + "\"");
+	}
+	return result;
+    }
+
+    
+    /** command line program and auxiliary methods */
+
+    // Fairly self-explanatory I should hope
+    static private boolean query_result_caching_enabled = false;
+
+    static public void main (String args[])
+    {
+	if (args.length == 0) {
+	    System.out.println("Usage: GS2LuceneQuery <index directory> [-fuzziness value] [-filter filter_string] [-sort sort_field] [-dco AND|OR] [-startresults number -endresults number] [query]");
+	    return;
+	}
+
+	try {
+	    String index_directory = args[0];
+	    
+	    GS2LuceneQuery queryer = new GS2LuceneQuery();
+	    queryer.setIndexDir(index_directory);
+
+	    // Prepare the index cache directory, if query result caching is enabled
+	    if (query_result_caching_enabled) {
+		// Make the index cache directory if it doesn't already exist
+		File index_cache_directory = new File(index_directory, "cache");
+		if (!index_cache_directory.exists()) {
+		    index_cache_directory.mkdir();
+		}
+
+		// Disable caching if the index cache directory isn't available
+		if (!index_cache_directory.exists() || !index_cache_directory.isDirectory()) {
+		    query_result_caching_enabled = false;
+		}
+	    }
+
+	    String query_string = null;
+
+	    // Parse the command-line arguments
+            for (int i = 1; i < args.length; i++) {
+		if (args[i].equals("-sort")) {
+		    i++;
+		    queryer.setSortField(args[i]);
+		}
+		else if (args[i].equals("-filter")) {
+		    i++;
+		    queryer.setFilterString(args[i]);
+		}
+		else if (args[i].equals("-dco")) {
+		    i++;
+		    queryer.setDefaultConjunctionOperator(args[i]);
+		}
+		else if (args[i].equals("-fuzziness")) {
+		    i++;
+		    queryer.setFuzziness(args[i]);
+		}
+		else if (args[i].equals("-startresults")) {
+		    i++;
+		    if (args[i].matches("\\d+")) {
+			queryer.setStartResults(Integer.parseInt(args[i]));
+		    }
+		}
+		else if (args[i].equals("-endresults")) {
+		    i++;
+		    if (args[i].matches("\\d+")) {
+			queryer.setEndResults(Integer.parseInt(args[i]));
+		    }
+		}
+		else {
+		    query_string = args[i];
+		}
+	    }
+	    
+	    if (!queryer.initialise()) {
+		return;
+	    }
+	    
+	    // The query string has been specified as a command-line argument
+	    if (query_string != null) {
+		runQueryCaching(index_directory, queryer, query_string);
+	    }
+
+	    // Read queries from STDIN
+	    else {
+		BufferedReader in = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
+		while (true) {
+		    // Read the query from STDIN
+		    query_string = in.readLine();
+		    if (query_string == null || query_string.length() == -1) {
+			break;
+		    }
+		    runQueryCaching(index_directory, queryer, query_string);
+		    
+		}
+	    }
+	    queryer.cleanUp();
+	}
+ 	catch (IOException exception) {
+ 	    exception.printStackTrace();
+ 	}
+    }
+
+    private static void runQueryCaching(String index_directory, GS2LuceneQuery queryer, String query_string) 
+	throws IOException
+    {
+	StringBuffer query_results_xml = new StringBuffer();
+
+	// Check if this query result has been cached from a previous search (if it's enabled)
+	File query_result_cache_file = null;
+	if (query_result_caching_enabled) {
+	    // Generate the cache file name from the query options
+	    String query_result_cache_file_name = query_string + "-";
+	    String fuzziness = queryer.getFuzziness();
+	    query_result_cache_file_name += ((fuzziness != null) ? fuzziness : "") + "-";
+	    String filter_string = queryer.getFilterString();
+	    query_result_cache_file_name += ((filter_string != null) ? filter_string : "") + "-";
+	    String sort_string = queryer.getSortField();
+	    query_result_cache_file_name += ((sort_string != null) ? sort_string : "") + "-";
+	    String default_conjunction_operator = queryer.getDefaultConjunctionOperator();
+	    query_result_cache_file_name += default_conjunction_operator + "-";
+	    int start_results = queryer.getStartResults();
+	    int end_results = queryer.getEndResults();
+	    query_result_cache_file_name += start_results + "-" + end_results;
+	    query_result_cache_file_name = fileSafe(query_result_cache_file_name);
+
+	    // If the query result cache file exists, just return its contents and we're done
+	    File index_cache_directory = new File(index_directory, "cache");
+	    query_result_cache_file = new File(index_cache_directory, query_result_cache_file_name);
+	    if (query_result_cache_file.exists() && query_result_cache_file.isFile()) {
+		FileInputStream fis = new FileInputStream(query_result_cache_file);
+		InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
+		BufferedReader buffered_reader = new BufferedReader(isr);
+		String line = "";
+		while ((line = buffered_reader.readLine()) != null) {
+		    query_results_xml.append(line + "\n");
+		}
+		String query_results_xml_string = query_results_xml.toString();
+		query_results_xml_string = query_results_xml_string.replaceFirst("cached=\"false\"", "cached=\"true\"");
+		System.out.print(query_results_xml_string);
+		return;
+	    }
+	}
+	
+	// not cached
+	query_results_xml.append("<ResultSet cached=\"false\">\n");
+	query_results_xml.append("<QueryString>" + LuceneQueryResult.xmlSafe(query_string) + "</QueryString>\n");
+	Filter filter = queryer.getFilter();
+	if (filter != null) {
+	    query_results_xml.append("<FilterString>" + filter.toString() + "</FilterString>\n");
+	}
+	
+	LuceneQueryResult query_result = queryer.runQuery(query_string);
+	if (query_result == null) {
+	    System.err.println("Couldn't run the query");
+	    return;
+	}
+	
+	if (query_result.getError() != LuceneQueryResult.NO_ERROR) {
+	    query_results_xml.append("<Error type=\""+query_result.getErrorString()+"\" />\n");
+	} else {
+	    query_results_xml.append(query_result.getXMLString());
+	}
+	query_results_xml.append("</ResultSet>\n");
+
+	System.out.print(query_results_xml);
+
+	// Cache this query result, if desired
+	if (query_result_caching_enabled) {
+	    FileWriter query_result_cache_file_writer = new FileWriter(query_result_cache_file);
+	    query_result_cache_file_writer.write(query_results_xml.toString());
+	    query_result_cache_file_writer.close();
+	}
+    }
+    
+    private static String fileSafe(String text)
+    {
+	StringBuffer file_safe_text = new StringBuffer();
+	for (int i = 0; i < text.length(); i++) {
+	    char character = text.charAt(i);
+	    if ((character >= 'A' && character <= 'Z') || (character >= 'a' && character <= 'z') || (character >= '0' && character <= '9') || character == '-') {
+		file_safe_text.append(character);
+	    }
+	    else {
+		file_safe_text.append('%');
+		file_safe_text.append((int) character);
+	    }
+	}
+	return file_safe_text.toString();
+    }
+
+    
+}
+
+
Index: /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/IndexXML.java
===================================================================
--- /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/IndexXML.java	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/IndexXML.java	(revision 14757)
@@ -0,0 +1,68 @@
+/**********************************************************************
+ *
+ * IndexXML.java 
+ *
+ * Copyright 2004 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+package org.greenstone.LuceneWrapper;
+
+
+import java.io.File;
+
+public class IndexXML extends Object {
+
+    String doc_tag_level_ = null;
+    File out_dir_         = null;
+    Indexer indexer_      = null;
+    boolean create_index_ = false;
+
+    public IndexXML(String doc_tag_level, File out_dir, boolean create)
+    {
+	doc_tag_level_ = doc_tag_level;
+	out_dir_ = out_dir;
+	create_index_ = create;
+    }
+
+    public void init() 
+    {
+	indexer_ = new Indexer(doc_tag_level_, out_dir_, create_index_);
+    }
+
+    public void finish() 
+    {
+	indexer_.finish();
+    }
+
+    public void indexFile(File file) 
+    {
+	String name = file.getName();
+	name = name.substring(0, name.lastIndexOf('.'));
+	System.out.println("Indexing "+file.getPath()+" with id "+name);
+	indexer_.index(name, file);
+    }    
+
+    public void indexFile(String xml_text) 
+    {
+	indexer_.index(xml_text);
+    }    
+
+}
Index: /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/Indexer.java
===================================================================
--- /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/Indexer.java	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/Indexer.java	(revision 14757)
@@ -0,0 +1,284 @@
+/**********************************************************************
+ *
+ * Indexer.java 
+ *
+ * Copyright 2004 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+package org.greenstone.LuceneWrapper;
+
+
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+
+import java.util.Stack;
+import java.io.FileInputStream;
+import java.io.File;
+import java.io.StringReader;
+import java.net.URL;
+
+
+
+public class Indexer extends DefaultHandler 
+{
+    IndexWriter writer_   = null;
+    SAXParser sax_parser_ = null;
+    String doc_tag_level_ = null;
+
+    Stack stack_ = null;
+    String path_ = "";
+
+    Document current_doc_ = null;
+    String current_node_ = "";
+    String indexable_current_node_ = "";
+    String current_contents_ = "";
+
+    protected String file_id_ = null;
+
+    /** pass in true if want to create a new index, false if want to use the existing one */
+    public Indexer (String doc_tag_level, File index_dir, boolean create) 
+    {
+	doc_tag_level_ = doc_tag_level;
+
+	try {
+	    stack_ = new Stack();
+	    SAXParserFactory sax_factory = SAXParserFactory.newInstance();
+	    sax_parser_ = sax_factory.newSAXParser();
+
+	    XMLReader reader = sax_parser_.getXMLReader(); 
+	    reader.setFeature("http://xml.org/sax/features/validation", false);
+
+	    writer_ = new IndexWriter(index_dir.getPath(), new StandardAnalyzer(), create);
+	    // by default, will only index 10,000 words per document
+	    // Can throw out_of_memory errors
+	    writer_.setMaxFieldLength(Integer.MAX_VALUE);
+	    if (create) {
+		writer_.optimize();
+	    }
+
+	} catch (Exception e) {
+	    // do nothing!
+	}
+    }
+
+    /** index one document */
+    public void index (String file_id, File file) 
+    {
+	file_id_ = file_id;
+	path_ = "";
+	String base_path = file.getPath();
+	base_path = base_path.substring(0, base_path.lastIndexOf(File.separatorChar));
+
+	try {	    
+            sax_parser_.parse(new InputSource(new FileInputStream(file)), this);
+        }
+        catch (Exception e) {
+	    println("parse error:");
+            e.printStackTrace();
+	}
+    }
+
+    /** index one document stored as string*/
+    public void index (String xml_text) 
+    {
+	file_id_ = "<xml doc on stdin>";
+	path_ = "";
+
+	try {
+            sax_parser_.parse(new InputSource(new StringReader(xml_text)), this);
+        }
+        catch (Exception e) {
+	    println("parse error:");
+            e.printStackTrace();
+	}
+    }
+    
+    public void finish() 
+    {
+	/** optimise the index */
+	try {
+	    writer_.optimize();
+	    writer_.close();
+	} 
+	catch (Exception e) {
+	}
+    }
+
+    protected void print(String s) 
+    { 
+	System.out.print(s); 
+    }
+
+    protected void println(String s) 
+    { 
+	System.out.println(s); 
+    }
+
+    public void startDocument() throws SAXException 
+    {
+        println("Starting to index " + file_id_);
+        print("[");
+    }
+
+    public void endDocument() throws SAXException 
+    {
+        println("]");
+        println("... indexing finished.");
+    }
+
+    public void startElement(String uri, String localName, String qName, Attributes atts) 
+	throws SAXException 
+    {
+	path_ = appendPathLink(path_, qName, atts);
+
+	if (qName.equals(doc_tag_level_)) {
+	    pushOnStack(); // start new doc
+	    current_node_ = qName;
+	    String node_id = atts.getValue("gs2:id");
+
+	    print(" " + qName + ": " + node_id );
+	    current_doc_.add(new Field("nodeID", node_id, Field.Store.YES, Field.Index.NO));
+	}
+
+	if (XMLTagInfo.isIndexable(atts)) {
+	    indexable_current_node_ = qName;	
+	}
+	else {
+	    indexable_current_node_ = "";
+	}
+
+    }
+    public void endElement(String uri, String localName, String qName) throws SAXException 
+    {
+	if (qName.equals(indexable_current_node_))
+            {
+                current_doc_.add(new Field(qName, current_contents_, Field.Store.NO, Field.Index.TOKENIZED, Field.TermVector.YES));
+                // We only need the term vector for the TX field
+                if (!qName.equals("TX"))
+                    {
+                        current_doc_.add(new Field("by" + qName, current_contents_, Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
+                    }
+
+                current_contents_ = "";
+            }
+
+	if (qName.equals(doc_tag_level_)) {
+	    try {
+		writer_.addDocument(current_doc_);
+	    } 
+	    catch (java.io.IOException e) {
+		e.printStackTrace();
+	    }
+	    popOffStack(); // end document
+	}
+	
+	path_ = removePathLink(path_);
+    }
+
+    public void characters(char ch[], int start, int length) throws SAXException 
+    {
+	String data = new String(ch, start, length).trim();
+	if (data.length() > 0 ) {
+	    current_contents_ += data;
+	}
+    }
+    
+    protected String appendPathLink(String path, String qName, Attributes atts) 
+    {
+
+	path = path + "/"+qName;
+	if (atts.getLength()>0) {
+	    String id = atts.getValue("gs2:id");
+	    if (id != null) {
+		path +=  "[@gs2:id='"+id+"']";
+	    }
+	    else {
+		id = atts.getValue("gs3:id");
+		if (id != null) {
+		    path +=  "[@gs3:id='"+id+"']";
+		}
+	    }
+	}
+	return path;
+    }
+    protected String  removePathLink(String path) 
+    {
+
+	int i=path.lastIndexOf('/');
+	if (i==-1) {
+	    path="";
+	} else {
+	    path = path.substring(0, i);
+	}
+	return path;
+    }
+    /** these are what we save on the stack */
+    private class MyDocument 
+    {
+	public Document doc = null;
+	public String contents = null;
+	public String tagname = "";
+	
+    }
+
+    protected void pushOnStack() 
+    {
+	if (current_doc_ != null) {
+	    MyDocument save = new MyDocument();
+	    save.doc = current_doc_;
+	    save.contents = current_contents_;
+	    save.tagname = current_node_;
+	    stack_.push(save);
+	}
+	current_doc_ = new Document();
+	current_contents_ = "";
+	current_node_ = "";
+    }
+
+    protected void popOffStack() 
+    {
+	if (!stack_.empty()) {
+	    MyDocument saved = (MyDocument)stack_.pop();
+	    current_doc_ = saved.doc;
+	    current_contents_ = saved.contents;
+	    current_node_ = saved.tagname;
+	} else {
+	    current_doc_ = new Document();
+	    current_contents_ = "";
+	    current_node_ = "";
+	}
+    }
+
+
+}
+
+
Index: /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/LuceneQueryResult.java
===================================================================
--- /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/LuceneQueryResult.java	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/LuceneQueryResult.java	(revision 14757)
@@ -0,0 +1,250 @@
+/**********************************************************************
+ *
+ * LuceneQueryResult.java 
+ *
+ * Copyright 2007 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+package org.greenstone.LuceneWrapper;
+
+import java.util.Vector;
+
+/** a QueryResult class for a lucene search
+ *
+ */
+public class LuceneQueryResult {
+    
+    public static final int NO_ERROR = 0;
+    public static final int PARSE_ERROR = 1;
+    public static final int TOO_MANY_CLAUSES_ERROR = 2;
+    public static final int IO_ERROR = 3;
+    public static final int OTHER_ERROR = 4;
+    
+    /** the list of DocInfo */
+    protected Vector docs_=null;
+    /** the list of TermInfo */
+    protected Vector terms_=null;
+    /** the list of stopwords found in the query */
+    protected Vector stopwords_ = null;
+    /** the total number of docs found - not necessarily the size of docs_*/
+    protected int total_num_docs_=0;
+    /** the start result number if we are retrieving only a portion of the results */
+    protected int start_results_ = 0;
+    /** the end result number if we are retrieving only a portion of the results */
+    protected int end_results_ = 0;
+    /** whether an error has occurred and what kind it is*/
+    protected int error_ = NO_ERROR;
+
+    LuceneQueryResult() {
+	docs_ = new Vector();
+	terms_ = new Vector();
+	stopwords_ = new Vector();
+    }
+    
+    /** clear the info from the last query - should be called before setting any new docs/terms */
+    public void clear() {
+	total_num_docs_=0;
+	docs_.clear();
+	terms_.clear();
+	stopwords_.clear();
+	error_ = NO_ERROR;
+    }
+
+    /** returns the result as a String - useful for printing out results */
+    public String toString() {
+	
+	String result = "";
+	result += "docs (ranks): ";
+	for (int i=0; i<docs_.size(); i++) {
+	    result += ((DocInfo)docs_.elementAt(i)).toString()+", ";
+	}
+	result += "\nterms: ";
+	for (int i=0; i<terms_.size(); i++) {
+	    result += ((TermInfo)terms_.elementAt(i)).toString()+", ";
+	}
+	result += "\nactual number of docs found = "+total_num_docs_;
+	
+	return result;
+    }
+    /** a shorter representation - just terms and total docs - not the 
+	individual docnums and ranks */
+    public String toShortString() {
+	String result = "";
+	result += "\nterms: ";
+	for (int i=0; i<terms_.size(); i++) {
+	    result += ((TermInfo)terms_.elementAt(i)).toString()+", ";
+	}
+	result += "\nactual number of docs found = "+total_num_docs_;
+	return result;
+    }
+    
+    public void setTotalDocs(int num) {
+	total_num_docs_=num;
+    }
+    
+    public void setStartResults(int start) {
+	start_results_ = start;
+    }
+
+    public void setEndResults(int end) {
+	end_results_ = end;
+    }
+
+    public void addDoc(long doc, float rank) {
+	DocInfo doc_info = new DocInfo(doc, rank);
+	docs_.add(doc_info);
+    }
+    
+    public void addTerm(String term, String field, int match, int freq) {
+	TermInfo ti = new TermInfo();
+	ti.term_=term;
+	ti.field_=field;
+	ti.match_docs_=match;
+	ti.term_freq_=freq;
+	terms_.add(ti);
+    }
+    public void addStopWord(String stopword) {
+	stopwords_.add(stopword);
+    }
+    public Vector getDocs() {
+	return docs_;
+    }
+    
+    public int getError() {
+	return error_;
+    }
+    
+    public String getErrorString() {
+	if (error_ == PARSE_ERROR) {
+	    return "PARSE_EXCEPTION";
+	}
+	if (error_ == TOO_MANY_CLAUSES_ERROR) {
+	    return "TOO_MANY_CLAUSES";
+	}
+	if (error_ == IO_ERROR) {
+	    return "IO_ERROR";
+	}
+	if (error_ == NO_ERROR) {
+	    return "NO_ERROR";
+	}
+	return "UNKNOWN";
+    }
+
+    public Vector getTerms() {
+	return terms_;
+    }
+    
+    public Vector getStopWords() {
+	return stopwords_;
+    }
+    public int getTotalDocs() {
+	return total_num_docs_;
+    }
+    
+    public void setError(int error) {
+	error_ = error;
+    }
+    
+    public String getXMLString() {
+	StringBuffer buffer = new StringBuffer();
+
+	// terms
+	buffer.append("<QueryTermsInfo num=\"" + terms_.size() + "\"/>\n");
+	for (int i=0; i<terms_.size(); i++) {
+	    buffer.append(((TermInfo)terms_.elementAt(i)).toXMLString()+"\n");
+	}
+
+	// stopwords
+	for (int i=0; i<stopwords_.size(); i++) {
+	    buffer.append("<StopWord value=\"" + (String)stopwords_.elementAt(i)+"\" />\n");
+	}
+	
+	// results
+	buffer.append("<MatchingDocsInfo num=\"" + total_num_docs_ + "\"/>\n");
+	buffer.append("<StartResults num=\"" + start_results_ + "\"/>\n");
+	buffer.append("<EndResults num=\"" + end_results_ + "\"/>\n");
+	
+	for (int i=0; i< docs_.size(); i++) {
+	    buffer.append(((DocInfo)docs_.elementAt(i)).toXMLString()+"\n");
+	}
+
+	return buffer.toString();
+    }
+
+ 
+    public class TermInfo {
+	
+	/** the term itself */
+	public String term_=null;
+	/** the field for which this term was queried */
+	public String field_=null;
+	/** the number of documents containing this term */
+	public int match_docs_=0;
+	/** overall term freq for this term */
+	public int term_freq_=0;
+	
+	public TermInfo() {
+	}
+	
+	/** output the class as a string */
+	public String toString() {
+	    String result="";
+	    result +="<"+field_+">\""+term_+" docs("+match_docs_;
+	    result +=")freq("+term_freq_+")";
+	    return result;
+	}
+
+	/** output as an XML element */
+	public String toXMLString() {
+	    return "<Term value=\"" + xmlSafe(term_) + "\" field=\"" + field_ + "\" freq=\"" + term_freq_ + "\" />";
+	}
+    }
+
+    public class DocInfo {
+	
+	public long num_=0;
+	public float rank_=0;
+	
+	public DocInfo(long doc, float rank) {
+	    num_=doc;
+	    rank_=rank;
+	}
+	public String toString(){
+	    return ""+num_+"("+rank_+")";
+	}
+	public String toXMLString() {
+	    return "<Match id=\"" + num_ + "\" rank=\"" + rank_ +"\" />";
+	}
+    }
+
+    // where should this go???
+    
+    public static String xmlSafe(String text) {
+	text = text.replaceAll("&","&amp;amp;");
+	text = text.replaceAll("<","&amp;lt;");
+	text = text.replaceAll(">","&amp;gt;");
+	text = text.replaceAll("'","&amp;#039;");
+	text = text.replaceAll("\\\"","&amp;quot;");
+	return text;
+    }
+ 
+}
Index: /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/XMLTagInfo.java
===================================================================
--- /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/XMLTagInfo.java	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/XMLTagInfo.java	(revision 14757)
@@ -0,0 +1,62 @@
+/**********************************************************************
+ *
+ * XMLTagInfo.java 
+ *
+ * Copyright 2006 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+package org.greenstone.LuceneWrapper;
+
+
+import org.xml.sax.Attributes;
+
+/** XMLTagInfo
+ * contains any methods that are specific to what kind of XML you are working on
+ */
+
+public class XMLTagInfo {
+
+    public static boolean isDocumentLevel(Attributes atts) 
+    {
+	boolean is_doc_level = false;
+	String id = atts.getValue("gs2:id");
+	if (id!=null) {
+	    is_doc_level = true;
+	}
+	return is_doc_level;
+    }
+
+    public static boolean isIndexable(Attributes atts) 
+    {
+	boolean is_indexable = false;
+
+	String index = atts.getValue("index");
+	if (index!=null) {
+	    if (index.equals("1")) {
+		is_indexable = true;
+	    }
+	}
+	return is_indexable;
+    }
+
+    
+}
Index: /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/lib/lucene-license.txt
===================================================================
--- /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/lib/lucene-license.txt	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/src/org/greenstone/LuceneWrapper/lib/lucene-license.txt	(revision 14757)
@@ -0,0 +1,204 @@
+Lucene v 1.4.1 is licensed under the Apache Software License 2.0
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
Index: /indexers/branches/3.03a/lucene-gs/winMake.bat
===================================================================
--- /indexers/branches/3.03a/lucene-gs/winMake.bat	(revision 14757)
+++ /indexers/branches/3.03a/lucene-gs/winMake.bat	(revision 14757)
@@ -0,0 +1,50 @@
+@echo off
+
+set LUCENEHOME=.
+
+rem ---- Where to put class files ----
+set JAVACLASSDIR=classes
+
+rem ---- Name and location of java programs ----
+set JAVAC="%JAVA_HOME%\bin\javac"
+set JAVAH="%JAVA_HOME%\bin\javah"
+set JAVA="%JAVA_HOME%\bin\java"
+set JAVADOC="%JAVA_HOME%\bin\javadoc"
+set JAR="%JAVA_HOME%\bin\jar"
+
+set JAVACOPTIONS=-deprecation -g -O
+
+set LUCENE_JAR=.\lib\lucene-core-2.0.0.jar
+set MYCLASSPATH=%LUCENE_JAR%;%JAVACLASSDIR%
+
+
+if ""%1"" == """" goto all
+if ""%1"" == ""all"" goto all
+if ""%1"" == ""install"" goto install
+if ""%1"" == ""clean"" goto clean
+
+:unknown
+	echo Error: Unrecognized argument %1.
+	goto done
+
+:all
+	if not exist %JAVACLASSDIR% mkdir %JAVACLASSDIR%
+	echo Compiling Greenstone Lucene Java classes ...
+	%JAVAC% -d %JAVACLASSDIR% -classpath %MYCLASSPATH% %JAVACOPTIONS% -sourcepath src src\org\greenstone\LuceneWrapper\*.java
+	cd %JAVACLASSDIR%
+	%JAR% xf ..\%LUCENE_JAR%
+	cd ..
+	%JAR% cf LuceneWrapper.jar -C %JAVACLASSDIR% .
+	goto done
+
+:install
+	goto done
+
+:clean
+	echo Cleaning up Greenstone Lucene ...
+	if exist %JAVACLASSDIR% rmdir /S /Q %JAVACLASSDIR%
+        if exist LuceneWrapper.jar del LuceneWrapper.jar
+	goto done 
+
+:done
+
Index: /indexers/branches/3.03a/mg/COPYING
===================================================================
--- /indexers/branches/3.03a/mg/COPYING	(revision 14757)
+++ /indexers/branches/3.03a/mg/COPYING	(revision 14757)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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 of the License, 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 program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: /indexers/branches/3.03a/mg/INSTALL
===================================================================
--- /indexers/branches/3.03a/mg/INSTALL	(revision 14757)
+++ /indexers/branches/3.03a/mg/INSTALL	(revision 14757)
@@ -0,0 +1,176 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
Index: /indexers/branches/3.03a/mg/INSTALL.mg
===================================================================
--- /indexers/branches/3.03a/mg/INSTALL.mg	(revision 14757)
+++ /indexers/branches/3.03a/mg/INSTALL.mg	(revision 14757)
@@ -0,0 +1,38 @@
+                     BUILDING AND INSTALLATION OF MG
+                     ===============================
+ 
+This file explains how to build the mg system.
+ 
+(1) Follow the general GNU install instructions in the INSTALL file.
+    NOTE: this procedure has changed from version mg-1.1 which did
+    not use a GNU configure script.
+    e.g.
+      cd ~/mg-1.2
+      ./configure --prefix=`pwd`
+      make
+      make check
+      make install
+    Report portability problems to tes@kbs.citri.edu.au .
+ 
+(2) You will need to set the environment variable MGDATA which 
+    indicates where the mg data files will be created. You will also
+    need to create the directory you specify.
+ 
+    e.g.
+        setenv MGDATA ~/mgdata
+	mkdir ~/mgdata
+
+(4) You may also need to set the environment variable MGSAMPLE which
+    is used by mg_get and indicates where the sample data included
+    with this package is located.
+    If this is not specified it defaults to ``./SampleData''
+
+(4) Included with mg is an X11 interface to mgquery called xmg. 
+    Xmg is a ``wish'' script which uses the Tcl/Tk packages available
+    by anonymous ftp from allspice.berkeley.edu [128.32.150.27].
+ 
+(5) Another environment variable that you may wish to set is
+    MGIMAGEVIEWER, this variable sets the image viewer to be used
+    to display images. The image viewer must take the image from stdin.
+    If this is not specified it defaults to ``xv -''.
+ 
Index: /indexers/branches/3.03a/mg/MODIFICATIONS
===================================================================
--- /indexers/branches/3.03a/mg/MODIFICATIONS	(revision 14757)
+++ /indexers/branches/3.03a/mg/MODIFICATIONS	(revision 14757)
@@ -0,0 +1,1023 @@
+TITLE
+  Parsing of Long Words
+APPLICATION
+ mg-1, mg-2
+TYPE
+  bug
+REPORT
+  tim@cosc.canterbury.ac.nz - May 11th 1994
+FIX
+  tes@kbs.citri.edu.au - August 9th 1994
+CLAIM
+  Mg didn't handle long words properly; it crashed.
+PROBLEM
+  Invf passes calls PARSE_LONG_WORD [words.h] which uses a limit of
+  MAXLONGWORD on iterating thru the string and storing into 
+  a word. MAXLONGWORD = 8192.
+  However, mg strings generally store the length in the first
+  byte limiting them to 255 characters. The word which was passed
+  to PARSE_LONG_WORD was an allocated string of MAXSTEMLEN = 255,
+  which is as large as we should get anyway. Thus when accessing
+  a larger word than 255 chars, PARSE_LONG_WORD would allow it
+  (less than 8192) and would try storing beyond the array limit.
+SOLUTION
+  The author can't remember why PARSE_LONG_WORD was used and what
+  the significance of MAXLONGWORD = 8192 is.
+  So PARSE_LONG_WORD has been changed to PARSE_STEM_WORD which
+  uses MAXSTEMLEN as its limit.
+FILES
+ *   words.h
+ *   invf.pass1.c
+ *   invf.pass2.c
+ *   ivf.pass1.c
+ *   ivf.pass2.c
+ *   query.ranked.c
+*************************************************************
+TITLE
+  Use of Lovins stemmer
+APPLICATION
+  mg-1
+TYPE
+  improve
+REPORT
+  local - 1994
+FIX
+  linh@kbs.citri.edu.au - 1994
+CLAIM
+  Stemming was done naively.
+PROBLEM
+  Only a few types of words and their endings
+  were considered.
+SOLUTION
+  Replacement with a more elaborate "known" stemmer by Lovins.
+  The algorithm is described in:
+    J.B. Lovins, "Development of a Stemming Algorithm",
+    Mechanical Translation and Computational Linguistics, Vol 11,1968.
+FILES
+ *   stem.c
+ *   stem.h
+*************************************************************
+TITLE
+  Different term parsing
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  tes@kbs.citri.edu.au - 23 Aug 1994
+FIX
+  tes@kbs.citri.edu.au - 23 Aug 1994
+CLAIM
+  Boolean queries did not extract words/terms using the
+  same method as is done at inverted-file creation and
+  as is used for rank query parsing.
+PROBLEM
+  The hand-written lex. analyser, query_lex, which is called by
+  the boolean query parser was not calling a common
+  word-extraction routine as used by the rest of mg. 
+  This would be ok if the code did the same things - but they didn't.
+  Query_lex, for instance, did NOT place any limit on the
+  number of digits in a term.
+  Of even more concern, it would allow arbitrary sized words
+  although it used Pascal style strings which store the length
+  in the first byte and can therefore only be 255 characters in length.
+SOLUTION
+  Query_lex in "query.bool.y", was modified to call the routine
+  PARSE_STEM_WORD which is also used by text-inversion routines and
+  ranking query routines.
+  Now all terms are extracted by the same routine.
+  To do this, the end of the line buffer had to be noted as
+  PARSE_STEM_WORD requires a pointer to the end - which is the
+  safe thing to do (don't want to run over the end).
+  This meant I had to find the length of the query line buffer.
+  This was allocated in the file "read_line.c" by the routine,
+  "readline". Its size was the literal number 1024. 
+  This was changed to a constant and placed in "read_line.h".
+  The definition for PARSE_STEM_WORD can be found in "words.h".
+FILES
+ *   query.bool.y
+ *   query.bool.c (by bison)
+ *   read_line.c
+ *   read_line.h
+*************************************************************
+TITLE
+  Highlighting of query terms
+APPLICATION
+  mg-1
+TYPE
+  extend
+REPORT
+  tes@kbs.citri.edu.au - Aug 94
+FIX
+  tes@kbs.citri.edu.au - Sep 94
+CLAIM
+  Difficult to feel happy that the query-result returned is
+  satisfying the query - need to look hard to find the queried words.
+  Need to show words in results using some highlighting method.
+PROBLEM
+  No highlighting of query terms in results.
+SOLUTION
+  Mgquery was previously outputting the decompressed text to a pager
+  such as "less(1)" or "more(1)".
+  (Except when redirected or piped elsewhere :)
+  So what was needed was some sort of highlight pager that instead of
+  displaying the text would also use some means for highlighting the
+  stemmed query words. 
+  Two common forms of highlighting were chosen: underline and bolding.
+  These are supported by "less(1)" and possibly by "more(1)" by
+  using the backspace character.
+  A highlight pager will also need to know which words need to be
+  highlighted. Therefore, the code was modified to build up a
+  string of the stemmed query words for passing to the highlight pager.
+  Design Options:
+  ---------------
+    * Could do text filtering in mgquery before passing out to pager.
+      Instead I pipe to a separate process, the "hilite_words" pager,
+      which filters and pipes into less/more.
+    * Could do different highlighting or a combination.
+    * Could use a different structure for storing the query words other
+      than the hash-table I used.
+FILES
+ *   Makefile - to include hilite_words target
+ *   mg_hilite_words.c
+ *   mgquery.c
+ *   mgquery.1
+ *   query.bool.y
+ *   query.ranked.c
+ *   environment.c
+ *   environment.h
+ *   backend.h
+*************************************************************
+TITLE
+  Mg_compression_dict did premature free
+APPLICATION
+  mg-1
+TYPE
+  bug 
+REPORT
+  R.Sosic@cit.gu.edu.au - 23 Sep 94
+FIX
+  R.Sosic@cit.gu.edu.au - 23 Sep 94
+CLAIM
+  mg_compression_dict dumped core in 
+	file: mg_compression_dict.c
+	function: Write_data
+	line: int codelen = hd->clens[i];
+PROBLEM
+  Huffman data, hd, was freed *before* it was accessed again. 
+SOLUTION
+  The freeing of hd has been moved to after all accesses
+  (just before returning).
+FILES
+ *   mg_compression_dict.c
+*************************************************************
+TITLE
+  Boolean tree optimising rewrite
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  sosic@kurango.cit.gu.edu.au - 23 Sep 94
+FIX
+  tes@kbs.citri.edu.au - Oct 94
+CLAIM
+  "I am still getting core dump in "and" queries in mgquery, 
+   where the first word does not exist, but the second one does."
+PROBLEM
+  Having freed a particular node, it tried to refree it and 
+  access one of its fields.
+
+  I.e. code-fragment...
+
+       FreeNode(curr); /* where curr = CHILD(base) for 1st term in list */
+       FreeNodes(next);
+       FreeNodes(CHILD(base)); 
+              /* but CHILD(base) has already been freed above */
+              /* if the node was the first one in the list */
+
+SOLUTION
+  A number of things in the code seemed a bit dubious to me.
+  So I have rewritten the boolean optimising stage and abstracted out
+  the various stages - each file starts with "bool".
+  Boolean query optimising seems to be a tricky problem. 
+  It is not clear that putting an expression into a certain form will
+  actually simplify it and whether simplification means faster querying.
+  I have converted a given boolean expression into DNF 
+  (Disjunctive Normal Form).  "And not" nodes, which are readily apparent 
+  in DNF, are converted to "diff" nodes.  I have only applied the idempotency 
+  laws involving TRUE and FALSE, and not the ones requiring matching of 
+  expressions - it is a potentially more complicated problem.
+  The optimiser has been tested by playing with "bool_tester", and if you are
+  having a crash or problem in a boolean query it would be worth testing the
+  query on the "bool_tester." The token "*" stands for TRUE (or all documents) 
+  and the token "_" stands for FALSE (or no documents). This should show the 
+  expression before and after optimisation in an ascii tree bracketting format.
+FILES
+ *   bool_tree.c
+ *   bool_parser.y
+ *   bool_optimiser.c
+ *   bool_query.c 
+ *   bool_tester.c
+ *   term_lists.c
+*************************************************************
+TITLE
+  Mgtic pixel placement
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  Bruce McKenzie - bruce@cosc.canterbury.ac.nz (21st Oct 1994)
+FIX
+  singlis@cs.waikato.ac.nz
+CLAIM
+  mgtic crashed on certain files.
+PROBLEM
+  Placing pixels outside of bitmap.
+SOLUTION
+  Changed the putpixel routine to truncate at borders of the image.
+FILES
+ *   mgtic.c
+*************************************************************
+TITLE
+  Improved boolean tree optimising
+APPLICATION
+  mg-1
+TYPE
+  improve
+REPORT
+  tes@kbs.citri.edu.au - 12/Dec/94
+FIX
+  tes@kbs.citri.edu.au - 21/Dec/94, 14/Mar/95
+CLAIM
+  Optimising by conversion to DNF is not necessarily such
+  a good idea - can actually slow things down.
+PROBLEM
+  The distributive law used in converting to DNF
+  duplicates expressions.
+SOLUTION
+  Introduce a query environment variable, optimise_type = 0 | 1 | 2.
+  Type 0 does nothing to the parse tree. 
+  Type 2 does the DNF conversion.
+  Type 1 is the new default and does the following...
+    Do simple tree rearrangement like flattening. 
+    Optimise for CNF queries.
+FILES
+ *   bool_query.c, .h
+ *   bool_optimiser.c
+ *   environment.c
+ *   invf_get.c
+ *   bool_tree.c, .h
+ *   bool_tester.c
+ *   lists.h
+*************************************************************
+TITLE
+  Similarity variants
+APPLICATION
+  mg-2
+TYPE
+  extend
+REPORT
+  jz@kbs.citri.edu.au/alistair - June 1994
+FIX
+  tes@kbs.citri.edu.au - July 1994 .. Feb 1995
+CLAIM
+  Can only use one type of similarity measure - the
+  standard cosine measure.
+PROBLEM
+  See CITRI/TR-95-3 for more details.
+  The standard measure can be broken up into 7 components.
+  The 7 components are  
+  Each one of these components has a number of alternatives.
+  The overall measure, S_qd, can also be altered.
+  Thus the particular similarity measure used can be specified
+  by an 8 dimensional vector.
+  What is desired is to be able to specify to mgquery an option
+  and a 8-digit string representing this vector (assuming that
+  any one alternative can have at most 9 (not using zero) variants).
+SOLUTION
+  The programs which had to be modified were:
+  (i) mgquery,
+  (ii) mg_weights_build.
+  The other mg programs in existence store the text, indexing info,
+  and the basic statistics such as N, n, ft, fdt.  
+  Other programs which had to be created were:
+  (i) mg_fmd_build,
+  (ii) mg_wt_build.
+  Mg_fmd_build will create the file to store the f_md statistic, 
+  where f_md is the largest (maximum) f_dt of any term in document, d.
+  Mg_wt_build will create the file to store the w_t primitive.
+  It only creates this for the w_t variants 6-9 which would require
+  extra passes of invf at query time if they were not stored here.
+  For details on similarity changes for mgquery and mg_weights_build,
+  please see the other modification entries.  
+FILES
+ *   mg_fmd_build.c
+ *   mg_wt_build.c
+ *   build_lib.c, build_lib.h
+*************************************************************
+TITLE
+  Similarity variants for mgquery
+APPLICATION
+  mg-2
+TYPE
+  extend
+REPORT
+  jz@kbs.citri.edu.au/alistair - June 1994
+FIX
+  tes@kbs.citri.edu.au - July 1994 .. Feb 1995
+CLAIM
+  "mgquery" needs to be altered to allow modification of
+  the similarity measure. 
+PROBLEM
+  See CITRI/TR-95-3 for more details.
+SOLUTION
+
+  Most of the similarity measures, Sqd, are of the 
+  form:   Aqd
+         -----
+          Bqd
+  where Bqd is an expression involving Wd and possibly Wq,
+  where Aqd is a sum over the common document/query terms
+  of w_qt and w_dt.
+  Building of Aqd
+  ===============
+  The calculation of Aqd is done in the file build_Aqd.c .
+  The functions for doing this used to be in the file invf_get.c .
+  Build_Aqd.c contains 4 different functions for building Aqd, each
+  of them building a different data structure:
+    (i) Array, (ii) Splay Tree, (iii) Hash Table, (iv) List Table.
+  Each of these routines seems to have been construction by modifications
+  to duplicated code. This is often the easiest way to construct variants
+  but is quite difficult to maintain consistency. 
+  As the aim of the exercise was to try out different sim. measures for
+  retrieval effectiveness, I only modified the code that constructed
+  an array. This routine was called "CosineDecode"; I changed it to
+  "build_Aqd_Array." This change reflects the fact that we are only 
+  calculating Aqd and this need not be used for the Cosine measure.
+  The other routines: "CosineDecodeSplay," "CosineDecodeHash," and
+  "CosineDecodeList" have been left unaltered - they need to be updated
+  in the future which would be best be done by abstracting out common code.
+  By the stage of building Aqd, the query terms have been looked up in
+  the inverted file dictionary and put into a list.
+  This list of common terms is traversed to lookup the corresponding
+  invf entries. Before the invf entry is processed, all query and term
+  relevant statistics and primitive quantities are calculated.
+  For example, fqt, ft, wt, rqt, wqt, Wq-partial-sum.
+  To save unnecessary calculations, there is a test for each value
+  to see whether it is needed e.g. "if (sim->variant_needs & NEEDS_wt) ... ".  
+  Aside: Variant Needs
+  --------------------
+  The idea behind the "variant_needs" field is to be able to have all
+  the code in the one place for each possible variant and this code would
+  get the information at the correct time/place only when it is needed.
+  The overhead is a "bit-and" and "test" for each component.
+  The important concern though, is that the "variant_needs" must be
+  accurate i.e. it should be carefully maintained.
+  Each possible need is stored as a bit position in a constant/macro
+  of the form "NEEDS_component" e.g. NEEDS_wt, NEEDS_nt 
+  More recently (Jan/95), I have found that the _need_ing of a component
+  may be relevant to a particular purpose, that is, it may be needed in
+  one situation and not another. This was the case for Wd. 
+  For rdt#6, Wd was needed, however, it might not be needed for Bqd, the
+  denominator of Sqd. So I changed from NEEDS_Wd to NEEDS_Wd_for_Sqd and
+  NEEDS_Wd_for_rdt. 
+  --------------------
+  To handle the different calculations of the variants, I wrote macros
+  based around a switch statement. All these macros are stored in the file
+  "similarity.h" . The point of doing this is to centralise most of the changes
+  and cut down on the number of files which have to be altered if a new
+  way of calculating a primitive is to be added.  
+  This is achieved by having a data record called, "Similarity_variant" whose
+  fields includes all the statistics and the similarity primitives.
+  So the standard procedure is to see if something is needed and if so, then
+  extract it from an mg file or calculate it using a macro - most of the
+  input and output to the macro is done via the "Similarity_variant" structure.
+  As well as calculating Aqd, it is also a convenient place to calculate Wq.
+  Previously, for Cosine measure, Wq was not needed because each Aqd was directly
+  divided by Wq and thus would not change the ordering. However, there are
+  some Sqd's which divide by a sum involving Wq and thus need Wq. 
+  Calculating Sqd and Ordering Documents
+  ====================================== 
+  The file query.ranked.c contains the code for calculating Sqd using the
+  approximate Wd in order to do the ranking of the documents.
+  The mg-1 file was cleaned up and modified slightly.
+  All the heap data structures and routines were taken out and placed in 
+  their own file, heap_weights.c/.h .
+  The major components/steps in the ranking process were abstracted into
+  macros and functions:
+    calc_MaxParas
+    insert_heap_entry
+    insert_greater_heap_entry
+    approx_guided_insert
+    fill_initial_heap
+    add_heap_remainders
+    change_heap_to_exact
+    add_remainder_exact_weights
+    Make_Exact_Root
+    build_doc_list
+  Aside: Zeroing of an Aqd Element
+  -------------------------
+  One interesting change concerned the use of zeroing out an Aqd element
+  so as to mark it as being used in the heap.
+  In the heap, the approx. Sqd is stored based on Aqd/Wd-approx.
+  Later when Aqd is required, it can be extracted from the approx. Sqd
+  by muliplication of Wd-approx i.e. Aqd = Sqd-approx * Wd-approx.
+  This, however, is not always possible for the various Sqd variants.
+  So, instead of zeroing out Aqd, I decided just to make it negative.
+  -------------------------
+  In some Sqd cases, Wd and Wd-approx. are not required. In which case,
+  step 3 which calls on "change_heap_to_exact", "Heap_Build" and
+  "add_remainder_exact_weights" is not required.
+ 
+FILES
+ *    build_Aqd.c
+ *    query.ranked.c
+ *    similarity.c/.h (in libmg)
+ *    heap_weights.c/.h
+ *    backend.c/.h
+*************************************************************
+TITLE
+  Similarity variants for mg_weights_build
+APPLICATION
+  mg-2
+TYPE
+  extend
+REPORT
+  jz@kbs.citri.edu.au/alistair - June 1994
+FIX
+  tes@kbs.citri.edu.au - July 1994 .. Feb 1995
+CLAIM
+  "mg_weights_build" needs to be altered to allow modification of
+  the similarity measure.
+PROBLEM
+  See CITRI/TR-95-3 for more details.
+SOLUTION
+  The weight files which are generated for a particular similarity
+  measure have their names extended by a suffix.
+  In the case of Wd#1 no weights are generated.
+  In the case of the standard cosine weights, Wd#2, a 3 letter suffix
+  is used to represent .
+  In the case of the other Wd variants, a one letter suffix is used
+  to represent which Wd variant it is.
+  In each case, the variant input (e.g. -q 22222222) should be the whole
+  similarity variant string and the relevant fields will be extracted out.
+  This is done for consistency in code and interface. 
+  The code is fairly similar to the original.
+  A dependency check has been added so that the dates of files and the
+  type of needed files is verified before building.
+  The dependencies include, invf dictionary, invf index, invf, fmd and wt files.
+  The major change here, is the possible use of fmd and/or wt files.
+  Later when I was having to write mg_fmd_build and mg_wt_build,
+  I decided to abstract out some macros, namely:
+    Get_ft, Get_ft_Ft, loop_invf_entry,
+  which were put into "build_lib.c" .
+  "loop_invf_entry" takes a function/macro name as a parameter and applies
+  it to the sim record (with field fdt set), current doc number and modifies
+  the return value. 
+FILES
+ *   mg_weights_build.c
+ *   build_lib.c
+*************************************************************
+TITLE
+  Mgstat with non-existent files
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  beebe@math.utah.edu - 16 May 1994
+FIX
+  tes@kbs.citri.edu.au - 10 Aug 1994
+CLAIM
+  NaNs and Infinites would be printed out by mgstat
+  if unable to open .text or .text.dict file.
+PROBLEM
+  The NaNs etc. were output in the column stating
+  the percentage size of the file compared with the
+  number of input bytes of the source text data.
+  If it couldn't read the .text file with its
+  header describing the number of source text bytes, then
+  in working out the percentage it would divide by zero.
+  Also due to some bad control flow, it wouldn't attempt to
+  open the .text file if it failed when opening 
+  the .text.dict file.
+SOLUTION
+  Only printout the percentage if we can read the header
+  from the .text file.
+  Read in text header irrespective of text dictionary file.
+FILES
+ *   mgstat.c
+*************************************************************
+TITLE
+  Boolean tree optimisations
+APPLICATION
+  mg-2
+TYPE
+  extend
+REPORT
+  (i) tes@kbs.citri.edu.au - 28/Sep/94
+  (ii) tes@kbs.citri.edu.au - 12/Dec/94
+FIX
+  (i) tes@kbs.citri.edu.au - 18/Oct/94
+  (ii) tes@kbs.citri.edu.au - 21/Dec/94
+CLAIM
+  The initial prompt for investigating the optimisation of
+  boolean queries is noted in the mg-1 mod14.txt. 
+  The code for optimising seemed to have a number of faults.
+PROBLEM
+  Boolean optimisation was unreliable.
+SOLUTION
+  Initially (in case (i) above, see mg-1/mod14.txt), I rewrote 
+  all the boolean tree and optimising code. I converted the boolean
+  expression into DNF. I did this after reading some notes about 
+  the steps involved in optimisation and they suggested standardising
+  in some normal form. I thought that DNF would be appropriate so that
+  all the terms are converted to be part of "and" expressions and be
+  evaluated quickly using skipping.
+  This, however, can suffer quite badly if the distributive law is
+  applied to often and the query expands in size. If there was
+  some sort of cacheing of invf entries, then it might not be so
+  bad otherwise there is quite an overhead on reading the same
+  invf entry more than once.
+
+  As it happens, CNF queries are reasonably common, where the user
+  queries with a conjunction of disjunctions of similes:
+    e.g. (car | automobile | vehicle) & (fast | quick | speedy)
+  This sort of CNF query expands a hell of a lot !
+  So after speaking with Justin who wanted to benchmark Atlas with Mg on
+  these sort of queries, I looked up the MG book for other ideas.
+
+  The method that I implemented was the following:
+
+  -----------------------------------------------------------------
+  Steps of tree modifications:
+    Gets literals by pushing the nots down, detecting T/F at leaves
+    and collapsing the tree by detecting  'and' of 'and's and 'or' of
+    'or's.
+    Next it looks at the or nodes and if all the children are terms
+    then it marks the or-node as such.
+    Finally, the or-term-nodes are sorted by using the sum of their
+    ft's for comparison.
+  Steps at query evaluation:
+    If it comes across an 'and' of 'or-terms' then the evaluation is
+    done noting the distributive law.
+    I.e. a & (b | c | d) = (a & b) | (a & c) | (a & d)
+    Assuming 'a' is the c-set of documents.
+    All of 'a' is tested against 'b' and matching ones are marked.
+    Next, all the unmarked members of 'a' are tested against 'c'.
+    Likewise for 'd'.
+    Now all the marked members of our c-set are kept.
+    When we do the testing, we can use the skipping in the invf entries.
+  -----------------------------------------------------------------
+
+
+  After doing this, I added the choice of which type of optimisation
+  the user wanted by adding query-environment-variable, "optimise_type".
+  Type 0 = no parse tree modification. 
+  Type 1 = Or-term recognition and CNF query evaluation optimisation. 
+  Type 2 = Put into DNF form. [generally not recommended]
+FILES
+ *   bool_tree.c
+ *   bool_parser.y
+ *   bool_optimiser.c
+ *   bool_query.c 
+ *   bool_tester.c
+ *   term_lists.c
+ *   query_env.c
+ *   invf_get.c [GetDocsOp]
+*************************************************************
+TITLE
+  nonexistent HOME bug  
+APPLICATION
+  mg-1, mg-2
+TYPE
+  bug 
+REPORT
+  cgn@totara.cs.waikato.ac.nz - 2/May/95
+FIX
+  tes@kbs.citri.edu.au - 2/May/95
+CLAIM
+"The big problem was that mgquery crashes when the HOME environment
+ variable is not set, which is the case when it is run by the www server."
+ [...] "I expect it happens when looking for $HOME/.mgrc."
+PROBLEM
+  The result of getenv("HOME")" was used directly in
+  a sprintf call. If the environment variable HOME
+  was not in existence then null would be used.
+  In some C libraries sprintf will convert the 0
+  string into the string "(null)" on others it will core dump.
+  (For example, Solaris seems to core dump, sunos 4 seems ok).
+SOLUTION
+  The result from getenv("HOME")" is tested before
+  being used.
+FILES
+ *   commands.c
+*************************************************************
+TITLE
+  mgquery collection name preference  
+APPLICATION
+  mg-1, mg-2
+TYPE
+  improve
+REPORT
+  cgn@totara.cs.waikato.ac.nz - 2/May/95
+FIX
+  tes@kbs.citri.edu.au - 4/May/95
+CLAIM
+ Surely something must override mquery's preference for ./bib. 
+ If MGDATA is set correctly, I think it should prefer that collection, 
+ and -d should definitely override it. 
+ I could always say -d . if I really wanted ./bib.
+PROBLEM
+Currently the priority is:
+1.  Check if ./name is a directory,
+     If so then use it as the collection directory.
+2.  Check if ./name.text is a file,
+     If so then use ./ as the collection directory.
+3.  Check if mgdir/name is a directory,
+     If so then use mgdir/name as the collection directory.
+4.  Otherwise,
+     Use mgdir/name as the database file prefix.
+     This would be the case if one used "-f alice/alice".
+     However, one would then not specify a final name argument
+     and we'd never get here. Go figure ???
+SOLUTION
+Moved step 3 to the top instead.
+FILES
+ *   mgquery.c [search_for_collection()]
+*************************************************************
+TITLE
+  Printout of query terms
+APPLICATION
+  mg-1, mg-2
+TYPE
+  extend
+REPORT
+  tes@kbs.citri.edu.au - April 95
+FIX
+  tes@kbs.citri.edu.au - April 95
+CLAIM
+  No easy way to find out the parsed and stemmed words
+  used in the query. Would like to know these words
+  so I can call a separate highlighting program to 
+  highlight these words.
+PROBLEM
+  No facility available.
+SOLUTION
+  A ".queryterms" mgquery command was added which lists
+  out the parsed/stemmed queryterms of the last query.
+FILES
+ *    commands.c (added CmdQueryTerms)
+*************************************************************
+TITLE
+  mg_getrc  
+APPLICATION
+  mg-1, mg-2
+TYPE
+  extend
+REPORT
+  bruce@cosc.canterbury.ac.nz - 2/May/95
+FIX
+   - 
+CLAIM
+  Repeated code had to be written for different named
+  gets but really the same type of parsing required.
+  E.g. one might want to use a standard method for inserting
+  ^Bs between paragraphs for different books. One doesn't
+  want to write duplicate code for each different named book,
+  rather note that each book should be filtered "book" style.
+PROBLEM
+  There was no way of abstracting out types of filters from
+  the name of an instance of a collection.
+SOLUTION
+  Allow information to be given with <name, type, files>.
+  This extra info can be provided in a mg_getrc file.
+  See man page for mg_get for details.
+FILES
+ *    mg_get.sh
+*************************************************************
+TITLE
+  TREC DocNo file   
+APPLICATION
+  mg-2
+TYPE
+  improve
+REPORT
+  tes@kbs.citri.edu.au - 26/May/95
+FIX
+  tes@kbs.citri.edu.au - 26/May/95
+CLAIM
+  MG has problems dealing with trec docnos for trec disk 3.
+PROBLEM
+  Trec DocNos file didn't have a wide enough field
+  to handle disk 3. 
+SOLUTION
+  Allow different width fields for file.
+  It is still fixed width but a number in the header
+  says how wide the field is.
+FILES
+ *   passes/mg.special.c
+ *   query/mgquery.c
+*************************************************************
+TITLE
+  Boolean optimiser #1 with `!'  
+APPLICATION
+  mg-1, mg-2
+TYPE
+  bug 
+REPORT
+  triffid@iconz.co.nz - 20/7/95
+FIX
+  tes@kbs.citri.edu.au - 27/7/95
+CLAIM
+  Complained about not-nodes. 
+  e.g. complained about "croquet & !hedgehog"
+PROBLEM
+  Boolean optimiser type#1 didn't convert
+  "and not"s into diff nodes.
+SOLUTION
+  Added code to convert '&!' to '-'.
+FILES
+ *   mg/bool_optimiser.c [mg-1]
+ *   query/bool_optimiser.c [mg-2]
+*************************************************************
+TITLE
+   Autoconfiguring mg-1  
+APPLICATION
+  mg-1
+TYPE
+  improve
+REPORT
+  many people - 94/95
+FIX
+  tes@kbs.citri.edu.au - Aug/95
+CLAIM
+  Portability is limited by setting up c-macros just for particular
+  machines and operating systems.
+  People had to make changes for HP, Next, Linux, Dec Alpha, ...
+PROBLEM
+  Porting was only targetting at the machines that the author had
+  access to.
+SOLUTION
+  Use GNU's autoconfigure program.
+  This allows checking of the systems features/characteristics.
+  It also allows some checking for specific machines/OS - although
+  I have not utilised this option.
+  I used GNU's tar-1.11.8 as an example to base my changes on.
+  I also used autoscan to generate the initial "configure.in".
+  The "Makefile.in"s were done very similarly to GNU tar's.
+  The "config.h" and "sysfuncs.h" files were scrapped and 
+  rewritten. The new "config.h" file is generated by the configure
+  script - it contains all the #define's for the system features.
+  The "sysfuncs.h" file wraps up a number of system headers. 
+  For example, some systems use , while some use ;
+  which one is included is decided in "sysfuncs.h".
+  I have also used GNU tar's use of ansi2knr in its Makefiles.
+  This should hopefully allow the package to work on a system with
+  only a K&R C compiler.
+  However, there are probably problems with what I have done.
+  I am concerned about <stdarg.h> for example.
+  I also noticed that "ansi2knr" require function definitions as
+  the GNU coding style recommends ie. with function name the first
+  string on the line. This prompted me to run all the package's code
+  thru GNU's indent.
+  Setting up the configure changes is difficult. It really seems
+  necessary to try the package out on many target machines so one
+  can know what is necessary.
+  A simple check target for the main Makefile has been written.
+  It is used to see if the installation is working - it does
+  not test much of the functionality of mg.
+  It does cmp's on data files and diff's on query/result files.
+FILES
+  Most of the files in the distribution.
+*************************************************************
+TITLE
+  Consistent use of stderr
+APPLICATION
+  mg-1
+TYPE
+  improve
+REPORT
+  beebe@math.utah.edu - 16 May 1994
+FIX
+  tes@kbs.citri.edu.au - 11 August 1994
+CLAIM
+  Inconsistent use of stdout/stderr in usage messages.
+PROBLEM
+  Sometimes used "printf" and sometimes used "fprintf(stderr"
+  in usage messages.
+SOLUTION
+  All should now use "fprintf(stderr" in usage messages.
+FILES
+ *   mg_compression_dict.c
+ *   mg_compression_dict.1
+ *   mg_fast_comp_dict.c
+ *   mg_fast_comp_dict.1
+ *   mg_invf_dict.c
+ *   mg_invf_dict.1
+ *   mg_invf_dump.c
+ *   mg_invf_dump.1
+ *   mg_invf_rebuild.c
+ *   mg_invf_rebuild.1
+ *   mg_perf_hash_build.c
+ *   mg_perf_hash_build.1
+ *   mg_text_estimate.c
+ *   mg_text_estimate.1
+ *   mg_weights_build.c
+ *   mg_weights_build.1
+*************************************************************
+TITLE
+  xmg bug
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  cgn@cpsc.ucalgary.ca - 22 April 1994
+FIX
+  cgn@cpsc.ucalgary.ca - 22 April 1994
+CLAIM
+  "Serious problem in xmg, which I fear occurs whenever a query
+   doesn't return anything."
+PROBLEM
+  ??
+SOLUTION
+  [xmg.sh 201] set rank 0
+FILES
+ *   xmg.sh
+*************************************************************
+TITLE
+  Unnecessary loading of text
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  tes@kbs.citri.edu.au - ?? August 1994
+FIX
+  tes@kbs.citri.edu.au - 12 August 1994
+CLAIM
+  Mg was loading and uncompressing text when the
+  query did not require the text.
+PROBLEM
+  There was no test for the query mode
+  before loading and uncompressing the text.
+SOLUTION
+  Only load/uncompress text if query mode
+  is for text, headers or silent(for timing).
+FILES
+ *   mgquery.c
+*************************************************************
+TITLE
+  Man page errors
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  beebe@math.utah.edu - 16 May 1994
+FIX
+  beebe@math.utah.edu - 16 May 1994
+CLAIM
+  Man page errors.
+PROBLEM
+  See below.
+SOLUTION
+ "The mg_make_fast_dict.1 file has been renamed mg_fast_comp_dict.1,
+  and all mg_make_fast_dict strings changed to mg_fast_comp_dict in all
+  man pages.
+  A large number of errors of spelling, typography, spacing, fonts,
+  grammar, omitted words, slang, punctuation, missing man page
+  cross-references, and man-page style have been corrected."
+FILES
+ *    mg_compression_dict.1
+ *    mg_fast_comp_dict.1
+ *    mg_get.1
+ *    mg_invf_dict.1
+ *    mg_invf_dump.1
+ *    mg_invf_rebuild.1
+ *    mg_passes.1
+ *    mg_perf_hash_build.1
+ *    mg_text_estimate.1
+ *    mg_weights_build.1
+ *    mgbilevel.1
+ *    mgbuild.1
+ *    mgdictlist.1
+ *    mgfelics.1
+ *    mgquery.1
+ *    mgstat.1
+ *    mgtic.1
+ *    mgticbuild.1
+ *    mgticdump.1
+ *    mgticprune.1
+ *    mgticstat.1
+ *    xmg.1
+*************************************************************
+TITLE
+  Man page overview
+APPLICATION
+  mg-1
+TYPE
+  extend
+REPORT
+  beebe@math.utah.edu - 
+FIX
+  tes@kbs.citri.edu.au - 17 August 1994
+CLAIM
+  "Write new mg.1 file to give a brief overview of mg, with samples
+   of how to use it.  Otherwise, users are likely to be completely
+   overwhelmed by the number of programs (about 20) which might need to
+   be used, when in reality, only 2 or 3 are likely to be run by end
+   users."
+SOLUTION
+  It was thought that mg.1, written by Nelson Beebe, was very useful
+  but a bit too comprehensive for an introduction.
+  Therefore, two man files, mgintro.1 and mgintro++.1 were written
+  with the basic stuff in mgintro.1 and slightly more advanced stuff
+  in mgintro++.1 . 
+FILES
+ *   mg.1
+ *   mgintro.1
+ *   mgintro++.1 
+*************************************************************
+TITLE
+  Parse errors not bus errors
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  tim@cosc.canterbury.ac.nz - 2 Jun 94
+FIX
+  tes@kbs.citri.edu.au - 19 Aug 94
+CLAIM
+  "These two queries 
+   (which I typed in before I knew what I was doing!!)
+      > The Queen of Hearts, she made some tarts
+      > "The Queen of Hearts" and "she made some tarts"
+      produced the following result:
+      mgquery : parse error
+      Bus error
+  "
+PROBLEM
+  What is expected to happen under boolean querying:
+    Query1:
+    > The Queen of Hearts, she made some tarts
+    will produce a parse error due to the comma which
+    is not a valid TERM.
+    Query2:
+    > "The Queen of Hearts" and "she made some tarts"
+    will store a post-processing string
+    of ''The Queen of Hearts" and "she made some tarts'' and
+    will have a main boolean query of the empty string.
+    This is because the postprocessing string takes in
+    everything between the first quote and the last one.
+    An empty string is illegal for the boolean grammar and
+    hence a parse error.
+  The problem stems from the fact that the processing of
+  the parse tree is carried out, even though we have a 
+  parse error. In the case of using an empty string to build
+  a parse tree, it is likely to leave the parse tree undefined.
+SOLUTION
+  As soon as we find out that there is a parse-error,
+  we abandon any processing of the parse tree.
+FILES
+ *   query.bool.y
+ *   query.bool.c (generated from query.bool.y)
+*************************************************************
+TITLE
+  Perfect hashing on small vocab
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  tes@kbs.citri.edu.au - July 1994
+FIX
+  alistair@cs.mu.oz.au - July 1994
+CLAIM
+  Mg could not handle small collections in the case
+  where there was only a small number of unique words.
+  The perfect hash function would report an error.
+PROBLEM
+  Rounding of the arithmetic during the calculation of the
+  parameters of the perfect hash function was resulting in a
+  combination of values such that the probability of a hash
+  function being found was very small. This led to the limit
+  on the generation loop being exceeded, and eventual
+  failure.
+SOLUTION
+  By using ceiling rather than floor when converting from a
+  floating point value to an integer parameter, the arithmetic
+  is now correct for all lexicon sizes, and the probability of
+  each iteration successfully generating a hash function is
+  sufficiently great that with _very_ high probability the
+  execution loop counter will not be exceeded unless there
+  genuinely is no hash function (for example, if the lexicon
+  contains two words the same there cannot be  a hash
+  function).
+FILES
+ *   perf_hash.c
+*************************************************************
Index: /indexers/branches/3.03a/mg/Makefile.in
===================================================================
--- /indexers/branches/3.03a/mg/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/mg/Makefile.in	(revision 14757)
@@ -0,0 +1,180 @@
+# Main Makefile for MG
+# Copyright (C) 1994, 1995 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ 
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+ 
+@SET_MAKE@
+SHELL = /bin/sh
+VPATH = @srcdir@
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+srcdir = @srcdir@
+ 
+
+CC = @CC@
+CFLAGS = @CFLAGS@ -fpic 
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@  
+TOUCH = echo timestamp >
+ 
+bindir = $(exec_prefix)/bin
+infodir = $(prefix)/info
+libexecdir = $(exec_prefix)/libexec
+ 
+MDEFINES = 
+#CC='$(CC)' CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' LIBS='$(LIBS)' \
+#prefix='$(prefix)' exec_prefix='$(exec_prefix)' \
+#bindir='$(bindir)' libexecdir='$(libexecdir)' \
+#infodir='$(infodir)' infodir='$(infodir)' libexecdir='$(libexecdir)'
+
+#SUBDIRS = lib src/text src/images src/scripts 
+SUBDIRS = lib src/text
+JAVADIRS = java/org/greenstone/mg 
+JNIDIRS = jni
+.SUFFIXES:
+
+all install uninstall execinstall execuninstall maninstall manuninstall: config.h
+	for subdir in $(SUBDIRS) $(JAVADIRS) $(JNIDIRS); do \
+	  echo making $@ in $$subdir; \
+	  (cd $$subdir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+	done
+
+nojava: 
+	for subdir in $(SUBDIRS); do \
+	  echo making $@ in $$subdir; \
+	  (cd $$subdir && $(MAKE) $(MDEFINES) all) || exit 1; \
+	done
+
+install-nojava: 
+	for subdir in $(SUBDIRS); do \
+	  echo making $@ in $$subdir; \
+	  (cd $$subdir && $(MAKE) $(MDEFINES) install) || exit 1; \
+	done
+
+javaonly:
+	for subdir in $(JAVADIRS); do \
+	  echo making $@ in $$subdir; \
+	  (cd $$subdir && $(MAKE) $(MDEFINES) all) || exit 1; \
+	done
+
+install-javaonly:
+	for subdir in $(JAVADIRS); do \
+	  echo making $@ in $$subdir; \
+	  (cd $$subdir && $(MAKE) $(MDEFINES) install) || exit 1; \
+	done
+
+
+check: all
+	echo making $@ in ./test directory
+	(cd ./test && $(MAKE) all) || exit 1
+	./test/testmg `pwd`
+
+mostlyclean: mostlyclean-recursive mostlyclean-local
+
+clean: clean-recursive clean-local
+
+distclean: distclean-recursive distclean-local
+
+maintainer-clean: maintainer-clean-recursive maintainer-clean-local
+	rm -f config.status
+
+mostlyclean-recursive clean-recursive distclean-recursive maintainer-clean-recursive:
+	for subdir in $(SUBDIRS) $(JAVADIRS) $(JNIDIRS); do \
+	  target=`echo $@ | sed 's/-recursive//'`; \
+	  echo making $$target in $$subdir; \
+	  (cd $$subdir && $(MAKE) $$target) || exit 1; \
+	done
+
+mostlyclean-local:
+
+clean-local: mostlyclean-local
+
+distclean-local: clean-local
+	rm -f Makefile stamp-h config.status config.h config.log
+
+maintainer-clean-local: distclean-local
+	@echo "This command is intended only for maintainers to use;"
+	@echo "rebuilding the deleted files may require special tools."
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+distdir = $(PACKAGE)-$(VERSION)
+
+distname = $(distdir)
+
+DISTFILES = \
+INSTALL.mg INSTALL README README.port COPYING MODIFICATIONS about_mg.html \
+Makefile.in acconfig.h aclocal.m4 configure.in install-sh mkinstalldirs \
+config.guess config.sub \
+config.h.in configure stamp-h.in sysfuncs.h
+
+dist: $(DISTFILES)
+#-----------------------------------------------------------------
+	#create distribution directory
+	-rm -rf $(distdir)
+	mkdir $(distdir)
+#
+	#link in local distribution files
+	ln $(DISTFILES) $(distdir)
+#
+	#link in SampleData
+	mkdir $(distdir)/SampleData
+	(cd SampleData; $(MAKE) "distdir=../$(distdir)/SampleData" dist)
+	# link in davinci stuff
+	mkdir $(distdir)/SampleData/davinci
+	(cd SampleData/davinci; \
+	$(MAKE) "distdir=../../$(distdir)/SampleData/davinci" dist)
+	# link in bible stuff
+	mkdir $(distdir)/SampleData/bible
+	(cd SampleData/bible; \
+	$(MAKE) "distdir=../../$(distdir)/SampleData/bible" dist)
+#
+	#link in tests
+	mkdir $(distdir)/test
+	(cd test; $(MAKE) "distdir=../$(distdir)/test" dist)
+#
+	#link in docs directory
+	mkdir $(distdir)/docs
+	(cd docs; $(MAKE) "distdir=../$(distdir)/docs" dist)
+#
+	#link in lib directory
+	mkdir $(distdir)/lib
+	(cd lib; $(MAKE) "distdir=../$(distdir)/lib" dist)
+#
+	#link in src distribution files
+	mkdir $(distdir)/src
+	for dir in src/text src/images src/scripts; do \
+	  echo makeing $@ in $$dir ; \
+	  mkdir $(distdir)/$$dir; \
+	  (cd $$dir; $(MAKE) "distdir=../../$(distdir)/$$dir" $@) ; \
+	done
+#
+	# archive and compress
+	tar -chf - $(distdir) | gzip -9 > $(distname).tar.gz
+	tar -chf - $(distdir) | compress > $(distname).tar.Z
+#
+	# cleanup
+	rm -rf $(distdir)
+#-----------------------------------------------------------------
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /indexers/branches/3.03a/mg/README
===================================================================
--- /indexers/branches/3.03a/mg/README	(revision 14757)
+++ /indexers/branches/3.03a/mg/README	(revision 14757)
@@ -0,0 +1,156 @@
+                 MG INFORMATION RETRIEVAL SYSTEM
+                 ===============================
+
+The MG system is a suite of programs for compressing and indexing text
+and images. Most of the functionality implemented in the suite is as
+described in the book ``Managing Gigabytes:  Compressing and Indexing
+Documents and Images'', I.H. Witten, A.  Moffat, and T.C. Bell; Van
+Nostrand Reinhold, New York, 1994, ISBN 0-442-01863-0; US $54.95; call
+1 (800) 544-0550 to order.
+
+These features include:
+
+-- text compression using a Huffman-coded semi-static word-based scheme
+-- two-level context-based compression of bi-level images
+-- FELICS lossless compression of gray-scale images
+-- combined lossy/lossless compression for textual images
+-- indexing algorithms for large volumes of text in limited main memory
+-- index compression
+-- a retrieval system that processes Boolean and ranked queries
+-- an X windows interface to the retrieval system
+
+As one example, a collection of 2 Gb of text (1,700,000 documents) can
+be indexed (on a SPARC 10 Model 512) in about four hours and compressed
+in a further four hours to make a database that in total occupies less
+than 800 Mb, or 40% of the original size. This includes a full index to
+every word and number in the original text. Boolean queries such as
+``managing AND gigabytes'' run in a few seconds, and ranked queries of
+30--50 terms are evaluated in 10--30 seconds.
+
+Details of these methods and further performance results appear in the
+MG book.
+
+The MG system comes with ABSOLUTELY NO WARRANTY; for details see the
+file COPYING.
+
+Instructions on how to build and install mg are in the file INSTALL.
+
+
+** CHANGES FROM BOOK
+
+For copyright reasons the stemmer used in this distribution of MG is
+not the same as the one illustrated in Figure 3.8 on page 108 of the MG
+book.  This means that the numbers generated by the command ``mgstat
+alice'' will not match those numbers in Figure A.1 on page 394.
+Another stemmer was initially written as a simple stopgap for version
+1.0.  That stemmer has been replaced by a stemmer based on the Lovin's
+stemming algorithm for mg-1.1.
+
+The output format of ``mgstat'' has changed since Figure A.1 (page 394)
+was prepared. The same information is displayed but formatted
+differently.
+
+** MG VERSIONS
+
+The current version is mg-1.2, September 1995. The changes from earlier 
+versions are listed in the file MODIFICATIONS. This can be accessed
+with mg by building a database using ``mgbuild mods'' and can also be
+accessed from the mg web page (see below). 
+
+The mg-1.2 extensions include:
+
+-- Source modifications for use of GNU's autoconf.
+
+The mg-1.1 extensions include:
+
+-- A new highlighting mode.
+   The output mode ``hilite'' will highlight the query terms in the
+   retrieved text documents. The variable ``hilite_style'' can be set
+   to ``bold'' or ``underline''. It works best with the pager
+   ``less''.  A .mgrc to use would include:
+	.set pager less
+	.set mode hilite
+	.set hilite_style bold
+
+-- A web site containing manual pages, documentation, and a
+   mgquery demo page (utilising cgi scripts). 
+   See: http://www.kbs.citri.edu.au/mg
+   One of these pages ``about_mg.html'' is included in this
+   distribution.
+
+-- A revised mg_get script which uses a .mg_getrc file to map
+   specific collection names to filter types.  (Modifications by Bruce
+   McKenzie). See mg_get.1 for more details.
+
+-- Code to perform merging of existing databases. This code
+   was created by Shane Hudson and is documented in the mgmerge.README
+   file found in the docs subdirectory.  This code is maintained by
+   Shane Hudson (shane@cosc.canterbury.ac.nz).
+
+-- Revised man pages, including some new entries (thanks to Nelson
+   Beebe). See mg.1, mgintro.1, mgintro++.1.
+
+-- A real (rather than toy) stemmer.
+
+** PORTABILITY
+
+Please refer to "README.port".
+
+** CREDITS
+ 
+The MG development is largely the result of research collaboration
+between:
+
+        Tim C. Bell            <tim@cosc.canterbury.ac.nz>
+        Ian Witten             <ihw@cs.waikato.ac.nz>
+        Alistair Moffat        <alistair@cs.mu.oz.au>
+        Justin Zobel           <jz@cs.rmit.oz.au>
+
+The bulk of the programming work has been carried out by:
+
+        Stuart Inglis          <singlis@cs.waikato.ac.nz>
+        Craig Nevill-Manning   <cgn@cs.waikato.ac.nz>
+        Neil Sharman           <neil@kbs.citri.edu.au>
+        Tim Shimmin            <tes@kbs.citri.edu.au>
+
+In addition to these, the following people have contributed to the
+development of the MG software:
+
+        Lachlan Andrew         <lha@kbs.citri.edu.au>
+        Gary Eddy              <gary@cs.mu.oz.au>
+        Hugh Emberson          <hugh@cosc.canterbury.ac.nz>
+        Kerry Guise            <kerry@cs.waikato.ac.nz>
+	Shane Hudson           <shane@cosc.canterbury.ac.nz>
+        Linh Huynh             <linh@kbs.citri.edu.au>
+        Bohdan S. Majewski     <bohdan@cs.uq.oz.au>
+        Bruce McKenzie         <bruce@cosc.canterbury.ac.nz>
+
+In addition to these, the following people have submitted bug reports
+and suggestions/fixes:
+
+        Rex Barzee             <rex@python.cs.byu.edu>
+        Tim A.H. Bell          <bhat@cs.mu.oz.au>
+        Tim C. Bell            <tim@cosc.canterbury.ac.nz>
+        Nelson Beebe           <beebe@math.utah.edu>
+	Rodney Brown           <RBrown@cmutual.com.au>
+        Rok Sosic              <R.Sosic@cit.gu.edu.au>
+        Carl Staelin           <staelin@cello.hpl.hp.com>
+
+Development of the MG system was supported by the Australian Research
+Council; the Universities of Melbourne, Waikato, Canterbury, and
+Calgary; RMIT; and the Collaborative Information Technology Research
+Institute (Melbourne).
+
+** BUG REPORTS
+
+Send bug reports to <alistair@cs.mu.oz.au> and <tes@kbs.citri.edu.au>.
+Back-traces from gdb are always welcome but not mandatory :-)
+
+** FURTHER READING
+
+A bibliography of MG related research work appears in the files
+MG.Bibliography.ps and MG.Bibliography.bib on the ftp site and
+is accessible through the Web page.
+
+
+
Index: /indexers/branches/3.03a/mg/README.port
===================================================================
--- /indexers/branches/3.03a/mg/README.port	(revision 14757)
+++ /indexers/branches/3.03a/mg/README.port	(revision 14757)
@@ -0,0 +1,125 @@
+P O R T A B I L I T Y
+=====================
+
+The main development of MG is done under Solaris on a Sun sparc.
+However, we would also like MG to be reasonably portable.
+Therefore, MG-1.2 now uses a configure stript generated by GNU's autoconf.
+Below, is a list of the machines that the s/ware has been ported to. 
+Most only need the configure script and some require manual modifications 
+mentioned in the "Problems" field.
+
+------------------------------------------------------------------------- 
+** Systems which have successfully been built.
+
+Tester:		tes@kbs.citri.edu.au
+Date:
+Machine:	Sun
+System:		SunOS 4.1.2 8 sun4c
+Compiler:	gcc version 2.3.3
+Problems:	none
+
+Tester:		tes@kbs.citri.edu.au
+Date:
+Machine:	Sun
+System:		SunOS 4.1.2_DB 14 sun4c
+Compiler:	gcc version 2.3.3
+Problems:	none
+
+Tester:		tes@kbs.citri.edu.au
+Date:
+Machine:	Sun
+System:		SunOS 4.1.3_U1 1 sun4c
+Compiler:	gcc version 2.5.7
+Problems:	none
+
+Tester:		tes@kbs.citri.edu.au
+Date:
+Machine:	Sun
+System:		SunOS 5.3 Generic_Patch sun4m sparc
+Compiler:	gcc version 2.4.3
+Problems:	none
+
+Tester:		tes@kbs.citri.edu.au
+Date:
+Machine:	Silicon Graphics
+System:		IRIX 5.2 02282014 IP7
+Compiler:	gcc version 2.6.3
+Problems:	none
+
+Tester:		tes@kbs.citri.edu.au
+Date:
+Machine:	Sun
+System:		SunOS 5.4 Generic_101945-27 sun4c sparc
+Compiler:	cc: SC3.0.1 13 Jul 1994
+Problems:	none
+
+Tester:		RBrown@cmutual.com.au
+Date:
+Machine:
+System:		SCO 3.2v4.1
+Compiler:	gcc 2.6.1
+Problems:	requires RANLIB=true, use of tcsh
+
+Tester:		RBrown@cmutual.com.au
+Date:
+Machine:	HP
+System:		HP-UX A.09.04 D 9000/837 415303291 64-user license
+Compiler:	HP92453-01 A.09.73 HP C Compiler
+Problems:
+
+Tester:		RBrown@cmutual.com.au
+Date:
+Machine:	Data General
+System:		dgux 5.4R3.00 generic AViiON mc88110 
+Compiler:	gcc 2.4.5 (dg supplied)
+Problems:	none
+
+Tester:		RBrown@cmutual.com.au
+Date:
+Machine:	Pyramid MIPS R3000 box
+System:		
+Compiler:	cc (vendor supplied)
+Problems:	none
+
+Tester:		RBrown@cmutual.com.au
+Date:
+Machine:	IBM RS6000
+System:		AIX 3.2
+Compiler:	AIX XL C Compiler/6000
+Problems:	none
+
+Tester:		RBrown@cmutual.com.au
+Date:
+Machine:	Linux 1.2.9
+System:		
+Compiler:	gcc 2.6.3
+Problems:	none
+
+-----------------------------------------------------------------------
+** Systems which have NOT successfully been built.
+
+Tester:		RBrown@cmutual.com.au, 
+		Lloyd.Parkes@vuw.ac.nz
+Date:		Oct, Nov, 1995
+Machine:	Dec Alpha OSF/1
+System:
+Compiler:	cc
+Problems: 	Many - see below.
+
+* Problems with Dec Alpha
+  - 64 bit length longs as opposed to 32 bit longs.
+  - Lloyd.Parkes@vuw.ac.nz says that there is some bit encoding problems 
+    but the decoding seems to work.
+  - RBrown@cmutual.com.au says that it will compile but will core dump
+    when  building the test database.
+  - tes.kbs.citri.edu.au says that he needs to look into the repercussions
+    of 64 bit longs, however, he does not have access to such a machine.
+		
+-----------------------------------------------------------------------
+** Other systems. 
+
+Systems other than the above may have installation problems.
+If this is the case, please send me (tes@kbs.citri.edu.au) a log of the output
+and I will modify the configuration files in an effort to fix the problems.
+
+-----------------------------------------------------------------------
Index: /indexers/branches/3.03a/mg/SampleData/MODIFICATIONS
===================================================================
--- /indexers/branches/3.03a/mg/SampleData/MODIFICATIONS	(revision 14757)
+++ /indexers/branches/3.03a/mg/SampleData/MODIFICATIONS	(revision 14757)
@@ -0,0 +1,664 @@
+TITLE
+  Parsing of Long Words
+APPLICATION
+ mg-1, mg-2
+TYPE
+  bug
+REPORT
+  tim@cosc.canterbury.ac.nz - May 11th 1994
+FIX
+  tes@kbs.citri.edu.au - August 9th 1994
+CLAIM
+  Mg didn't handle long words properly; it crashed.
+PROBLEM
+  Invf passes calls PARSE_LONG_WORD [words.h] which uses a limit of
+  MAXLONGWORD on iterating thru the string and storing into 
+  a word. MAXLONGWORD = 8192.
+  However, mg strings generally store the length in the first
+  byte limiting them to 255 characters. The word which was passed
+  to PARSE_LONG_WORD was an allocated string of MAXSTEMLEN = 255,
+  which is as large as we should get anyway. Thus when accessing
+  a larger word than 255 chars, PARSE_LONG_WORD would allow it
+  (less than 8192) and would try storing beyond the array limit.
+SOLUTION
+  The author can't remember why PARSE_LONG_WORD was used and what
+  the significance of MAXLONGWORD = 8192 is.
+  So PARSE_LONG_WORD has been changed to PARSE_STEM_WORD which
+  uses MAXSTEMLEN as its limit.
+FILES
+ *   words.h
+ *   invf.pass1.c
+ *   invf.pass2.c
+ *   ivf.pass1.c
+ *   ivf.pass2.c
+ *   query.ranked.c
+*************************************************************
+TITLE
+  Use of Lovins stemmer
+APPLICATION
+  mg-1
+TYPE
+  improve
+REPORT
+  local - 1994
+FIX
+  linh@kbs.citri.edu.au - 1994
+CLAIM
+  Stemming was done naively.
+PROBLEM
+  Only a few types of words and their endings
+  were considered.
+SOLUTION
+  Replacement with a more elaborate "known" stemmer by Lovins.
+  The algorithm is described in:
+    J.B. Lovins, "Development of a Stemming Algorithm",
+    Mechanical Translation and Computational Linguistics, Vol 11,1968.
+FILES
+ *   stem.c
+ *   stem.h
+*************************************************************
+TITLE
+  Different term parsing
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  tes@kbs.citri.edu.au - 23 Aug 1994
+FIX
+  tes@kbs.citri.edu.au - 23 Aug 1994
+CLAIM
+  Boolean queries did not extract words/terms using the
+  same method as is done at inverted-file creation and
+  as is used for rank query parsing.
+PROBLEM
+  The hand-written lex. analyser, query_lex, which is called by
+  the boolean query parser was not calling a common
+  word-extraction routine as used by the rest of mg. 
+  This would be ok if the code did the same things - but they didn't.
+  Query_lex, for instance, did NOT place any limit on the
+  number of digits in a term.
+  Of even more concern, it would allow arbitrary sized words
+  although it used Pascal style strings which store the length
+  in the first byte and can therefore only be 255 characters in length.
+SOLUTION
+  Query_lex in "query.bool.y", was modified to call the routine
+  PARSE_STEM_WORD which is also used by text-inversion routines and
+  ranking query routines.
+  Now all terms are extracted by the same routine.
+  To do this, the end of the line buffer had to be noted as
+  PARSE_STEM_WORD requires a pointer to the end - which is the
+  safe thing to do (don't want to run over the end).
+  This meant I had to find the length of the query line buffer.
+  This was allocated in the file "read_line.c" by the routine,
+  "readline". Its size was the literal number 1024. 
+  This was changed to a constant and placed in "read_line.h".
+  The definition for PARSE_STEM_WORD can be found in "words.h".
+FILES
+ *   query.bool.y
+ *   query.bool.c (by bison)
+ *   read_line.c
+ *   read_line.h
+*************************************************************
+TITLE
+  Highlighting of query terms
+APPLICATION
+  mg-1
+TYPE
+  extend
+REPORT
+  tes@kbs.citri.edu.au - Aug 94
+FIX
+  tes@kbs.citri.edu.au - Sep 94
+CLAIM
+  Difficult to feel happy that the query-result returned is
+  satisfying the query - need to look hard to find the queried words.
+  Need to show words in results using some highlighting method.
+PROBLEM
+  No highlighting of query terms in results.
+SOLUTION
+  Mgquery was previously outputting the decompressed text to a pager
+  such as "less(1)" or "more(1)".
+  (Except when redirected or piped elsewhere :)
+  So what was needed was some sort of highlight pager that instead of
+  displaying the text would also use some means for highlighting the
+  stemmed query words. 
+  Two common forms of highlighting were chosen: underline and bolding.
+  These are supported by "less(1)" and possibly by "more(1)" by
+  using the backspace character.
+  A highlight pager will also need to know which words need to be
+  highlighted. Therefore, the code was modified to build up a
+  string of the stemmed query words for passing to the highlight pager.
+  Design Options:
+  ---------------
+    * Could do text filtering in mgquery before passing out to pager.
+      Instead I pipe to a separate process, the "hilite_words" pager,
+      which filters and pipes into less/more.
+    * Could do different highlighting or a combination.
+    * Could use a different structure for storing the query words other
+      than the hash-table I used.
+FILES
+ *   Makefile - to include hilite_words target
+ *   mg_hilite_words.c
+ *   mgquery.c
+ *   mgquery.1
+ *   query.bool.y
+ *   query.ranked.c
+ *   environment.c
+ *   environment.h
+ *   backend.h
+*************************************************************
+TITLE
+  Mg_compression_dict did premature free
+APPLICATION
+  mg-1
+TYPE
+  bug 
+REPORT
+  R.Sosic@cit.gu.edu.au - 23 Sep 94
+FIX
+  R.Sosic@cit.gu.edu.au - 23 Sep 94
+CLAIM
+  mg_compression_dict dumped core in 
+	file: mg_compression_dict.c
+	function: Write_data
+	line: int codelen = hd->clens[i];
+PROBLEM
+  Huffman data, hd, was freed *before* it was accessed again. 
+SOLUTION
+  The freeing of hd has been moved to after all accesses
+  (just before returning).
+FILES
+ *   mg_compression_dict.c
+*************************************************************
+TITLE
+  Boolean tree optimising rewrite
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  sosic@kurango.cit.gu.edu.au - 23 Sep 94
+FIX
+  tes@kbs.citri.edu.au - Oct 94
+CLAIM
+  "I am still getting core dump in "and" queries in mgquery, 
+   where the first word does not exist, but the second one does."
+PROBLEM
+  Having freed a particular node, it tried to refree it and 
+  access one of its fields.
+
+  I.e. code-fragment...
+
+       FreeNode(curr); /* where curr = CHILD(base) for 1st term in list */
+       FreeNodes(next);
+       FreeNodes(CHILD(base)); 
+              /* but CHILD(base) has already been freed above */
+              /* if the node was the first one in the list */
+
+SOLUTION
+  A number of things in the code seemed a bit dubious to me.
+  So I have rewritten the boolean optimising stage and abstracted out
+  the various stages - each file starts with "bool".
+  Boolean query optimising seems to be a tricky problem. 
+  It is not clear that putting an expression into a certain form will
+  actually simplify it and whether simplification means faster querying.
+  I have converted a given boolean expression into DNF 
+  (Disjunctive Normal Form).  "And not" nodes, which are readily apparent 
+  in DNF, are converted to "diff" nodes.  I have only applied the idempotency 
+  laws involving TRUE and FALSE, and not the ones requiring matching of 
+  expressions - it is a potentially more complicated problem.
+  The optimiser has been tested by playing with "bool_tester", and if you are
+  having a crash or problem in a boolean query it would be worth testing the
+  query on the "bool_tester." The token "*" stands for TRUE (or all documents) 
+  and the token "_" stands for FALSE (or no documents). This should show the 
+  expression before and after optimisation in an ascii tree bracketting format.
+FILES
+ *   bool_tree.c
+ *   bool_parser.y
+ *   bool_optimiser.c
+ *   bool_query.c 
+ *   bool_tester.c
+ *   term_lists.c
+*************************************************************
+TITLE
+  Mgtic pixel placement
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  Bruce McKenzie - bruce@cosc.canterbury.ac.nz (21st Oct 1994)
+FIX
+  singlis@cs.waikato.ac.nz
+CLAIM
+  mgtic crashed on certain files.
+PROBLEM
+  Placing pixels outside of bitmap.
+SOLUTION
+  Changed the putpixel routine to truncate at borders of the image.
+FILES
+ *   mgtic.c
+*************************************************************
+TITLE
+  Improved boolean tree optimising
+APPLICATION
+  mg-1
+TYPE
+  improve
+REPORT
+  tes@kbs.citri.edu.au - 12/Dec/94
+FIX
+  tes@kbs.citri.edu.au - 21/Dec/94, 14/Mar/95
+CLAIM
+  Optimising by conversion to DNF is not necessarily such
+  a good idea - can actually slow things down.
+PROBLEM
+  The distributive law used in converting to DNF
+  duplicates expressions.
+SOLUTION
+  Introduce a query environment variable, optimise_type = 0 | 1 | 2.
+  Type 0 does nothing to the parse tree. 
+  Type 2 does the DNF conversion.
+  Type 1 is the new default and does the following...
+    Do simple tree rearrangement like flattening. 
+    Optimise for CNF queries.
+FILES
+ *   bool_query.c, .h
+ *   bool_optimiser.c
+ *   environment.c
+ *   invf_get.c
+ *   bool_tree.c, .h
+ *   bool_tester.c
+ *   lists.h
+*************************************************************
+TITLE
+  Mgstat with non-existent files
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  beebe@math.utah.edu - 16 May 1994
+FIX
+  tes@kbs.citri.edu.au - 10 Aug 1994
+CLAIM
+  NaNs and Infinites would be printed out by mgstat
+  if unable to open .text or .text.dict file.
+PROBLEM
+  The NaNs etc. were output in the column stating
+  the percentage size of the file compared with the
+  number of input bytes of the source text data.
+  If it couldn't read the .text file with its
+  header describing the number of source text bytes, then
+  in working out the percentage it would divide by zero.
+  Also due to some bad control flow, it wouldn't attempt to
+  open the .text file if it failed when opening 
+  the .text.dict file.
+SOLUTION
+  Only printout the percentage if we can read the header
+  from the .text file.
+  Read in text header irrespective of text dictionary file.
+FILES
+ *   mgstat.c
+*************************************************************
+TITLE
+  nonexistent HOME bug  
+APPLICATION
+  mg-1, mg-2
+TYPE
+  bug 
+REPORT
+  cgn@totara.cs.waikato.ac.nz - 2/May/95
+FIX
+  tes@kbs.citri.edu.au - 2/May/95
+CLAIM
+"The big problem was that mgquery crashes when the HOME environment
+ variable is not set, which is the case when it is run by the www server."
+ [...] "I expect it happens when looking for $HOME/.mgrc."
+PROBLEM
+  The result of getenv("HOME")" was used directly in
+  a sprintf call. If the environment variable HOME
+  was not in existence then null would be used.
+  In some C libraries sprintf will convert the 0
+  string into the string "(null)" on others it will core dump.
+  (For example, Solaris seems to core dump, sunos 4 seems ok).
+SOLUTION
+  The result from getenv("HOME")" is tested before
+  being used.
+FILES
+ *   commands.c
+*************************************************************
+TITLE
+  mgquery collection name preference  
+APPLICATION
+  mg-1, mg-2
+TYPE
+  improve
+REPORT
+  cgn@totara.cs.waikato.ac.nz - 2/May/95
+FIX
+  tes@kbs.citri.edu.au - 4/May/95
+CLAIM
+ Surely something must override mquery's preference for ./bib. 
+ If MGDATA is set correctly, I think it should prefer that collection, 
+ and -d should definitely override it. 
+ I could always say -d . if I really wanted ./bib.
+PROBLEM
+Currently the priority is:
+1.  Check if ./name is a directory,
+     If so then use it as the collection directory.
+2.  Check if ./name.text is a file,
+     If so then use ./ as the collection directory.
+3.  Check if mgdir/name is a directory,
+     If so then use mgdir/name as the collection directory.
+4.  Otherwise,
+     Use mgdir/name as the database file prefix.
+     This would be the case if one used "-f alice/alice".
+     However, one would then not specify a final name argument
+     and we'd never get here. Go figure ???
+SOLUTION
+Moved step 3 to the top instead.
+FILES
+ *   mgquery.c [search_for_collection()]
+*************************************************************
+TITLE
+  Printout of query terms
+APPLICATION
+  mg-1, mg-2
+TYPE
+  extend
+REPORT
+  tes@kbs.citri.edu.au - April 95
+FIX
+  tes@kbs.citri.edu.au - April 95
+CLAIM
+  No easy way to find out the parsed and stemmed words
+  used in the query. Would like to know these words
+  so I can call a separate highlighting program to 
+  highlight these words.
+PROBLEM
+  No facility available.
+SOLUTION
+  A ".queryterms" mgquery command was added which lists
+  out the parsed/stemmed queryterms of the last query.
+FILES
+ *    commands.c (added CmdQueryTerms)
+*************************************************************
+TITLE
+  mg_getrc  
+APPLICATION
+  mg-1, mg-2
+TYPE
+  extend
+REPORT
+  bruce@cosc.canterbury.ac.nz - 2/May/95
+FIX
+   - 
+CLAIM
+  Repeated code had to be written for different named
+  gets but really the same type of parsing required.
+  E.g. one might want to use a standard method for inserting
+  ^Bs between paragraphs for different books. One doesn't
+  want to write duplicate code for each different named book,
+  rather note that each book should be filtered "book" style.
+PROBLEM
+  There was no way of abstracting out types of filters from
+  the name of an instance of a collection.
+SOLUTION
+  Allow information to be given with <name, type, files>.
+  This extra info can be provided in a mg_getrc file.
+  See man page for mg_get for details.
+FILES
+ *    mg_get.sh
+*************************************************************
+TITLE
+  Boolean optimiser #1 with `!'  
+APPLICATION
+  mg-1, mg-2
+TYPE
+  bug 
+REPORT
+  triffid@iconz.co.nz - 20/7/95
+FIX
+  tes@kbs.citri.edu.au - 27/7/95
+CLAIM
+  Complained about not-nodes. 
+  e.g. complained about "croquet & !hedgehog"
+PROBLEM
+  Boolean optimiser type#1 didn't convert
+  "and not"s into diff nodes.
+SOLUTION
+  Added code to convert '&!' to '-'.
+FILES
+ *   mg/bool_optimiser.c [mg-1]
+ *   query/bool_optimiser.c [mg-2]
+*************************************************************
+TITLE
+  Consistent use of stderr
+APPLICATION
+  mg-1
+TYPE
+  improve
+REPORT
+  beebe@math.utah.edu - 16 May 1994
+FIX
+  tes@kbs.citri.edu.au - 11 August 1994
+CLAIM
+  Inconsistent use of stdout/stderr in usage messages.
+PROBLEM
+  Sometimes used "printf" and sometimes used "fprintf(stderr"
+  in usage messages.
+SOLUTION
+  All should now use "fprintf(stderr" in usage messages.
+FILES
+ *   mg_compression_dict.c
+ *   mg_compression_dict.1
+ *   mg_fast_comp_dict.c
+ *   mg_fast_comp_dict.1
+ *   mg_invf_dict.c
+ *   mg_invf_dict.1
+ *   mg_invf_dump.c
+ *   mg_invf_dump.1
+ *   mg_invf_rebuild.c
+ *   mg_invf_rebuild.1
+ *   mg_perf_hash_build.c
+ *   mg_perf_hash_build.1
+ *   mg_text_estimate.c
+ *   mg_text_estimate.1
+ *   mg_weights_build.c
+ *   mg_weights_build.1
+*************************************************************
+TITLE
+  xmg bug
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  cgn@cpsc.ucalgary.ca - 22 April 1994
+FIX
+  cgn@cpsc.ucalgary.ca - 22 April 1994
+CLAIM
+  "Serious problem in xmg, which I fear occurs whenever a query
+   doesn't return anything."
+PROBLEM
+  ??
+SOLUTION
+  [xmg.sh 201] set rank 0
+FILES
+ *   xmg.sh
+*************************************************************
+TITLE
+  Unnecessary loading of text
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  tes@kbs.citri.edu.au - ?? August 1994
+FIX
+  tes@kbs.citri.edu.au - 12 August 1994
+CLAIM
+  Mg was loading and uncompressing text when the
+  query did not require the text.
+PROBLEM
+  There was no test for the query mode
+  before loading and uncompressing the text.
+SOLUTION
+  Only load/uncompress text if query mode
+  is for text, headers or silent(for timing).
+FILES
+ *   mgquery.c
+*************************************************************
+TITLE
+  Man page errors
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  beebe@math.utah.edu - 16 May 1994
+FIX
+  beebe@math.utah.edu - 16 May 1994
+CLAIM
+  Man page errors.
+PROBLEM
+  See below.
+SOLUTION
+ "The mg_make_fast_dict.1 file has been renamed mg_fast_comp_dict.1,
+  and all mg_make_fast_dict strings changed to mg_fast_comp_dict in all
+  man pages.
+  A large number of errors of spelling, typography, spacing, fonts,
+  grammar, omitted words, slang, punctuation, missing man page
+  cross-references, and man-page style have been corrected."
+FILES
+ *    mg_compression_dict.1
+ *    mg_fast_comp_dict.1
+ *    mg_get.1
+ *    mg_invf_dict.1
+ *    mg_invf_dump.1
+ *    mg_invf_rebuild.1
+ *    mg_passes.1
+ *    mg_perf_hash_build.1
+ *    mg_text_estimate.1
+ *    mg_weights_build.1
+ *    mgbilevel.1
+ *    mgbuild.1
+ *    mgdictlist.1
+ *    mgfelics.1
+ *    mgquery.1
+ *    mgstat.1
+ *    mgtic.1
+ *    mgticbuild.1
+ *    mgticdump.1
+ *    mgticprune.1
+ *    mgticstat.1
+ *    xmg.1
+*************************************************************
+TITLE
+  Man page overview
+APPLICATION
+  mg-1
+TYPE
+  extend
+REPORT
+  beebe@math.utah.edu - 
+FIX
+  tes@kbs.citri.edu.au - 17 August 1994
+CLAIM
+  "Write new mg.1 file to give a brief overview of mg, with samples
+   of how to use it.  Otherwise, users are likely to be completely
+   overwhelmed by the number of programs (about 20) which might need to
+   be used, when in reality, only 2 or 3 are likely to be run by end
+   users."
+SOLUTION
+  It was thought that mg.1, written by Nelson Beebe, was very useful
+  but a bit too comprehensive for an introduction.
+  Therefore, two man files, mgintro.1 and mgintro++.1 were written
+  with the basic stuff in mgintro.1 and slightly more advanced stuff
+  in mgintro++.1 . 
+FILES
+ *   mg.1
+ *   mgintro.1
+ *   mgintro++.1 
+*************************************************************
+TITLE
+  Parse errors not bus errors
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  tim@cosc.canterbury.ac.nz - 2 Jun 94
+FIX
+  tes@kbs.citri.edu.au - 19 Aug 94
+CLAIM
+  "These two queries 
+   (which I typed in before I knew what I was doing!!)
+      > The Queen of Hearts, she made some tarts
+      > "The Queen of Hearts" and "she made some tarts"
+      produced the following result:
+      mgquery : parse error
+      Bus error
+  "
+PROBLEM
+  What is expected to happen under boolean querying:
+    Query1:
+    > The Queen of Hearts, she made some tarts
+    will produce a parse error due to the comma which
+    is not a valid TERM.
+    Query2:
+    > "The Queen of Hearts" and "she made some tarts"
+    will store a post-processing string
+    of ''The Queen of Hearts" and "she made some tarts'' and
+    will have a main boolean query of the empty string.
+    This is because the postprocessing string takes in
+    everything between the first quote and the last one.
+    An empty string is illegal for the boolean grammar and
+    hence a parse error.
+  The problem stems from the fact that the processing of
+  the parse tree is carried out, even though we have a 
+  parse error. In the case of using an empty string to build
+  a parse tree, it is likely to leave the parse tree undefined.
+SOLUTION
+  As soon as we find out that there is a parse-error,
+  we abandon any processing of the parse tree.
+FILES
+ *   query.bool.y
+ *   query.bool.c (generated from query.bool.y)
+*************************************************************
+TITLE
+  Perfect hashing on small vocab
+APPLICATION
+  mg-1
+TYPE
+  bug
+REPORT
+  tes@kbs.citri.edu.au - July 1994
+FIX
+  alistair@cs.mu.oz.au - July 1994
+CLAIM
+  Mg could not handle small collections in the case
+  where there was only a small number of unique words.
+  The perfect hash function would report an error.
+PROBLEM
+  Rounding of the arithmetic during the calculation of the
+  parameters of the perfect hash function was resulting in a
+  combination of values such that the probability of a hash
+  function being found was very small. This led to the limit
+  on the generation loop being exceeded, and eventual
+  failure.
+SOLUTION
+  By using ceiling rather than floor when converting from a
+  floating point value to an integer parameter, the arithmetic
+  is now correct for all lexicon sizes, and the probability of
+  each iteration successfully generating a hash function is
+  sufficiently great that with _very_ high probability the
+  execution loop counter will not be exceeded unless there
+  genuinely is no hash function (for example, if the lexicon
+  contains two words the same there cannot be  a hash
+  function).
+FILES
+ *   perf_hash.c
+*************************************************************
Index: /indexers/branches/3.03a/mg/SampleData/Makefile
===================================================================
--- /indexers/branches/3.03a/mg/SampleData/Makefile	(revision 14757)
+++ /indexers/branches/3.03a/mg/SampleData/Makefile	(revision 14757)
@@ -0,0 +1,4 @@
+DISTFILES = Makefile alice13a.txt.Z MODIFICATIONS 
+
+dist:
+	ln $(DISTFILES) $(distdir)
Index: /indexers/branches/3.03a/mg/SampleData/alice13a.txt.Z
===================================================================
--- /indexers/branches/3.03a/mg/SampleData/alice13a.txt.Z	(revision 14757)
+++ /indexers/branches/3.03a/mg/SampleData/alice13a.txt.Z	(revision 14757)
@@ -0,0 +1,2293 @@
+ 
+
+EÊ%EPq€
+"NrD'D@©âdÈERL)DÊ$ Š )Yä
+K
+`I³fMcRÄÈ#FÌ
+ Èy£ŠÌ:
+ëÐ)ãFL9g@ 	3D0dÊ#GN7gÊŽaJ§ê4tÐh¬ãfÌWeæá:F­7r@(H«L9tä€£4Í7 ÞYÛö­žsåÔQÑÀÓÁd°W9y@,ÅCÇE@'o¶9\&ô_sÞ°Ñ¶
+bB
+%z9éÒŠOÏ¶È
+2ÃÐ1ìŠêÔtÞè	TW1\Ã0v(¶ÜáÊ¥«(O
+y8dÀ
+2µ
+0iÎža"	6Ä_
+ Žà
+|òhŒöÚSÉQÆ
+\Á_
+oÔaU¡Áñ`  ¢tqÔVnäqOYžUUl
+U[ÇPføo F[uteÛpzÁDUVH¡üñegaÜbÌår
+XUsÔ1Öm¹¡Ñ
+ÜR#ªöOUµ%X^\þUb[Zý( !¡rÌU
+×qv
+FÍ¥eXvÔPnh&Z€Í1
+£e[JØ'ø}	[Yå5Æpä!Øh UŠ^7öØ_iäõãRgFG
+üñ%á]¹§ÆQG­¶Ú}sTÅW"v«tðwšnÚUkhU×WaÝVæyœqb§ÂF\Ã]¡
+$Uæ<Þâb_mkgÝV%lnÁ_l Üáí[§
+yâ³i^¶¡š²}Ÿ1V»Z¡ªVÂU\Á_¹rn(§Ã.F®¢çj:š_ZXzŠõÚUn°)ÇpIší
+²qÛlÝp_
+cX^5ó9GcmóS/n%ÆvžšF
+ þ8udUã
+iŽšyŠ\Ò¥QeTiuÕÙ+š³ÐñÆÕYoE6Ëß v€¡XøÝt
+!
+@
+[ÇvŽA
+b 'L:Îä_.ù.
+¶iš NyífiH|±UÔG(ÅSPÝ>èw!öØx©5Õ
+
+ä9ažq§N}s¿Ÿ§VUDµ
+dïú|ÅýøÆ_ŠýôS6ÕI
+QÄ	SXDQQEHõ'áWxF&Âd:kgÂ	œf\ÊÇÈŸ
+H(à&@Ä	IšB@`*0aR!e*$A 
+f°>
+ÒCÐ	Ob°
+Ç@<	Ž¡XÃ!¶ï$AÂC€ÐÔ°FÔ¹Ãì-sthd£
+B1TÀO01ŒFN9Ã"
+)ß
+Ír$tE
+o9m
+ì`c'ªé%&bÌR±ã5ðç+u\ÌT
+×F
+Ù¬eBãcÆ9æ,ŠrÀ¡
+eøämn7­\í
+k
+ÕÈªQš*ò
+X¬¥!
+Â=©:).¬Þ÷v·4¡
+?`@dÁŠâ#gñkZYvNiÈè%-bRÈš­á,Ø¬¥ºòKAê0ÃÔa~`M@d
+©Ñä«R=²êGQÑÓ
+§hÝ42ØÇh$ÏÕAhüQ°¶'
+
+CÛ
+ÍJãÄ6	eh	:š
+)àÏÊà«kò	pë§Å-|Ö
+øC
+Zð-=í `z^ÒÂPÌÔ¡JZQÀ¢ÞÇšxE·ç\ZEþe]s)Ó¥¿1
+
+`Ð€)\QDàTº
+Éš<Ó+è\pØ¥}òÔ+
+÷Èš
+RÈ$t9¬aoi3w ŒŒøå6Ü¬ä^DVÝu"zmÃäÔ!€,ªcjXÄzU
+X
+DË€ŽÈ
+
+f@æÔ®  «=Nd^ÛDMJÉ8NyÉB`M `€TåS8µÉ4Ë~o+fX
+DšÚ21cCèH±=ŠE9°áS6[UÝ0ôM@
+Xn]9÷ZånÙòÛÂ¢2Vmn§ I)UÀµëÙ¯¶·
+
+ð%XA ÂI@ð0Øý¡Bý\)(ø		6PP0%
+
+ØÞÊda÷HÝ
+bÐ0ÝuÕq?Äé&lâŽq¥Feµ\f+€Tò$¯>T=MÄ×EJAqÉŠãê·
+ÀÒ\Ž¢
+¯¬Ús]IµC!;J9-ðÐºµãAqY9!mVÙñ¡X£Ö>É0áãUvµÖ­
+¹Y
+Uèº\åÚ2Ä·/K¶¬¬*[ë×K±)?×CpÐ
+rZŠ
+Ž
+e¯þmÆK*ªUEdË[Ä|¥GF¶YÌÔ2Å+±TN.ÕPÜdªQ2šõLÃ=Ûš1{5M§r tAçZŠ7&ŠaÒV}A>Y¢æbÁf
+3ü7KD£²hØÂ&ã,46QËlBÉÄø¢MØ²âGoÆ«*œ
+äWÉÕVÃ6=2{k3`P5ÖšÀîŽqJ÷ì2R©|ZBoëÒ{×è¢Y	å¶CmÊŒÎÔ|šqæ
+rPÂapiãE?vÑ9ÄèXåÏ¹ùc¬Í2$
+Íe)MÐÏÚãe*­Öæ=²ûÆá-Õ2±;×ç0u³a7SnG©¶°Vp¬€8
+ðž2¹ÍZ®»ËŠÑ©
+èÐÒGHa6êW)ÀÒùª+aÛMq¥wŒ®r°yY£Ñzqd7ÅÅÌí
+Æ`ÚenSgéÂáj\in©Ùy²!ksÈ/ìšäÕSüiöº
+
+¶$âqú2pRaQ=OÁRïäyt®vš¡³f
+ŽX3Ÿ*
+õU+(³äBÂF
+S,0<A
+9Pòó»{u©«¹ fY÷Ð­
+."ðBT,pØã
+zXº>)
+EICiUt|y±PÕY²TåÓF'kWCzF08me·,µ€#$Ì×xÞâQ '¢WtA5sÆÁ,xWr`à.ÅÁ[{²]ÛTF'³YmqÈº6U#fà^4b^üza[sptÅXQqY^R%
+ÇOjvŽµEö"^Ñ7|'ð1ÍSJQ]3Žuh gBxSBã' dxHÈtžc
+PY#-!&ø<QEÑi
+ØPÐä(@¡,÷¡n¶rPeà)P$?ASÄ÷fSÔ.ACyZÑãEW5eòLAŽB^!uÅ&5úÂ)ýq}ã@ÇV{òË1ìôzøA^16Ã¡ªh\¹ET.
+nâzlÒYUdF$²R{È'ÃÑ@H1pRJÓohSáô4"f6²xMtp-ÐÖÀPÂ2eükRásp#gJFO!%¹)Urà#+F5Ù±(ÇuAbl0yÃ¥æõhþ§
+x¥WÏñÄp;Åh;g..¥D5ôb.äL-Á|€5­DE4(³
+s}ÎAbIå×SIeò4®a\O`Ðfå\¥
+'°%WSKUŽ*Ü3wbFíx-w­èJÇâKb#TyÁ2a£I@Zñ
+"ÓŸe"­5uH!ËAóP`¡b£e°£~x­±m)+Ê4"7CÈ!(!A"VPiôÑn0
+Åu»vÙå^¶žWùÁ]
+AQGUth
+æ¢)ävYh
+S-e2wm×^oRw<÷IšXà(%©TgŽ%z÷Æ\Ž
+)A"ip6AhR?²íøqKÊ±Gg*è).Q?NÂ|6ùøÔ+
+R{±^/ù\¥J!"]îU«wxR °-p-BHÆÑsVTJ
+óvI_Qó§ÂáÎ%,+yÃ)å"M'5ü¡ñ	­c/Z0 "bÇè³œP"VPáb×ÒUr±Qé4
+Ò-íØmC°?VYà?A#crÇqCQ¬ÂPø!ŽEØB&]ø¥Ehøihñ8 A bªož2ÿGtXjl{¶ÿè
+hfs°T`A[šQ¢t §
+Ðk
+
+ú§óIr0³W[Sñ1Vºò£iÌ8RâíÄ>x.(ªŽÕsåHoØ(kIo00©a±%O%T€.õÓDð#azj65%Yiö-)ÚŽ§18µ§.è[œZ2ø|â¥ŠÅš1dyzÊWb<z±GO39Ÿ¶èp®2-°È«Ÿªm­Å¥q¡
+iÇO®WgbxªR!¹d6Ô['-8èÂŠ~
+ ,fC\Ø:Ó€
+ÉLQ	n5²Ðt!Ù²¡Ã(µ
+}¢
+Uá~ž¡²ÛIr kz®g àl
+à%es.§g9kYbWwqW¢®v
+2¯°±Sãcz^­+]ØQ?À«<ª²bµ*Û
+%kîê\R{cW[µHAµœbJÑw­(2Ç('
+`,q(J(d ·Æ*¯Êah+R ÒÃ!Ø(ÛØoái&zpÐyžiÈXgÀ8sáWPögžJlÊ€O©=Óú«GŽ
+Ãl97 šqü±ºhÐ+b
+€8vJÓÂÂyÁ²wµœÈ_úvUz^¯%œöñZ
+WPn5
+%ÚÁY~šq¡'bszÛî5WXó%g©pž!",V­Ë'[cÉrT»ERi"pGûÇ'×¿/qîS}÷Ÿ:ÕPsõj%#m4}žŸZ5_Zs5Ÿ=÷üq¿ Ñ-ò¯4âH+kñR&¹¥VtÀ8ÍYÛvk2ørþys
+¹
+CieÂY=6@["r{lB^u£3ª%¯¡ŽÇyñÙ-àÓÂ·	*\
+«Ú[_ó!ŠT5Jy7UGÅš	Å
+
+¡%ì¹äÁaA©[SæÜ§c5Z<b³4bö2©l U;W³G&Uv*ö!Sm|ÃP9;	qõ.1
+x±%s¥­1·e,ry1é^12f¶_IÇtésN±uýråqÌgO¬wGUEBå+œòÂmŒôJb:IqÂ'Zd`oüTEfó7P0ëR¯¹ÈëFÜfºjªîóœ·œZÑœI{Éuz2h !eÐP.¢X.â^W!6ò³qåÉ%GÃU¡ª')-HA)f5G¡ñ
+B³uÝ¢gÍ#bž¶±9>Ùo"2±Üµ}2B1
+XAåÊàÓ|t[u(d¯E(§»ŒfÃ§[Pá"²XZÑÑ'œwsp·Ç[Ñ^)jhVèãjS}ÐÏ2
+RŒCENc­(&Ë3ÏPSÏŒW#7ÇAR"z²d>gÃgF9eçqü\<§ù¬iÖ
+>º¶u^Ã"E¶,dÇm§²Ao  Ô¥%Ö>ýcF°Û~ØVÂ]"#tj¯õÎöÕeÇ'2bwaq(7"¥N  ìþžD
+È{âTmÑØôâž¥bÙwv&È
+Ûy²
+#Y3{³¡·uÇ{\°7RXx2rÇÎÖf÷Ù\JÄD5	WKÍ3/žVN!zB
+ÿ©)7×&)Mku*²Qq$çÅÞÚ{ÕeÂál{ô/¥ÜÅÚÖYL"fà÷¢L«àá³ys¥¬ÂÖtF3ØžLVý¬¹uÐ
+
+MÙNHÁŽŽm2
+«%Æö¯€BX¡ÊÆbi
+«
+éRŽ%FžãX¢Šyž¡
+e/:¬¹ÓÖ[F"«!nKÎSY- íÊ"-ÄuÊ>©TÅºÕhÑ[yÁS³FØoEQö²Xø$Åâ,Çg,êheã!Í2Qr«ü^bqÇ¹å$,nSøQTžXEø
+X2
+«^³
+cfpÂ%Ð-,%*ËÈ'*]Øû©ª*Žbf&Õ¡Á³âFMÔ²žsJéÆRlMÄA5äsPäsð'ê®÷ÚûÙŠÔ#M3;ßÔ ¡fT éhó{K1)qìá¢%lþf!šLhÍPl²éBÓž¡ìõ×÷ášºµ}"¥= U!µRà?Öó£N
+aåh7r+ÉÂìiâi>MRÊ|ïyG#îuQ*Wi%µAVcÁí\iÄk5éA%¿5ìPV÷ºf¢Ê+±zòœÓ¢9š³ø1§#
+vÖTPOó°ÊQ ŽL$µGfì&å," 
+)äH'_;GË·Kïõ=þÈ>­âÑAvRÙfuq6+rcž
+¬ç~[ÉÇõLeb°F5l¡ëT!§x9[Fáï­zËÔ`L6
+®m ®ÎèEëÀÔµ¢)d0Eæs%ÂàÙû·Tü¹W¶mH1€|6ž$!,ý¥Î9ÙÏ5ÔLXìVy¥/,Ò
++#h`A5)[¡díÚ£
+ôbØ.""\SÕ\¬£5ÝIÊcp©IÆäb
+8ÝiAÊ
+îtX}µÍÄHôÁí:Ë«"Ó.×8
+í÷.Ú3&°Êå·d
+¿©üÕß¯q5Ù?O(ú
+±ýÝçýû¡æÅª!VnO²Ø
+Ðí±È0dI>#²Kêñ`¿°ÒÒÔâ4­€XJÀÉâÇx
+Q.C]x
+ ¡]}þ ]Ôâc¥Åq¶WÞÛ»&A¢£õ
+J,C9Êå±=
+JÍ!1`ä«("PRÉ* &DA0gB
+W
+JÁT¶©`Ž_
+rÁÉ`Ô^0
+Áw¶*vèQkhO\ÐÍC,2(Â	!É"tG%û qãë§Je3«iù5áO@	hlóË^899ØÚb
+«	ò(²d"LUú
+,ªõgE\ 1{h·É?ŠúT^yÄi»D7ª×)ùm²í}9(!Â02`gÇ°Í
+]43s0öüß!*Õb\
+V}6ýÀ+H°£±Íöìž
+°"ë±7óáJJ«o§(ËU¶zÁíîà·[?µ8ÄÀŽ¢áùh#ì
+D7Rx]àÝì]5
+$ÕUË-°1
+üNÆc£Fj
+\ÊSEDàÂ)+`×s¡Fd#V
+*ÁO*ÎîYŸD7øR:[$ËPË÷"ÌA5¢pÑÀÈT*Dk#«ÁS 9Š`ÄN_0
+ç#
+ž{O [á
+
+»üŠrX(
+âEÉ ×Â_Õ[r(e¢©X3£èßhÓc~ÊnëH:Zšá6
+Ó)Æyx¡é
+T)	h@
+Ç
+b§nèâq·Á	:²Q%^Ý\
+h¡±FD÷\ä
+@)Õ.4,gøÄB
+)G=Ä=â@Äo
+/S%6AÓ
+H|ÈÓA5?6ÔlÎurTyàøy±­C×:É
+I'ã<Œ#ï€ÙOZ!+æWEËûá'ÊDÚ=64d
+pÑ­=á'òKñXIÆþ¢wHZr£<€jä*B Ø8 V(
+kEX$ôM @ê'nÀwž °ÆÂÎ~Q¢oxÇÅpQ:y!
+ÃLÀDq.ÊßiÈZÜ
+â`.Z)Ql­ %eNÅF3ñðÞ¹ð=¢ô
+p1Ú»ZC\£1X<à
+*ZW£=ì1"
+Ll#'Ðd`HÓÈ¢DÔ8w}b(è-%s
+ÈUÒŠ9`»
+yÉÑá5BsäÄ]pQáFS#OÐ0eà8	D0`²ðNtŒ1,
+~8RÈ]ã·C&eBKþcÁ.É²ºn
+¡â+ÊÀÆÝlñ7>¢eH.í0P€ùæÀ'9
+
+VŽÃ0Ù<É{ÄDÎÁáœºáe
+ìb$¬âRJ
+ÞJ@¥±©69Æû¢1á5ç¶¥¬nÖôBáJ3)Þ
+(°ô5éskïßŒmôF	º.!øè
+ô»ÖÇ`YÇ€æmGn5n)})_š+ÆWd	eÇœ
+?+Zk@ØòÅiK7ñœhj·å)l§ðà'\^0
+EŠÁÓòkKÃÙÜÂ§xÝ`2YE$c
+¥,¹íGüa
+s Rþ5f2Ü[Ä"­k;~<mf1Z6h@¢ÉY²Õ*°1&4ÌÕe/Š§ ñà(D¬(ËÄpA­Eè
+Üå{ÊEÒ1J 1ðšDô'¢RtñÐŽÚ€ÌZã#­ð
+²¡É$Þ£}ìGÅ¡­<ÌD^èóq?ôD[ª7§áòõS
+Ó	
+C)
+%€ûQáZx90ÇÆÜhABi(ÂØ6àK²Ç!àeF_òQôâl (nI
+Ì6ÞÄáz+25Q0ð!I1G0K(Á £[è³A0:Kç4iP}ŽÓ©Å`ëDªÓuÁ×:g§ítbÄ2œ30RýaUÞyª@Hã
+HwòÀÀž3áPœ(	Mž5ñ:Ê
+¡ÈEvÐß!ú`>3(À#Zp
+±÷Ò'áÎ#é
+"lÀ/ª^Ì¢åæNR-Áì[V·Bž1Då
+:.¯¶
+ T ÌÎÑ1h¡ÈÅÌVbnÚY2OÇGÄå7édnãÏ²Ô;ÂÂ,bzK
+oÝ
+TÍ@
+M5Î*tÁF
+ØñJâÅ_jìñ1àÀUa+#Æ
+ÆLÓÂ
+Ê®0²Öþ7â
+$/päÖ±áÈŠñAsÖx?,JY€Ú9ÃâÊóG6©$û2ãXÇHjX Ò^h}_°l¥Z²ã(BTtòYp;7âÔ pT
+&]Ã 0³â9ÿdä°Ôð
+h6²
+Ýš
+0i
+Ôb×MØû°øÚ)i{Ô
+ÐðI®¥øTc€!1ËÒ{ZÔ<òåÊgUŠØË0b[ÄÑçé®UY:©æ	6I"2yE/gè&-Ôü`,H&Ö°±ø
+¥-ðy$ÈvÅõ8
+fôTrÚ§Mxñc~Ô{ 0 2L(9
+H)	®	6%â	JÉÓ F" )0P§@D-%ÀSùA?8ÃÀ/TÅz%U°
+h--¬ŠÍê ,
+J ésbÆä@8IÒ3Z³þ$c
+zbãÈ¥?¢>{
+l€q	°Ñá&¡¥DéìÜKÀØ¢F£lJí¶ç
+Ã¢e,f/ã©»É{x[ÂMX>
+9Š,è«zÖ± ³DWXVØëôRFÉP âÖ©3_Ó¬PEÊ©³¬,+>µ¡|NáLLÑ÷hlÄäžÁÍõHKuÜ
+IRelaÒŠÜšTÕô
+-iéí
+i2ñ¢,+Ö
+ãà±Øx"uõmâ%!Á@³QA2­6EîDºòm}è=0±qÑªLb3¡åjŽóYkFñož(Á ÅeábüÁBÑ>éÀz[pD[È8»~žÞÈg'°*L#îãTéð
+I¿p¢£4K&2X1â
+å¬!Sµ'ò-Caôj3R
+Ù
+w^+s
+#wÒø!B}
+)H*ö3
+%Ð9,ö&pÏ§)-9M,
+&Ý`>03Åtg y{rqSR4èT®bn)Ž¡Ç$Ki»xuì
+
+I#f¬ð>µ¡|ðê\ªÈUlÁ$Ùð¢0
+
+¿sv`Ÿ¶Ô7º
+EÛ#]ŠšD+{Ž
+aVpý«BýK>fR%l |¡¡Ã&öåYå/U$Ââ±§ùŒ€87ëvsÑ+Ê·Ýô
+1%÷äBB!rà;O=ëk
+Ç2
+@§NéÀÁpfMjÞ.Ø.ÆPTëZSŒ±ŽÙÊ[í
+«÷H¹©"ã-®Ús_Clø€f&s<)OïË¹ útjÚ0cÇ/ëcÖËÌ[
+
+ø:i)ITgÀI­È`fK@ènzkÀÆº¢%E
+)¶5 $ÂŠ€\Ð-wH³t48J#à3V8.ûÆ¶Î·š}ÆÒ€heÕ*è%
+^ÝqÌ$ç4&Bb×rÄ 8gšyd!tO5ð øÄU
+m€Ó°År
+=ZPèTv\3
+¹ë: @o/á\ÈPjÈ©ó.Ùhhè]&/ÁTÔ§øEF
+Ðz öDÈ«
+;8'éž3o1%»
+Å)nR®òË?ô4ŸÐ§i
+ŽIVWúR"¡Y$ý]2¶PºÆéj©LT"R¡
+
+
+0¥
+6\läËÜRÎÄÎÄhÇÜ¬e(
+çÈÔÂž ·©0Œ$eKŽâ"ÛŽøB\Ê­Ü¢à^BPÎœ€¶×xòõKIvÙÖDS\þ£-B .,
+ç¢äé<·?¬ÑÞká¶QÎè"]û£­qø
+GNO]š}»oÓÔ}·¿§@:I²ÂÁÍ€ãµ£	©)Ò@ßÐE¥Zº)£}ÍÚXH°ÜÚ$[åw
+[O±ÍÞû{]Û¢Æaù9°hkÄGzÁ.°Î6úhÀAY(E3šÄ@"%r`ŒUN¶<À8ïÆZŸG L:&8P`"ê×ª1%à
+òàðÆöGM
+8Ç#ÇB;âüÝúÑŸ Åo|¢å4iQ>xKŒKPfj\
+ÃŒÐyEò-Br£@ÐÝOYù¯
+é`M8Êµ
+Í7þ]Ç'o÷š ¯Rì
+Oáº¢BBjèt¯9]!!Þ'ÞQ?{ÑfŸm Æ¿~10(a ·³aÀ¡t]*£HG
+Ñ$-D
+ïÎöª0¬
+ù/Hj6t6Iöa(èÇ× I~SI
+
+U$Bñ~ÙÂ+(ª»ÓöñC*}ªŽÑ-dÑ1h*ñm:OàeMUèÚdÊ?"/îö4-lÐgî5|0pI%×Ð%šçf±MžÚÃ>:ãŠv6\Êñ©Æ3 È]hAwßYL`ÑÚ€Vz×·£,€É1S6¥îË}8Œíìm±²xñýÊ£1êZ¡	'(
+dhjY9Pì
+-(
+bfÃ÷kØeH%¢ë¬
+mA»\4P
+'
+òdi/-@
+ß»ÓŽÛÁè
+'õH»ÕYå·e×1­#C^Øš-±>*÷ò*dgÉJD5k«ç«ê©EX\s2º6°Å§È°xE7êH¶Ð
+¹yMÝÖµ=Iå^&a\]ªq
+ÛÜ­ÀsUU#xa·cZS~«Èc9
+'%á€£­áÔÅàHò9füdNÛ{QÚbl@.=Zfê¯õ
+ÙSÅ;"pb3 â¹2QE[òÎB»B}ÏdßsO÷FB
+Exûnc"±`7Ö8H	Û"Ò±E «îð"fV9
+
+ÂMaR4ï¥Y³÷(©üÐÑØ
+ûË)T0bä.ëí-ôÑRŠH`l+ºGøB$^ÇLzbŠ¢©"d/jÚŒ
+(UYFÖ$í)²LªðK@&#
+oüºÊç7k¹Wp4$š¬æ,GyªóõÉtàKÚPLXT?ç¡ÒphQÃBâRŒÂGÁ*	ÅÝ(*[`q¥tÁ€[
+Ìdû^ž/
+ xSOÒ3J¬f01
+hýâÆ¶[I}Øóä Š'=ÕÑnË:F³âÁD[#üã57("
++o¬J®}ê§?§£)böãQ§9Rô<áLEþ\(³º£A×Û}ê
+ÀºÈéŠ^&i§E[ªPœê¡
+l'ÌÇ¹)°ß
+u`ÃÅA©Y2Ù*o"qûh»ª)á(Ï%XiïVy¹&+ëIl[¡,Ë
+"ß	'²ÒZÝ¿
+V581B(+LcOQZ°³mYio"ßú}·ã
+k¥]áP\£ÖIk§K«ÁX
+w>dÔ$¯%r53Øµõ\ìÓÐ C¹xµN
+Æ]b6¡+ù5­±MãåâŽªÝ(
+XËÛo€]ÜØžoê0á°ØºQŠNóYç$3
+PÙ|2jñ.e"ÛÅù?ÅrùD¯sQQx
+²QÁÑê9.Â	AÂ'ègyÊWãþ
+€Ù<nÇ:W-Ü^
+r-xñ\UQ#V[]¿pÔHÁ¹
+Mi áhã}8³À1i¹Ëñ#R9É¹ð5€É0ªLâbjQT&@ÿþ¬ÍSÑ-8ÐÈÕ²b	L4gNÚžm,ÚI?¢éTS
+é+È-ì,ºg]ÐU3
+dØ@!åŸMcÈÃµã3þ­>4RpNsè*êðÆYÐ°Õª»Tszi}3.6¢t©Ú!ÜJ$W	Ù/ÀÄÛ× »Í-º=ï,¥ÊTÚžIäëŒîyËè[¿¡î*X®k8Ä¡$ÿÊžgs55©AQ¶6åv4$­1ÓçBa7ÈHrpP4Ðí!JŽe[Ç+jŸ±Ð©Ë9ZwÕŠ%Ò6î×~Ì,k¥ª°_
+×úà
+BÊØàžj"âÄá©²îjÕïM(÷9ìâ{
+8ÑÓqûH1R
+_Î
+¹~Ä<ÎêñYÕœTâº K[U9yoWGÕ\D<±Zà\ßxSä|c¶qx
+=1r¢··{¢Ü¶ÅeË±KNØæñA·ÊÝ!lÇE<&
+zpØ¹v|_€ò[T!wÞÏð}"éÚFÀ5)P ÛËo=ËU
+Gµž¥ãìRd%ŒØTÆn,œ€'Wh}«={/F¬ãíš¶phÒx%ocŒG+êÔ¢g\51gíË&_Â÷õ­«ÂCqÈ
+^%ÂŽtÃ9ÔÔcÙpSA§HíÓÀ,ò×Ûà²íç 
+ßžFj
+±Z^0ÂRò
+%  Ïp® Ò
+ÝÞ
+;£· +wÍê{Ù#ª%Ug«ôÌÃvåkDº=^s6
+*E[\¢7D'îfAVÐ€ÄšnW¡O0¥ÐŒfe×á[.Šp°TØ
+Áæ
+]-ÖÃP ÎÎ
+KÈŠ<?Ïü$æ¡èÎþ(Xèè€|ºjäó`(ÐBiD/¬û (åõ|Á
+À
+ä³
+¡3AkÆM~
+²!%D
+H[}â±',îÂôXT
+x³0dÛ§Z.pC¶R^Ás¬&
+Omú0©ôð|àÏ*
+4Hµ*ÜŸòŒY3ËžNÌ³*¬Zú
+ºuCn£Pâ	3sß\±Q|²
+S·"Æ¬ 
+¿œq¯Z³ÂŠ,€À»|Ã~QJ\hK
+ô$"Åèë¯/[,F³liÜ
+PXc€&Ö«{,X]ávòž~:FÖÄYjiÐ6¯qëÉ¡-;ãtÛûúõèrÚThäé&&LTDdÁÊÞ#÷¡ÇEªp^©FÒJ- 9ÜÎÇ¥^ÓB=5ÄGÓÉâÆê|Ü-ŒàÅ|JÅzC«}¹nÁ¢ÂP=F
+3'
+{ÔÎ
+
+vLO°õhFX)ñ5Ÿ÷é2+íù#ß~ÔÏ
+?
+(^.:vùVag0îtŠ÷±œŠ7š#ëÍÅ7BÓvÔuTð.âë4ŸÂÔê7»§š*]8DÓ`ŸnÅ-Ø%ÄÀî ŽÅ¡sBt$¥Df©
+'¯dªÅ8J`Ð37?ØÂ
+kb"rëðbRUÒY¢2IÒ7&FjB*Jì
+4Çz¶[²ò^ûÚÕgA¥Ê_ùñ!LÚÄvòÁ"CtòH¯!®$°äÜLü
+¹Ô$Œ)ï?6ì+Ð-³=eLÿ·s!¡hu|è8"~ï°·CÆGäúì³9},"_5ì(9op
+8Ò7mÒL€ž@ÈT
+nšÍLYî«wdQ¡G-¢D·Ô¯cz¢Ð\yDùzÜg©jB3F©y1As×5ògèÝ)š±Ìß°žÂäÎ	ÔÆ6PßådI;°Ð±pÍ
+XöÙid[rß²\ÆjcA&Î{uaÅ¶($ ð¥R`@ÃW%®
+HèïœÌj]±'­T¥ï0VlBÑÔµ
+q2Ï
+þŸE+v^Mù	;
+<W1ëw±lè©"b1>MØRÚà|c5 æ
+â·Ç¥%¡k¯xé3fÈ»fÇ ò»5-ËÜ5øžšSäÖgÞ}ýeŒèÛ/¡_Wçóz
+hEÔ¢§gqNÌT;)&úÅžã(ÊýïÜìn"<x6
+ºüŒë?ÀyËoÑ
+rœ Û£Å äébCÞ.ÇŸµÀ®.Œ]G&Tîßã|4FÕŽË0ûV1uáìD=<QJ
+ÊeŸLR¹
+Üh¢¯+ZÿJS+DÕ"
+i
+×$ò¬:)Ôéàï.qŸ­w|"sD&)Za5àûÜëÛÃugÉ/+FDKQøÔQhsxc9Ô%
+zÊ§zY_Çp°G³MŽÌ2Ë¶AÔtËlÖ±5+ÌäP	ŸÓ<	O_Ä1ÉA×Ðx»ÇŽ4
+X`Á<*ž
+·çX1²?svž 
+á
+aÏlÃ²
+a_w²ÂÕ/Û_8DåIä~<
+À@Õ
+|ÌÉT·\C>áRŽ1­J)Ñ@
+`ožÃñgdm÷R[`1(¡#sŽk2×Ô·(T(Ø+aãš3ïG$	;IÏaÅÔØÆ!*{
+ÁGÌÐsÑ
+@£a_(¥^RÕ}µiÆÝµåRô èál€djRó"}jØYŽ¡`6
+ËÇ`ù><Ã	HáyËô'nüsP0kZü§gyØá*~~ÑA±x4ÉUCÛq€Ùl6Ù 
+oûboPSðc%=Ø{$¿\5¡
+d/mÆrµIBO²{ak3)âžrÓað<bÐÁïbKl	ºÍùòpkeuÅ/²Í
+ôã5q`1ŠèÊB2>ø;Ø®°Qž7 
+ÄõíFÈÄ "š#eÏP@
+íIÄI%_LÀðôo«]W''0ÛÅ(Ç÷^
+rTý>÷
+µ³üL€ 7
+1NáL@ôÿ
+1ÌÖÅF`_
+S8ähä PÌb,=Q -WÍW#`
+4JD~ÿál/Y
+â© ?×ÞØ,;'-Ø;
+°ä<
+·³P0*Sµá ÌhÒÏõ^õÂâÒá	
+ZýD,ÙB£eä"8V>(|B9wÎa9à~£÷è?=8ôK	Qiy
+Vå
+¥åjÍ\Ÿ"U€ð¥`mÆSl
+LÅÄÛ-Pt *	Á
+`ÉQõEPË¥¥dÀAÈ·(4Oô 
+(š6ŽaÑpaqWÀ* n)Èì
+
+Â÷à·xŠÑàíiCáßç2çÂÏt-H
+Â%ã!)qœÊm0ÈqœTÖõž!C!
+úhgËw1\&MW÷°(
+4!Ž#BH¬`F
+	dagø&G¡¡[pÍÌ&Z@JCÑZ/ôŸ&[
+kK&DùÊ
+[åÃVs£
+=€@
+d1Altr@¡g;p
+ýM;B²AWÅq<îYSÇ'š*H¬kRyžVÔaÔ
+ÿa
+7@éQ¶pðéOm=Zsã©cXámÒ#þš7r
+!#Ul
+xÒ$äÐn§þ)qÖÜÕ$£@hÏÜgIpxApÒñv{
+öÙJGÿQE<ùÊÌÔUp
+qØ
+bÅ]£ÏðnßÕž0.µ#Ü-KY
+!>âÓœVß\gØæ|Á
+' ímfáry)<sR6xN§[»ÎA
+Kõ@LíEaŸÍ \©`2 \Ê
+Ä¢p¢Ž8ÃŒ7u7ÁÆ$!ÅŽÔ+œHÒwàH²&ú-
+ÞÕ÷wx>@aPÓ^¬,õ 7ÄäXcAòð¬x
+!s}XÐ¹È	_ÈäÅ
+åFÃ9Zä¡²¬bAœ¡gOEKä§Ad Ü'^È
+:F®Bš$ñàå	\ÄP1aš®`0ÎðFH
+à_HZlÐ ÇQõSŸ
+VEýGRXn]óuÑS
+>€q WîŽW9E&FGe¬ùTÛIÆž}¬
+}ÃÝ1Ü-cX1öKŒàqèr
+N³x
+è
+7 }È¶Šý
+{ID^
+wèÀU
+gÆQ<ŒB¹ØþÝ\Z
+r\ 1ß²d¶hÙUXŽ8rOátQ`
+Ô%`G`FP6jhcžuË¯ÝmÀÛ @#üf.b
+IÅ[H^€a©WyLOŸ#<D^!Tdp
+
+¿y¬'€«I
+^Èåµ!
+¢!Qc·ÙLpR×"9©AÛ*è	áOçBþqgÜÌRH,õ
+¯çØü
+Å¹pŽ
+oÙ
+8Í!<â 
+
+íÓèdo_"ÇT&ï
+0ŸeK~EÁmZ	è-v
+ÐX+èskÅsP
+ÔÂiÒ­<`sà2ž°jzà/BUjÄŽ%
+$°á5ÑVKà.ëau*þã$xYã^4À'ü
+x°A5šB×ä
+T 
+
+iÖÒ!J(	ÏÙld¥Ã7];]LA1@9]ßÇgtBãÕ4HÅ÷àHØ^An3úÞGŒ?M
+N<áÚçd
+eÚŸèb³Íã@i#äÁ"(||Ú,³Q|
+CÆ
+`ý;(Æ}`<2dò3InÇµ<ä[pâOÀ àeâ
+ø7Jh¡^sP· Óã ÷¥=-	äñËOtÈHìÜrìZíhIa3ÓÖkUA¡à vá 1Ð
+^E',Ø[Ã¥$ô
+ïSÕtÙ47œD9A3
+xfÊT7aDUl
+fÄÿ·šJy!¡d±86÷YP¹{qY
+yA+Tü±AÂ§PR¯\sKÆœÈÓ'Ñáét>òIÂ
+.zFí58@øc=ö¬î_s+CL!TFC "a£Fpô9l¡&æD~®R?ä¯5 IHŽT× C
+(BA KŸñä<É¬MNÂâÁePD#ÃY­Éàž
+gÉ>A5däáCõc,Ú4*Ýmiã\ `Åo4\èL÷wF"Cq
+=H[·=@
+_U0ðÈÃÈ¡3WG£Á|ÄêQ@eÄ2}
+"\åHŠ
+Ø¥¡šI¢#Cä© O3$¡$Ê#ê(ýQâ!&kãDÑ2ßEÊæQ>¢
+BIRô"ÕÖhÔ+
+$®ATªMZÎ¢ñ4J*Híp-!%~ 5
+^ ¹DRÕ9iqì\!Ê3!'ÐäÄEŽd%
+IxZ6ÃY90heQ³
+®
+a(TgxÎÊ%È)%P
+&üEhbpæúm#hQt¡fî0FGàZ2ÃMjäÖE±7šiÍÆè2ÊM'A08&ò"úÚ0Ì
+¢[08²Q}bvqK"MtEQB
+öAv× akHRÅ@EBaxä*É`éjUQ]%
+Tà:Î£D)ìHc#ïÈ#üA
+2ÁNr
+Ì±@58 è1w@Fyå1/þÄ C±(@ÛØ!ÂÜgSBíòKn3Ïä35	}¡ŒeçÕE'äögpRW9v°KDÈi$ILÔ£¡{
+@C6ŽÅ-^wMVB¬ ¬Ü1³_Ô°2Ðs ²TºC
+1òËø~¯ñh2Ž#C@Aè]TUpí£2Üi
+4ß3yb(&N{DQí
+ÒämåÖ r
+;k%I¥'ŠVYz>v£¬&
+ÖwžÙñ`r$*Ö'xx3¹¥	Hq
+ó§ñ¬Ÿ
+^yXâ`MûERòàQ=	B0Dº%f	>Ôð«Xvs,Vfb$h¿Pa±~Ïsü!$þÃ[Ô_ HbÞ
+AB©°ÕàQÇå`Š'fDI 1Dtd.B¬)©|"Dà?jÊvc Â
+°I©Š+È±­	FèuUÀp@dÎ`ŸŠ
+!û­vNB¶iCÐÓaâyíCNiÁQD"%0<¹©ù
+?I¶Iq¹8¯	75®
+`ôdS(m*u\¡ÖlÒ=
+ LÞS!äÀÌÀÙ>ìvúà5ãn.àéP9	[0q
+ÂÖjôFÄØøo*¯€Cnvî&òêç@ fQáqê6ÙÆ)ä'¯°o>A¿jOÒé<š«	L6§ËYs>Ë3Ãs_øt/Gt.ÉÑÓé)Š-çað1ÇæØZ`#;'c
+WÀQÚ
+&)'R
+²
+òòTmÒB]
+cI$>YåphgŸCR`ê©ÐE&»\šNAÀÐ[u!z§AK8üOZ÷bW0
+aN²
+ž×)cÝ$·`yi%éåq°T(­vn4ñ!7ÛåYr
+Í]Ó!ÿ
+(1Ê"çE
+,BE1
+ä=0ò
+¬q_9;ÅßyzlQÙî
+:RBe¢ªâ6çiw¥]±|T\ |ú-Ë\ Ñž rõwÉ ¢p¥°aç%Ù°Ü|EÑW/øf€)guK8&©ùGÂÜ¥}ëß ³QWmeMØ#@€kÛ€vá+À2ÆŸØ_Š	I#B¶dÚÉÏ1¬È
+r-Øydm§1,
+8£Íè
+dÁíò('&Æ.'_ð2;CÜUÖ#ïÈ-jÊG°
+n}šhÐ62WNSÜÚ* Hoê3XbÔ#MnH">
+4mØ,SH>TðsõXô·Åøv'J5Òá,ßòcv¬Ô&±ð/Ù²E+c·¹(aÀÄÈs	mÄº7h@ÄQùä+X
+hcJ)ZA¥Qž£'r
+Ëeb`)ß§ižEg·F¯qÛ	¬œÙ!DXç2è4TGâô
+fpPp¢	ã2ãñoII!#íP¯ïõÄET "
+C2ÕapÆ'¬e%±T&
+©ÞSp»°ÁzŸÁ¡qTþ
+(ŒK7õ]a+ÿ}ÇzåwYZaGÍçRxbœG^×^b@àI¢íšg·ó¬r`dJÔ
+Í
+4°zòÒ
+
+?š÷#(UÍÞA(¥ådPu¶ K_)ur Ô`?ßä0O\Dt?Zd€ZT'L€Qú(g@LYàœà
+ÖplºÑQÏUÂØíb[€Ù0±qAÅ­ØP
+ÍÀõ€wùN2Ô0(I€3!rQZGš
+gú
+Â¥.'ŽesÈDWFešIiÚÁºÝ+ÆZòg~q
+?C.ÂX0
+ldY
+¢
+$'u
+ò	jœ/Äq§L<Ý%žeL^¬ÁoHnÂÄ60Éïbí]tcq#Òâš¡Y°	-O)Zö&ÇÒ¹p-î5Ra^á4£ÕQ£
+Õ
+Y
+Ðµ+îséœb+}%¶i 0
+ÚÍÎ#,8>UÌ!9oyÁæ§Ðý&j hÒüeVÇÂ@h"ÆÍQzš
+º{šãÜ3lxfãCE@øYLX}õÜW
+c×JD*
+	VÒÚ
+4²q&5£à)XrýÆ¥Kü[ÍÂ¡7ôÅàRj€Åæ€<b(µ1ñ ðXŒØAèYSÀ)ÒiA&&šS#`V1VaE3ÊÎ2²ønßBÁ+ ìÙ1ÕÐÆÕ×Õ'é%ÊÃ
+oG0_
+})Í­³<Š
+nDD®LVëŠ<Y
+Æ[¬ŠEx÷æýš$ÉwõËü`ÌçLÌD)Ÿ4E1bsÐö,
+úæõ}ÂyÖDŒV'H
+D°©Ì2ÄÌ¡yd#³[%
+S&FÜ `ùÔki5Í5>lg lQouìâ%+ýmÝÍa,Æ9#ødûâ#h[AEœàz2Q;¢»œ!{`cznÂ§
+×ÐS!@ÕÝ±:VöÔd^X$GXX`SéP¢Yæj"ºSrX²Ë¬Â8éYvâ9ÐU§^¡
+étWÏ`ÊÂP¶Å­P5zé:ò!°ŠÀmÊKjÈÿŽ$NÀ¹!w¢Ð­¹6²šŒÂ^w6D
+;F
+m
+
+§ŸC·ÚÙÄøü'bIwXIš{$vtù95õòGÞš,0{m#Â©8xÉî
+Egµ3ÈÒ5ØH¯¯97
+¹°éFZñKu7ÌYø$-eï
+óaÛÛe
+µ°õ>?V@S4Péké©šG&çú
+~ŠIxÐ°ãgógâÖçuJÍX7ÄkÖJbÑQ³(ÜJÕÊ|BS+`$¡	aÉ5¬ Šø!-D;Áð
+
+³³žt6Åë
+òFÔ##UUwGñ1i
+GÕÍã¬){[UF5«¡Á³¬¶q¬ fSr~
+ÅK
+ÑÍª«
+ÏXn9"a_1U
+ CLp¶±~G®Õ)
+q#ÍÒG"C×Z EnÎ¯¬ïÛ	E*Ìùõ4M×ñ®6]¶J%õDRÓRzIeß[£7)q"À	hàŽ
+WÆ
+BK9*4L%ó
+
++#=\}zŽ%-GïÐ$
+c! \ádbOQ²ó<%JÀi*LáRÀr2då&êöu!À]59k\¥ãùÊyŒË135$Œf
+ÁÍaÊêå:§ªO@1¥Ìàê"ÔÖY4(YÅ-ô^U£ÄD-XBN€ÔÔrÆJ&ÑøA·1(ã¡Ýr*?#
+
+ÍÇ0Í#VÎ2j56ºhÔžÒ©nÊ
+
+byj{êxi
+SO#MöIñ$Æ#ØécËÇ`Ï`§
+þØ@.ÃG`ŽÏI:!ê a|J'\ñ
+jÂ{4GbÈèaïà;DÀíèµ¢Ò(*$x`99HRtwÌr²T£ŸA8)ŽM0Ÿ
+m¬W8uh
+³Öw	Å³C
+BËò2\<åK
+Ð¢
+ciŽ)ñŠKé
+sÊÒ&*X±ÁÊjÇ-Mmª/
+5:©£{N[Ü|ã:Øg4FÓ
+ÕŸÕ
+;
+u©7î ¶*.\EmÓe`ø0+Ý8°æŸ7Hš;.qZNŸL6
+I68 íÌð6gcnkæ`ú¯3SQrnîåN*AônnX"×-*)AM`AeÇÍ3ÿ,ëæªq@iPIU8¢hz8Êe×Ôb0íÈþ0+î(óÙPF(2?²
+ŠÑÜ²ÌÁ0pLŸÁšñLÇZüCËÁlÙQð1Y[øçÙIŽÝìm9­ßlqÆ®U¥ÒcA~*
+cd,Ch7xØÑŠ[«Ñ}Zâ"Y#%×ÐÉpj
+
+É(°WœÍ2ŽcšúÌ8
+rŽ íé 
+,.<	oÒUf	(í ]nÍ
+8@xæ@I
+
+ËLÇP°ÛÓVÝüSEu
+lÂóª±2pžËm¢y<N_Ù5
+Ç
+Þ€,Í WÀëætsè
+¶Ê¬1/UwšR©ªömH
+ìY€?áà4µu,Õ~Ø
+NÂ3ÓŸi&FrQÈ±eR]böeLR©HiçdY@¡L«$/Ç
+O*DÂb>íÚç$DÄ©qÃ 9 gótüÑŒM£2š7·sÁç'æÈ²UAÅ+!·
+_Xk]Ñ	7ÊmÓî'I/D]0oú
+ŸÐ¥kYoPoãŠó¡^}oí­p#à)]¿'&í5§ÊQ
+ú×V¶-ÕæûhQ-lZy© YAG',zAßû9bwÓÓÔ
+3Ešé\à!­WyR4M!·üHžãmâz¬¬T_GX,
+¬J¬UVŠC¹tÜ
+1ã¹\í©ëÄ£]Ä5µy;_°Ù
+"GÅ©7(
+Ëç.œ|]àLÉ6(b
+¡B5P)Ól
+¹çÞ¶@0n|A.bI"KH)n`Àl*"¢³Ñål4NÒ[°XoæÂ[Š±pQâÆÜ¡h5gÄL¬€3UJ%Y
+_lh[º4ºð51çæF{lAàÅ88E·Àµ&'Cý
+	ÌŒf¬¢^³#e
+åÙ/
+êùb éŠ	«µ¬n[n¬(u¹
+Ò @mŠžzApë-êEÎÃZÒ¡Ó=y£
+qñVÉŠi2íZ2³3Â~
+¬6}Q/Ùèr`.7y1iŸÂ^Uhš7wàÀÓ/ª¬¥
+Øu»2Óºô!ñFÒ1§iPiuRénñî³jjvhb«s
+Ó¹ÒV
+Ûàú[OÈ@Öø°¡\>|2ÖÅÑæYþÅ(RŽÄ<~×5£Þ
+¥_Ù¡Né­Öå&juEMó4AR!SëMá»Á}Ñ©¬µb¡úa.ñRÿ
+ìÆÔy;ÚîVMi&ž£EÏè°wÑªÊn\
+Hóñ;UQÕÐŽ
+i&É\`!eÙÔb$Öì(©²]ÃÑoöAç#µ .ØÀ?ŸC×iý±Z	5*#CDÆ~z
+1uøýZù«¡Àµ
+`§-
+7Ýrj&¶
+YLÅÇËsDD:J¹
+ÙèYJ
+ŸYøq­ÍÏÇ¢Óc{æ{ç.
+bÄ8m)gë\>®Cê³\Z²ŽT£øB±Å[·. )ìSSEIäÝø În
+Î¡|ÈmjÁÓ
+Öß}(1¡Ã^P¢¶H%TÛHÒEý&(>rFMÚÀbr\×NQrŽ"ÙÐëkQv
+
+Vª³ÎŒ×YTÒ'g<1¥úc£©b|
+X©âZ×ŒDÆþ¢t{%eðJÑ§Ò	ð§p!ŒL	€çõ*þï(cfÀh/{ïZ×¢êÇ'!h|Êë3Õ(d[ûÇNÑ
+
+O
+I`uû
+8ó8Öå.)&ðâ"¿&ãæú0Nxoä	 U5çTµðé3(µ¡(Çg4@
+ú	ý("$]à©D"lÐÂÖªC
+÷)¬eé
+ì±ÖB.ò$¶þîIÏ
+ Q
+ÌhQ§ú0
+z
+üû\
+ü'jqÈÆ²çºt¢
+¹,HÃ%Ö
+}ùjÑº
+ë0Ä»±ÚÕÔ°¢*Èè~rt
+Êq&î¥CÌlGV:1hbßèO°ßŸ4VÝ¿UüúÕ-p(Y·h
+?ð!á-ÂÆWŽR¶T
+HÎð!šC§tÒ
+í'ä
+dó@cS)A¹PjkÇækÓ®/Úôté
+µÂ
+Á/šJLBÝë[5×À¶ïP°ÎÚ°\TéÙlõ£:¿LÝùÅ[8!
+²ævAÄÉÞ2z
+ÊÂ&àÔè·,^|ÛŸµ¯þ&eô(j6ø=D@òÅhÞWVF¬ËL5ÌSà­1d¢¡}c¬Cç%ŒnÈ:Áìpyß
+€ýº1à}E
+ÉÀª
+®4ñž%°H÷+cô'Ù§²À=ÿF¬æJ¶¥þÊÀÑD>?@;2ëÒ·*Þ ðÊMu^ð gL<ÖÃíÈRÌŒÚÞ,êšH;b»¬phýyYÊOA;âò,ZÁWìÌ}MÚ
+}¿ÕÜB.9L
+±0
+RÒßrIÖÒÚ ?KXšÞdA¢¢
+²áVÌHÅ¯
+L8jÜfÉ"àEŠ
+MµöÄ,íÈ)b ¯ëÔZas
+|qÄW~q±Ù·EÁDü
+Za
+ãh)Àø»
+9aÓ{ªTŒDD®ÍuQR7zu×­ÁmìŒÃ'~òZP%éÚ0lc'Ž!@T
+úüÆÙœ¡wŠâ+èÓšÉ
+PÚ0®Â¥=Ï^+fe^ëé&YTÜSNp,Ñáµ­Á§CkÉ=R¬2lêÐæ$&œ	ÅÐOª¥R[Ã^IŠ«0åz{lR
+DÛ?YP,ÊzÙG"
+óc PiîRíF5Y¹PòÇ:Æ_»Tl:o>ó³6B$cÞ1vU%o=Äñt\jB±YC©oG_|ªvþÈö·(ÈHŽ),ß
+ûJA~±ŒÝ(MrH
+r9wSz0ñ%ßÐS²øcKÙš_€SèÆ«J·Ö6+geCŸ 7µŽÉj]WÞ4^tYqŽúþ5Z¢?RÊ¡ó
+$>qx«ú
+º»ã/±íí§ ° Ý­W¶AX`Ó1pÅ>jkùßap
+b]7ïùbpT(ÏITVT£õB;B
+nÃÌZ6hÅFb:8&H
+Ì .ÅÐþ^Ú 
+äPŸXBþŒÝPóÚÎzË²~Ÿ>k¬É&
+I3â(%uðv(9Yœm;¿
+Y¡W=Q0«¡*(.ëõÓZcÔÈf4
+®p
+ÐèEâSŽN¿8¬!yÍyA 4~-À°ÂtxäqT@\ lÞ·ÀiÊL1ð2€gÜ
+Ði
+êS+ß0¹æxr%ú0llV.FX
+2V")è=ÈÎ
+€­q)Zþ À3è)rÁ6Ò¿bÀ³ŠR&Â­
+_ÄI>7üŠyèÇj
+ØÃÈdê0EÄ÷$¶!`k»Þ+0ÖD^žxÝ§Ç«v
+Q[SAE\`v¯hBù4@PµÊ[°0*;Ã
+4CÌuJñFÀÎ¥ÂïDæÂËç1ÑäcŽqXgî$
+Ž|/ß¢0"&œÈ9lFx»xCÁÜ@b°cìãeÀ;k ÌÃE_ 
+,2ôî,Ë
+òÜœùpë4Â4ÐÂVq±5$ß/uÅsneU¥`«æÊÀå/
+ô(hN³yçýJ]¬ð)Ò¿°aa3­0¬â»Ú
+1¹ê7Ç@QÍ×
+QÎ@EP3°Wg&]5¯KN/ß*ÐY1mTë{¬>²D
+·KeâGŠ$ËÁ4na¿dFËc¬µcÚj×ÇjjãdÁHš±Ð¿
+ÑP4JÔ5£RÔ`þYGºZÓÍÜ7/Fu¹ÏB¬lÚXZeÂÏÊã®oëK¢©Uþ*Ü¬ÙªÛ	#+Í!y±EBI¡sÕÓKõEè©&G¢µ[ý)žØTçý
+
+)È 1àCJ2RŸjqÔè¡Çb
+úÐÂ*Îüq³¬Ã FaII
+
+ÏH8B
+°äI¹œNÞÃeþsDßq/ìBæ8ØÐ,7OÇÃT!T0
+ÏACë«¹
+^.9æ4ÍB[OâôÚ
+Ófâ±AÔILn¯§ðwêÇö¬qòæP&<ïx$$Î16µ	h¯N}C6ŽBª¬/CBeÍî&ü¬LËªåU
+%Ö.T0-X8¢NµqŠcçÓ¢
+Ö4eÚbx!þéÒ_AÐOþ¡­J¹È©niøl]VÁ€d¥_=
+ÆâÃÖèÔÕ5Nñ"Þv
+wIûO0ÌZ"Y ð®Qì0{zLlÙEêÂV3,
+µ,}ãÍe£
+ÿf)UG
+ Wt¹0É-fQo\
+0o«XaPuF*;îðrš2a,o&€ß¢l­®µá]4SÏ*
+;m·,qUÃ[Ëá?dqL¯KÖÔ>D=¬U&.¶KVÚL©Ÿâ²@ótÚDœú|Í'Ýâ(äªµ©¥NTšRvÔ²LGBèAïÊ.ÈÇÄ²ì5U1Ugï
+»R·ïLí `ËõBy¯ŸdR
+ùÈûè=Üð®É	_3(BQNv¡M
+q*eÀW/Ôóÿ!ŸÒTF)¥¯&}äÞ¶¯y»Ïë{.
+ M	%AZ ¯*z9ŸŽ«œ°Ø°2ò#Ž
+^ 'Óïïæ
+|9E_£
+šæE>Wu
+"vÎVÑ.€
+#Á4 stÁQj
+wt§æ+GšP§
+/êäµ(ä|,5±Ì6
+7g|9ÎXè5¥/¡¡í¥eÛ
+Ñª€z¹uÃ¢dßÜô9dGÙ°^.E*Â
+ ]ö/ú»HRð}Æžs]Ú	"`;]77rõJŽÈX7ZJtÔœìÌ<ÖÓyK»Put
+Q
+So×f
+Çs³3ÕE{Mysµ1Q
+ÈrLI>:
+Þ@o€`ÃiLÈÛô&
+ª»¡.':"÷(sF»mÏ&§¥º9ûÊÉê ÄàØ I)
+µ+þ:XZ~oLN!éDyô]mÆÛÍ[
+¥ÈÞÌ7_Ðåòº·527MK©qšO I®éÌ§xPÙ	0mv°ÛÑWùµOÒ*nÚa/<µ3¡*kÒŽ;ZÔkmÚÃKÝ°GÁÎÞé]î tì%« òI±2Y09®Êõb
+ª"€jB\ÒÂ%ÊbºZºÚX±I²Õ¥Eââ,Ò7¯«ÊZR
+7èŽ#¯HÛ8Å<œÔ¢é¢®nLAãv-Þ"ý£æ2(ÀXÞ.ÑÅ²
+£4ÉyR'j$Ž.Ð?µsùà%>×cºµÓ¡ü
+ÒLc?a@â`FyŽèëX
+êËåB?äÆœ£hŠ$kXP²£ŸeçI{¶16Y*K7³ÔÊòAà^)ãÝÚzæ$óÖre0õMeÜÓ²ŒfâKÅýôŸ³-õ5(F]LwÌ*Õ
+6óè<%+ÕA#¹UÏÊ¬11Cž*hóHþË€
+s
+¥ËQð
+³ÉÇÉF:\CÂýjÀÉË>æÅùl&UÒ¬*q*ë¯)êBq0J'ÑÈLF¡ËqÆËp!%òI±¬Hép
+¬K~£,ûÎÇ7Ý¹5
+«èkXñ43Uú§ºSß=þ§êJð;1*à-Dà]R'²ûjòSPu£
+}·*
+!èÓY@Â²^n)
+WAIqnPÄFNU)
+1(YE4Þ·Õ-È,
+64*ñ«®.'ckÙûÉß a	ÚL²¹à<>Fáw2èE°Pø1Cz?Þ¬è}¢pŠh_mIHÿ€Ç×.1Á
+@ŒÅ2Ö
+ž1G
+p»š"þìµ
+ | Ädd?o¡a€YnåyBöpM:¬|ÌêÇiGVè¿YÖ7Žª_Œø#ð×5KLtpH,âg1¥
+ß§7å|§
+Ê
+ºøK	ëêU¯šÅ÷Ðª ÉL °0,;oZi¡ÔÈÄbûê8+CF
+Ló(qæzÂûZévjÇ·å
+²A¹Wyh^
+SWÒú\ª]¿ÊÚwO+ÈµÁ÷M«eD
+Óîw'ø{38q75ÝÍaÅÈÎ*B0¡PresJFŒ >>_^³Â`Ç`ýøò9ySÝ>øçØ,Ia'Š ]rË XFÿ·]PÍ
+(š·-daÑÆlÁJt Á¹ö0%?ÃÇö¡[êÐh.ø·G>**-â@P0v»èzÏû%(¡Ø
+Én"Þ×þ
+v×á4-íàª^Ë w8"¥¯
+×unsâNLÒyÐ²ä^ÄËZBßáâEïV&è;g.ù÷àªwÅ°Ñ
+œuIè
+LÂ·§@|3k(ÓÔêªiZ@Ö±¥kÄñÉsTßº5ÄYhuPÝz	£
+ËÀñv?{·OÃÝ€X ÿÑ"óµG
+óô©rÙú}ëßShGdqYÉ0ÇÎ
+%à*S¹8'ß]5"L{lkfÒåRXÛýó;ŽÙ03Ü;8ÕxiÂBÎhyÚ ËYV9FYôÛÎmŒ¶Ugói
+SžÂõ¢ŒÖE2.GãRé·WÆgn	úH!µó%
+©	'fÁö)ÎaÛê"ã ïäÓÓÓDš5UÜµØKq(þ>£B9
+®zûmßñU|R	 1šg}vdÕ0ñ,gC²Ð 
+*ùP6$£úISFÜAÍÇfYÒ­ñ©w¯|c4©LØâ&î^C¥6H®Ñ##éÄŽ$ÄD
+5pÍ&VçS\ªDF*rrÈÞ|Ø]o¿œ Y_wUÛd
+ŒÛMYžµº
+ÈÂg®}yZs/àÙ(!¢6ÀåÄ­âßáÌ7$
+L	âÁx1Ðâ{n^ÕÀO_þ-^ÙØK7Ôä
+M
+ôÐž7ÌÄ4!Þ{,Õð7/e>;Þ³žwãdB­<
+!OÀ ð?(¡AÀTàA¯UÀ WHj¬Ñs-ÂLäÓdMg©d
+b4á9V±Ò(Žvéïm<u
+fp2Ç/Áð÷ðF@A0H3ü4,mÇâjù_­ã·àäÉaI
+ªYCÐÎÙÁ2Ùè5^^)sÏ
+Zª{H
+¢£2Š­[¢ÝTà¡d
+±"»à©ùÅ@°n	0€ºœ²kµAx)ß^w
+CºMëø	ED"=tGUœ5aéàÜYHRæ>>ÞfaÂÁPD1r·Ò±Œšhãd^Õú#TéAdLg]lãHåšPÎëú¥È9
+ÅÍq{bº{ùÙÄ£k>:BQ.	3v2QìAdb×pËPD8un.¹
+ÀÚŸ	'¡ršhE&ìähé!k`»Öçæ/Y3šæL ŒÜÛg	ã
+
+ÀŠI)©
+§Ãâ³ë®JÅ8KÇÒ~$"
+4<í±%ÇŽFb@UPs8ÐRg¢;ÂhÕÈkpµRdAïEbè$
+Å
+ëVº18ç¯ÃmjPè:Ïú§v&¢:,.­Gw+Ã9Ö)D¬ÛüEð|ywÅà³òIq«¹º¢zZQ0a}
+e¬©5Htpøº@p¬··ñ-ôR®£-°·Ñ:þw(=4cå°
+[²©€W'äE(ÈBÚKµúÃSŽÒŸÏÅ3\ty×Ü`Á­Tf2(m|Pc;{í#(@Màpë ³6}öè+EÁþ¢ìi$Œ
+
+lCÐ±®të?ÅR|HÈËÅ±;ÊRÂxú43
+a¬ä-
++ ì[0vá¿Í#
+Ë7,}
+ÈËË.±
+£
+ua¥ì<Ö6Ò¬,-ôKø4ËkP³ÃNÆèIéÐÖeÕdzp
+ŠüµaqE7ñ0ëK@&M{é!0ÇËc
+È©ÄÝ×2Ì­Ånäí,[6;ô	Éái9|ŸÇ]×aPŽÄñþD	áÀ8¶X
+Å:3ÒÚãN/iãÅ
+ÞL
+>X-ãBgŸíxöå1z'¬%E*è,ãÅ¢_Å³^Ž<æsñÔ_tÝWø9®cè?f95õËâáATþt1xç*íw3/áÿÛ#Ùjßù`Ù· ¬Š[4À§Ö×wÉæÂ
+Ÿ;'ÀB°ì±ïÊ»~<«Àbmx\:ÓBnjAõ ùGþ
+No^³¿YÐ%#HŠYþM¡?kÔ
+îyòz»ðc]µ
+Ã¶c 
+èi;0Ô
+vxŠG
+J­ÄMîÏMxUn={\ÆuuSY)45ï]Šî¥Åñº÷ûåuçÙ
+Â×us<ÄEúŸ
+ÃR:ch|©Æ'-Y.ûÓÅ`ºZåg²PÝò«;em%U¹ÃÓµL4v·Ø5Ž_û!IñE»J¶ðg[jvçL*&
+>BZÆÃÂOñ\ºŽtÅ­÷_!
+³œmnÞa¹kS§\aù;Ãc; O
+a®
+\ºtu|¥-iÂT ÉÅœ»Ä
+k|óñ«·ÚPžÞ·ù=,{ó)F
+@©9¿F8I§FRÕö¢27bS$
+ÈLUEt¿uI,äÑ$ç¥ù)ZWœÆÎÁa?
+Ûwé×üâžçŒŸ3ÎÍŽNI9ñÆ»€=ËD¯N)J)ÛÔŠ«k]-&eì~3X<mk[J8ÿœ1Hk)4gHD%ºpk°È;ÞÂ_Ýç7áH·]Ûø¢Kr¬ALšE(Ù MæóÓ448ÔIM
+N27}
+ìZ8ã®G]ŽhoYd%#Ô_2`Öî|âÇ<ê£áòE°Í`Ë	:6M&Î\ììÆB¶{ŠoYs/Êž7Ø
+KžJ¢ÍJ'4b¬È³²ô
+Ö°96AèN€,Ž«7Ì€fsÇ E÷@­îcú%GÊD€P9· P&ö|B¢±kß
+©o£UÄ;üâÐÑò;~iqtÑ[c*5cÊËXàTàKµé¬rt­ùûÎ@Ä°v.Ï«=µó(¿çºVë6hq®õžy.AìXV<
+bi
+i
+œGKv7B9A&êJÅF1°,ËsÐXR`Ünïè·w×÷)ž1ZL
+A÷0N;® í¯U¿²)œ±ÆðB8³6¡_šš[lÉQ¯]iLÐÎ%ÁbÒuî]v*t;Yø²SákAwí€á{ø>oý§¬Ó
+/âN§oÏ`#Òž°¬yÃÌc>IKûŽ$ÖË
+ïûÜk¥Ú ÄõTÃú$³Ók[¬{k© =§t5m[yo;r­%Ã¹-wyªl0GaÒÐñ­<Å¢PÎR2ÑÎl[&¬þPê|¡ó\0>€?®.¢-*mÏ2OgÁÒžÈK|Wyx©Å
+vÁæÏ£yÄáØBçèðÎŠž
+_?$¥¶OG>¢ÎPê"á\Œ"Âf·gá ¶i ÷Þ*Ù<Rq£TbšÝfà`}ùclæ1
+ÁtžÞÛi·{sfï
+ñÂ7 
+ñ
+LÂœäŠðoé¶Ì'€àHúDïÅV©àcG®ÐÏñ¬HjÐôªm4Fqmµf^PÎVNUæ~âœòVC¯ø«õ¥Á\4€ù!YúR¢ìä°
+ÂæÇÒ7D]7x46Ÿ|ËÀDµÊÙORŽøY<-%<FmÑÅö
+Z¯/Ã#ÂªïÍÓÀŸ€T.,€L$I
+?9§Éñ	Ð#QP
+;àÒ¡>Šµ÷f]
+ùAÄÒ&7Çøw±I~Ï~¿cræaV
+Ênœãï¡$šå>`ñ!üß6RQ
+¹æÈøÓOŽ
+@¯hr}ÕlBìxCôJ²;ïfdóóÙÎœJÃ?Å§5Òó~õçÎ©ÉXRÓ"È|VÈCd^¥ýÁVHé³ð}òá*
+Ó~Ïm
+ylNÉ&Q(V&çm¿Äöš?Òç!á­LI9#¢£ Žkn<ý^ÏxG5sRÑºâãP6ßäüe+æïÊ²ÞÕ$sK0®
+cGŸyšïÙ7>¿ÛŒUá%GìþbŠ8øü?ò
+Z¢É¢
+V¹}gT`ÁÏÞ#õ¿Ï(m+,
+`þÒ×Ib€áñåÔçÆÔ¯4Äz
+üfnù£Ö²&·à\ÆôcGdvíÞãÂ
+ÏpðTGPWðŠËxÿ·Ä¿&ŒfÆ
+èãa4Q
+#}7va/°K:F6&¡§7 uÚ?Ö
+(ÁíÐá-CZZ­ÉŸSäiè(3²Ãå€T3oÐFu©éZGhÈ-$v
+
+E^orýcØFcÙ­UÁËÆÈÓ2 ú8^AŽÛÐçwôÓó¯~ü±÷ïÒûRÌÙ}åzè3rGÐâZé¯ÇÀ9÷¢ÓýöNáKßÏ`Õ.r@rm' ÜðúA
+¹SL2Xpà_â ÕÓî1ôÂÖÞÍÄ©"«=hà
+BI¿áww	ö
+B0jõ
+¯\ät±9
+mg6ùãWð:È]ú
+.
+K,
+×
+­tcê!î
+R_:C Aš3°ñž(²ïMÆF[D
+,ú&€?ÖZ­K:rIP×ð-À¶
+ÏuMø]¬£.0~C
+Ð
+µC<ÿÎß§À¡¯DÐJž
+
+Al[èhÆÇ¥	J­
+$áÅËGhSýû8U<Ä¶c >ËT5x
+É'økG¿«+ïõ
+2l^,£#úúó4Í$iœË8Çû@Øã7c&#"Z`yØÌo(Å.¡æ+H×ÆjÖVh!!ÍÉóî,š
+ðëÇ8	²-FOPÔÉHAAÒ,(ýÉÞkItP#.!7Úä#ò
+Â+QR²j})øÑÊxô³1X®?©q/²Sc¡ÔRI?nàfç3eÃ=ENÐ?Uz ±&¶F,ÀÂJN,2Fz5và
+wšcó@`#£K ÍHVIû&ùâ«ÄôQj{Ô.Œš+ÅO±"ë>(þìrÚ  -ã
+
+L%|RdpAÉ"åü£B`è*j&lAäÃ%%r+É
+
+i&¡n±¡ÓV$ôI¯eë=SbJÄ€BIÑÍ§ePÂ|5š71³ÊZßÁ@"2
+K"ÏS°]#ZfŒ¿ÐKÒ.äwkÔÄ}!ÁXÀ[]\÷e€÷g±æÉ¿tKê>Gþ)D}ãk!
+`$UBOÇø3¡"07
+p¡)JT
+÷gë¹·yçø$®q£¢%©}Bè2Ÿ¯-ï¡5Ù9ð@K,Ðo*&¶
+Ô[º÷uW
+=Ø"øè{wóaþôm¹MÈþr3ÛýÆ¡§t»W¬\ª`6EîE2åÐ}2AÒBð
+wC€Ñ¢6
+R;ªš
+Ô8«{äfs
+­ŽÕb. ,é€Lpm~­úA{êÁÔ¯ÈáPJ2
+à
+ÑÊ¹`Ži
+
+O,TVÃH,¬GX¬£ö¢JŽ³¡IþüRl.é
+
+0¡OòÌ±¹È=ùtÊâ7öµ50ïÂ
+
+Dîµ
+DHm­{ØSÐVúSc »:=Ý oM
+£MH±xsæP
+ÃeÈ¢ÈE^NÃ×Y$ÁqÓô+Ze 
+xåb%ô»u*ÂhêŽõK1
+sŽxTÄ?M GõU¬<SÈ%B±Žz	ÂŠÄjwX×aÈ×Cg|;8ÎLêGb`Ûšý!ií!Y­¥9°x°ß\
+]ÔV
+KÊøÑè	ŽG§Å4£5Tõ;Ò$äÑ²KaŽõ
+r4+OŸ"6Þao=Lza
+TëšQg8QÐ
+^*R/êEBlk{¹Âgá+'Çtý¡ø;X~ËH(_FÊ8 HMÉÂ€ABÁ
+«út$Ì¥Üà¥ßpÕFL	nF qÅiìÜW]è>H<¢ô c ðžAnÔK,í8é[kF'iÝ!À£G+Tè	|gCÐî
+_âÖ«jui.	K 4ô!y-61þÁÖCÅ!RòæšfkfÆ ¥ia ,Á|,<'ËdA!
+1àqØ `]%ñÀù
+C"u3÷â
+YRu¬ß€;.²V¹Âó¯õÃ€èJÐjÈ¶á8@6ô
+Ô~_C9ãGhàq×ÐÒÀAÐ®ŽqKw
+zú»ÌâCÚóhü7ê'.¶¯©*ØÉ÷
+Cb1ÝfÌÇ¹ ÔÜBì<4œÈÝª4â	ä!ñä7â
+0P$#š7ü¶ª0Ã~ÖÌPYèõp¹Ô@Û¬ÉáÕ-±8
+
+k!l!È2pòÝ°Z`¯ ŠÞ©çzwëâ³ÉÐR
++	^Æ"m¬³Êâ^Æ¹¿æKÛê7R.
+â
+¢;1<ÍdY'$
+86LÌÂµBîEŽá#4b:­
+(ØDJÓèò
+,`ç
+§<0æTEµµ\óa1@s4PÂÆY³é	Vî¢TÝ«Ùd\º^
+¯BNð^Z+höL
+N4®gåžðHÊG ÉEJ§EBtŸP,&&E
+4dÀFÄoëp­
+Iý§
+Ôì.Œ"f3HAÂvè(ª2Ð>Q³4ÁÊ |juæhoSÏ5ÃÂÎX;9@à!$ÅÁõô²`dh$~\á@»IU4Y
+ãi%þ)@ý )ªqq/9ÏŽ
+DÂcmôNAë!_
+{xWê)PŠÔÜ
+ñ"43iŒïp>HÂ¶÷ål~bo@æh-T8lïé7Žz5íG"
+'ÁÂ¢uûè³š
+¹n$ZËV+  \áOL5`
+Ä¢ÚG#r7×»ž`eN­¶
+sm±êHrñ¡rër>ÀDyÝãÄAôÈ7e
+YÖ.qV@ÔXÌqÃpp,ÛÐ
+¬U	häá*
+œþ^
+kÕNÂaQÈP@Õ²ÄGä) Ä÷
+Z!;TGÎØ3"ÊžAZãøØÚŽiÊ*ÞµæBÓ8,ïDi
+°HÿÔ»B
+ðÔ
+áèÞDÐÙ
+$WÎa¢qD¶øS,xkÑO2{C*ÄÃÄ·(÷E$
+&Úv<1(Oîû)ð5Ë-ç9L#I9ì 
+ÃÙ'œú8
+Ð
+
+VV
+ñÉXùXÖeýAÎHÃlø¢HŸ%yáÆbù'È%Mœz
+3OQDõÕÒÜz@6(ÔGÈÆÊ
+%žÌ¯Ôn.e8ð%*Ú"2ÍÄ5ç0J*Û¹=*zt
+©E±xæª%¹ADf·
+ú©È\j#
+Â
+íÃ·¡ÁFŽz_xÏÓ-°aÀÔÓ=gG
+É`Õ³,H1i=×_îv»Ò.Ð
+uf6Å¬aW±V
+â­
+õE\*k©À×VYtæ
+5©§
+2¯h@ôùT¢]Ÿ!ãPFÃGX
+®|ÐxþSáføp|¢DŸWàìv 7ªÜž°p[Óð
+T5_TwB.#¿ÐR ãs+^Qv
+
+@Q>€'l5
+Ù
+Ä'T(X;è%t«ŠÎLïÏVÓÍüÑç 
+1'ªîEÉJC
+Þ¶êú
+p:m
+é"l@ÂXð.Pæ:Y
+ãlŒšgðcü
+$¹6
+KâÆR[-2ØÜDcÍ}À<T<¹&](
+	ââ	€ÕTT2E
+_œZ
+*!XµbÁ/a+t|ÊCHÉÁùµ\<n)D94âŒTçSÇx(Ø>8TpN€Ëûÿ
+4nY@IóG~ÃAªheY%?g 3]lH
+ÛŒþÝéÙqÿ3èù.
+Ù"ÆÎ
+g¬aŒ)6lENoºÝI2H|:0æüÀ,aÙ%bgÀ¬É×l¯~×oØüNö¢ø hÁØäË
+¬©6qªPT|oGAGÙèµX.9	KB©B
+a°}25­5Î5åÕùøèOú
+ôž¢ñ`p¥rtõLØ=
+=Áy	XNÑ
+jD%}jÆRå»S0<ÜEãÖ°YP§ÑÅ·Æj1Î
+š0rŸD%îÌ
+ïÐ"»hEá<¹8éÏ|A,d©zµ]_èGØæÅ-ÈA9ÚF&K·âÃ
+ÀEHE:O±TLø­ÏÞ#zÅJI£XfG€ÜT#ÌÀï¬w5¡èYü=
+tÜŸqÑúÏDn:héf]Öè~ÄzCHDp
+ôÅü¢ÿÂÑ!û
+ÖÞ
+ã=ËIÁg2Í áP^­ÁwÅ"B!b<·±eCÛ
+	A¿
+R6XCîk
+
+ošÜÆÅñwT4D=	
+r"dÐÂsXN;ÑŸ§UHß fDg?££«#Qlžðàð¢-mNýaE
+t_P#GIapsøHq@ ÖŸ
+hÑxâAà#^
+ÙpÎSP­Jc(xtUæ·éE,t3:V=¶{VE
+C¡®üÉU@Bà
+P <ž16KŽ~"ÉÑÊ*W\
+ {
+ QŠi\?€c
+ Î	ò
+Z
+P3
+3ÇŠI)¥e@žf)$,"FwÈÏcBt4ŒGÈCa/5pøY#õ Z	u®V¿] 6:.^5~°W$dÂ
+y:§
+DÎ5+J¡Ö&Ù
+úLB_Õ
+)åéâ9=Ñðæ
+JxZÁÉú%2Åj'#än \Ì_»lÁsÆñ9°H`ÏÞAAQGdpØí,Rb-ÇdÞ£÷I@ Ñ¿
+£q@ñ_ì¶è<²<ö=b¡'µxÞi¯DãåÄ|'À	
+	ªcáŠf[2/.'Ðô%Z­ á
+|"r!7f[°Æ:IënÓ4\Á5ª²8TþËL¡ücÀm'FdKÂÂ  ÒwIhd
+,.
+£±Nî	ïCl¢è;PiÎòc1²7Ø	6wU"'<*=[æcµÏ
+ÃÅ66ð]-ÀV7íùgq³Ëò'ýZ6GnH]'æg
+û";ßcã±S ê=(#Ô¢à°ÿ·³³ÒÀ"þÓÄh«	ÁÌ21ÁÓÞþÏ£¡@œ<€1«ÜN.0KºÒNß³SªÉ AU,FãÃ=Ä685é6N+2Xåb¶ôÍ"K;ªmã@\à³ñeq nè
+ÄfÙ®C¢Šµcá¶ç	È/* *7	qÜR
+$èÕD%š8ï"öÖ¢w#+<#€EdZ\
+Xí ÎT-i²2"/v1E¬Ø.8ø"É:1`tw"#
+ù-r&L!L
+@d$3h0TÅ]¶b¯DaŸÃT[ìíb<Œ 
+
+ÊTâR~
+J ÆàÚñÈ7Ø{= öNå@ØfÌÙ œ2B l62árÈêÓðdgC·ÃšxÂß«LxŸ0g'âtàU	-^l¬;CXa4±íŒð*	/RHögíh
+Ä6¢(G+vC¹Ž
+! ÉWñõCr®Å!:a7eÂid¡
+ð
+4¯îÈ%FŸÌ"(
+ÁôŸ
+c"7Ihoõ8aà 
+I¹
+¿glÅeºÛ€%EreBHšš'ŒçF(ìÄ7á-Å4i6NýD%KÑa?qV'³zÍÎ*~
+æ÷D0ø¬nP>d_ê»ô
+ÌÉüoN
+10cLD&~
+ÇEóÒ%ÁNð\šªÕ6Î
+ÂÌ¥l;'rO
+c06X:äòúK%
+-
+ÒI-ÉPö|äÙ  Æž¿§Íp=\vË#ÛgµsÚ$iLsÚ2£àìÈâcÃhøF \^ÒÂÝrTžÄ-&,cybpë;~=â>Í€ãÒœk3|¢DëÈ¥\®ÀB¡
+( à_çX0Sae
+7
+ï#ï³PTïg
+ÅN?1P ÊY$¬>kV!Gwê
+¶,Â#J PWuÊ±=nÜi#ªSi!òCB¢ADà5à±×ÍëpèX0eÈ4T#%J&W7ÈZM.ÑŒ*°²
+$:)á\õ!ÿ¬,ö1bŽèOTè8»¡&ÜÛµGH8Ÿô>gPÓòfq[è$v>
+;à)€
+Y)6pe%d¬ÚHÍÛew§
+¢Pj¬¥óÏBÂD¹~UDðžÍÃHä"Îq¡8èF'ï3pèBàüµ(¥ÌÇD©;øV\ýB}E`8 £ì
+Œª>%µL
+¹
+RßPeùIÊ1t
+â	Š¹çGìJ
+5g€¹ÆÎL{H#Pb ïn)«3²BVñžCÖkµÙÚ29ÂöG³¬	^ž&Ñ­Àé¹­<¬}ãÈLËí:cåã'ÔmVüªåÙìf
+sDxb^J­å© 6÷Qx{n*6ÁÝ¢÷WXhé$|4šüõ'29é>åº D,®ôÚ ø~®!£Ã²+6XÙòÔ+K
+õ 9PB@ÝÈÐI
+9©Ë24PvsÆ\iñØøVGäj'YŠŒ$ÍâÜä¿q³Å€z£òÄ©êÌj`°
+Ä[[sí£.øÁ ä2F$K
+ï8.lk¶RºÃuÈ6VTCYH<ò²%(G©B­+Ók-³ÄË<ž3ùM
+zFJ»Í_£Ecm	Š
+ì©ŽÐ¡Y£«.JS,
+Jô#nžºó¶?ŒÇÞbåòþteäsÐ1~9öÁªI9!Ó0øèdÃÄþ!Êæ°º}07Š1â
+É
+7ÕX
+ô<d2ãßdØÖÆù¢ð9Ž·	sdré)p
+B]#[pïfTAU¢ìÊ³q€g€2añµå®g@£¥,"1SùJtªX(2|
+dJDù
+
+¥KÁ!ÑÙd)§/ Èäª¡
+!3rÅ>`ŸIáq$Ç£È}b]z¯4]
+óYc
+÷²MŸO¡ewšEàÚ@8rãcQäy(
+­Ô@à#ít3i)£÷?æû.¡è«Z÷³Qd²þ@<i	Ât
+äÓµxüµìì;Àeh¬äHÉûŽ4øYÇuðÒh&	0IvÀMñ§ðcCG<;Yòõu§üDö(K'	,h	Y<- F
+h$¯}?Œ²$
+ÈÀÓ§Ë¡Z
+wj €FPjU;ø±xo®%cÌóÊÈ¢xú8zà
+ªÝ²dY#hVMŒj+ÀSa¢±±Œ,BØ@
+ÄdÇÐn«%Ø_i0%)|
+{£ &Ð0zÓÄÁ#
+åü·Ã
+äôeJ
+?°¶Z°T
+Ã`DáÌe)$öÀÐd1Ð7ËÓð€N
+CJ^ ïE$óÞ%bVILC¯ñ­~ÃKŒE
+afÙ@\YSRvÀ9
+§òà÷Óeêœ¶pi+L3ç¡é9šKÎgg'ÇDŒ}å7n<c¯
+
+î©Ñn°ü¥1ó00@
+îÌHë¹èHõ8dz#ú¢bK
+ì+­9ôÆá
+LÈÅØWæ^<	
+_È *ÀŽk¬
+èA8°h Å«©»Ì2Ç@€KCáaÃÀ?_nºæ	!µÕ÷ËÀÔ]él($
++
+
+CÄ¹
+CÐÎLôùCD¶ºJ³ÇGyÜœã7Cif§GËãMì<ar%X¢
+òÐªZ(ÕqŠÇsn>/iè@
+Á Ç7RÆáMî,ÎÜ32<hÄ[æÍ"24QLÂa
+é[xf 4°µóV3o¬ãÀúå<Üön- )*ÊrÊ¢!ZdíüSÐñìÆÚFÙòYŽÜLšJË"ã%JÚöq
+&-^þÌÂoÄ!µiR5§:,Ó.«)Í
+Þ#Å¬ëÉ£R¡©sM.è¶ØK;FŒ°5çÝ&!ÚeÖw4
+?
+ "Ó€`ü?d
+r@_Ï!(hÁÐkŽÎ§Ä
+eBF¹ª¹¥xæICd
+ïK*@*a-×@ÂE
+*T!ÖQXNëRŒC
+
+8ZzCfßfé"$
+µ57#äþHÿqÁTe}ñ¬°&Ç 6gsÉÏPADÚ
+ÉŠ%!Gp0lÎÁÚîÉŠ5¡	7#rvir£œ€y×1ªŽPªØÝðDûYíd	'j¿A°Ë`a°ïP0ÊçBUs8Qü°$À[JF(	 9=\Wt¥€ŒïC¥T[L gÄMß*4£Ž€D]
+S'ßEò¥o Â£*èÿJS¿ÏÚÅ~I\Ä#Ð
+ÔF"[¡Ñd\>4"C¶¡(L)Q%Má
+²Þëhª5Èg€oCL'îÐom*8¬ñÍM²c
+l>^Ñ+ÙÂXb[7x,2 S*É°¬3\Cä
+ŠÔ@Ì
+áÎ`/;"`ûåÃsæg÷;Ñ"ÂbÑ/0ö2F·'[LáæŠ)E`h44{äãÂÔ ò9RB!Ñûf~ùîÑ³<
+ bÂéyüòiæÞ@d
+ÈÃž|S/«+g¡PÇ44Ð)é«M S°$6
+O§INâ6 <
+­`ÄªÛEc"µÎš%àKNd$€@N(Ž:Û
+ËÍs[¹ÓžÔ
+Ô|S&_¡V"(hÝò$ø%Hçp¡
+°ÿDÛq
+ŠÃS +Ÿ$ÂZ 
+Öwµøh4µ
+Æ©€9. f
+ZµÅÊ,)H%ÎO§Ã¹-Dú{o
+
+Ú®%¹ŸzqøÀEÔA^dqÉba
+øyè&R^IÚG
+Lïo8Ä:5ë²É=[D?$ZÊrhGÒ
+n«Àà è¬ìýRÆàOS
+âwiKãŒ¯"_»ÑttbÁ2Öé*ŽÎMàÊŒåá¹JÜ€<l1Î7¯@u·Ú¬$|ÛhJmœjÄ¶tû»7<ÂpÞð0Õšåèà9ÒDµÑõSä
+rzOþÑS÷h[äs6oõb
+wh8
+~4&`=9UÄñOaòû,
+?sñ}?aó÷
+»l|
+"å¢Ü'Ó ³Ìrø1ÒPŠª×gÒn4 °æ¬V°&5RîWÊPJÙà;0Š|Ïâ£0DOžuŒ'ÊE
+ÏÔ!Q<(ÝL$ÆÑhtÒ/R¥¡Î Fä2=ìÍ®]ÓêÛðµ
+IŸíî<*ŽÚØgôOV±
+¡öŸ°ÈDÃsQhDd |ügbà¶JÜÇH<Pz	Tæ/àír/@§A=â£:ªã9\]3òÝMufYØÀÜkÄÙHfyMqW=&Uëlm
+ÿsŒ4)¥À5YëüµdŠÌUóÊµFÄ]dI¢V[Î[&Ûy
+ü¬nb»º1¯åo¢w%ºÏ±.£èBiòéóèj¥¥éË?M>¹râÊo(Ýö²à©õðtœÇ|0 ßPuÅïMÕOÐåhÑô;
+Ä3×uš¢žŒ©_ ýIZü§ jeWßš'^
+ywìÂË1¢!$¶=LNKÈ¥*0
+
+­ÔB§
+"=ÏÙ©šÆT­Ðº0P®äæ
+¿B
+ÌBQµÐ7Â-Ôú4!·Ðf¡ÎZhž!
+ÿd
+¡Ú ç24øe<ªj¡<öÅ6NLL@ùxæ(e¡@,œ²¶Àþ>¡Ë^èýçÐZýÊÜP7S@GØpÑ
+&9y
+ŠX\þÓrd
+ÙõØ0(AÑ|VÊàH¬^%,°PIÌàxsD/y¹ŠGzNàùZZRCÐsK\À[§TÓnŠ&
+â%(RÏH9Q9ÁO
+Å3myþhçyð*}\%JãWIÎ@Mê&ÈXÎ"k­ÃBŠ3(BUqºuïµ
+ÿóÅàöý£ÞnÇTÊd±Y€YÜhÕ
+×@d©lª/çYÛIwÈJûÐ{}Iä;
+d5áiQ
+î¢bF
+A'oÁÊ7L1pb@
+ÄËúãÿÔhJ¶þL@O
+Ào3¡ª"H,
+{QûIy=B0Åæ	*ÀÚ4"bHFìòh0ZþT 5Ê³<q@}Púß#
+pfeÄBÁhô>(
+(Ðíæ2`³sÅX,S·6°Å>ÅZ$<@ß
+<Îšþ)gÛ£w¬v
+Û²	Å)3?_ÐG[éz
+,@Ã7Gå§­Dæ%Ÿ	,ö¢ëÀdfo1äêrš×H1I>Wö`yf
+I\	·aÑÖ§l1åçðÏÄ£ŸªÒá¥œU°E³6ÅàÐÆØt?ô<=PæÂpUÌŠ@^¢	J0üI!X5}¿}NøÃVT2(üa
+3êFe$ÔIIê)q6
+ù¬+Ë+Ò±`¡Úö9çÈálHCKÀ.^J
+HŽF{ÀAEäôì¢2qÃsÀZÊþSÔügT1öÙcó;dØÉÆðUûÉ¯Lš.À&ÁtvÉXáø[¯°ë&ÎFànlºÕÙÂK³Ï
+ÐSCö"à6xð/hc.ÔÃzEÔ|O,]ànûI DCY
+ØºTÂÍs`XDùÌÒ28ÍPAúöéT-J€Ö#£Q	ã@XPbÔB«E¬ÃMJÂ°ìÔZFÙ#§%
+ÄÎ.€1«Â"
+
+ä±÷ìí5'.K.ÉÜóÉÔŸñtZ
+3PlÜ÷PžFzjàŽ
+ôÇ²$pÐí§¬.ÊyäÐÂ9_f}ã\Ó~>>vÓ2ãÓ2U<l%((¯ %aC@€-§ šmºf
+nžÄ
+@th0²Â$iËÒkTçœ¶qJNô&*XÌhðü!CÅc!Ž&Ï»`JñGÑ>LR*+œ;>Îæ4.ÿP£=]ãÁ¥ bùAáõ RôR1`gT HErð (åþ)Fô"-jj¢Œw€ßYªÚê:Èhòf}17HtA?ÑöàÜ
+I1€°¶Oå
+weq-€à2\Öb)ÂníÂ²A
+ÃObVqSx;MEKÓÑöÍFü4ä[H%Éxj`°ô
+*bÂiTQÊº¿ýL€ËôÇr!hê
+ç6mZ
+MÍÝñœžP
+RŠd¿qÇç1Ð07mddhºÄ(šC+Y9R
+²oÆÙ±#bÂlAÑhé^Ë4ùÂ/`äC8YÉ NÇ8TOÛ²èòg%úÞîÑ4ÊS;ÑDa çÍ£©
+S
+s-}\5Hk#€
+µ@9U|6Ôv¡b
+Ò
+®-·UdõRzÅ"Ù§èb:2o`Lœ¢©^ej³#õs`FÏgÄ± ð»ÈKÞ@ôís¥3o)h¬F(€#kê,PóúŒ
+íçú@PÈûr¿Èèî3;Êi8>Å1ú9tò6¢SN-g
+@ö ¿ŒMÝ!XBaÊÄòÎNÛÌÞÕ#ãèLÊ]§m×PX .¹ý.N
+2>Å
+¹s&hÄÀM(f×ž@TÈ+Z²z€ÎEcw»ð6uÆ}pv
+WÀ ÷=ñN0š
+Èã4*àùé¶b¡€C©g¬{
+âìq7I|È(á@JÀ¢rP5šÔ^ÁU:GðÌÂª¥NHïàEê{svüf¬bõ³¡1Ïl8Úl]'¡á§¥N6L¢BBC­ilÈÌ«ÅÌ`j
+šéE
+9ýIÌ[Œ«kÂz!Ëã
+á¢ ¯WŠÒÝÕrq÷4È²HÊ¬	Õš`ð§tj74UaÐ
+ª²	-ÊQ¹¬­E¥éq€¬4ý0ü)ÚÑ/¡= 7ýiXpS«àâ]bèu
+©z¡ ã3ÔÓ	Îªðq
+ÈíÂ
+§OAWìòõç«N¯Íh@Ðã#<%\ÖzÄ
+uÌØØ
+
+
+Ù>I9Ìòç0­Îù4%îctÇäa
+J4}íD.°
+;­¡îA#u±v*ML
+C
+-s(Ž*y
+
+Æb	
+±51
+Be;±»È¹IÀ1úT$>)0
+ç0knv|ãeàº5)ùøSÄâÇú€bYíºPV÷+§Å'ÀCEÌu¡ßEUÀWæ¿Úhºás!Ü%ÓÜó2;óvU-T&V èî>'Ò"(Gº¹Äšu J«
+#äÄS:fâÙPþš¯ª&Ègæ#ÖózŠÙorR¶*FáÇ¹­Wµ@Ù{'è²èã9XLôX>
+Û
+rX°ë(qÒ3ÆTÊ¥ñ_ð»0È'(¥3\Æ8ÀT]8
+`ÚOÉJJ,d& ?Á
+¬?ŽÔÐiÊ"£4q;~b
+š0ó&È
+ôx82+kÎzæÌU©$$	wŠšJ}
+«ÕGcx×ª'
+@mª¶ò8>eŽVÀ`IelÐkKHÈ~ôÒòÌ.³ñYî	%¡wÐ(
+içûl B»«°«]&PøFOÍa9C+­] r7>ž+~,(,®Zê41¡%~Lã¹[u©óQÎ°zñ®©ð
+ðœõKÕ3À`fõ)YDÜ€"¡ÐG,ÄÔ2ÿØ 9v:š>Ç¢qNáž}>Ô£eol³§F
+]X>i"¡¶ðXdš@N5^/G47|Áœe/mjæ:ó0 Äq,~û8èÕï*ö#ŒªS9PW;±Îp²Tš$:uR
+$®œlþ§áŠ[4;œÒéc&Qr)YÛ\7"«ÀÕê.L	ª	­€(g@$0š¶šÆ,+Uàc"gm|4 Ë`NïøhLº
+?E
+3Š1· z i. %
+èörxŠBg
+Ök``zÊÐŽ0õ°÷?Idº:ëJ1{OŸC7MQ"ñD÷ÄÊ
+
+ôèv²)pB®ÞÐØ[vE
+ÉÅÆÚŠ
+;²PŸè%ý²ãCq²)ÃªŠ
+qReãÛ\°r:ª!®Uäá¡°(
+ýküWõ9cß
+f5îÉåzöÔ°¹ÂHµ [2Þ.>PUèÁStzê¹¥^jwÔ0jÀé{RRyúGYfíš¯ÀÌ[üÌrŒ¢Œ¥n1WÕ=Ž
+DÁ¡D¡gÒ*1%ÁÃe7Ê	O
+iE9ñ(0*ÃrMéÚËõ°«y«Y#5àÔ÷Ôü=¯qekÆ9rXZ?*N<Ç®¡puçA\Å>Î{P3#OQäÑñ»f«xi¢óªÒ£^uŒ|Rà
+å|¿H.	°Ââ­Í_YÔ%
+)fpDÜ)¥ãaÐŽ
+d%Árª±UÇ¢ä|qÍ ³F66nV
+£>PÔu­u.	X
+ÊhÛ5²y»þ2d?³!³STæášE¬·l š=d.F'2QòšÎâûÞM5Î#äÇOØê¢¹c2)ÿöùÉq/U£ØYÚ¿²gWµÀrórG[ÕÚÀgïÄÖ )²
+œZIKØË~ØðóÊ4:8¬ÑKÔLjfà1-²53FgÒA»Àõ &â{tüÈ4×ÖÀõÃvv
+<_;€Ÿ·ÖA¹m}<äKV0[*¡yŸF_Õ6
+ÎÃe ûÊT]^
+a
+LžbIøÞZÍ)¥Qàäw5Šm#
+G<4Øñ"JºIÕôL€{ÄDã°Xz€ú]#
+íGµq­øxJ¿€qí€aWÏD°CåUç­
+Woe4\úØ£ORpªàdóäÚ,iuíûŒ:Ô
+^y!à©ÞW{]?
+ÌA"ÒRÚü3ê)pHOò	5ã¹žs4m}Ã<€ÊçŒÊ\mÒ)UÆ
+yõÄch2
+m®ŒÐ#ŠZí|&â%¿+%
+K&Ç°Ÿ(
+.ŸÏQAZÄ!Z!{ZÉ®,x]Z#©V¢AÄtöëCQCa6$\£Gg5#|Âv×T,º=NÅ[ÅÉÄÌ
+D«UÒ9B,pûÙM^-
+*óo!X4K¬B"P€²{è8,
+§@kšÔªãw_àb6°Ç@aQ'Šx³Kªj
+Ùoc
+÷CÕOæýºSØ>ÙGÚ/
+ÏØYœ@¯Ô`uÆJ4VF Ëxd+ÐØ{	ëVEÁæÁ§	næ¥ÊbØ<mµ;IG<¹Nú%°YêÐFß€»Ís°ø,d8£y#ÔÄóŒf\·bÞ&pY€<+BžÇOtÃ
+Á5hÀ2 ÉW%¹.åví ¬bÑ¿ LOtÏQ°ÎfVÜ9š\G">c¬ù­Å_Ï,ë
+Ò7iÎØ`äuÎ1SðÞÒßüEgýH AññaÅèW$Ñ(éRâB]î#Íç@OžüÑÇRî$\!:EGYŒ!p
+±ºÓ&T£ìå¯m&²b0ÙœÕ9Fæ0Hã4$çÃìqÔüÔ?+Sú°RVÉàÓpcÑ'Ä ®³ýî-}ãXj$ní^ðúÓ¥¶6ú
+³ë¡]
+
+)0vúv :Ç<á
+œTÕ+e
+)Q!¡NL	ÆŠAEQ¶ÈóæVèPv*ngoìyÌ4Âqnx^*Nv4k¯TñQ}
+1ÓÏböÐôÔ7ÈmÅ
+TÅß ÅM
+|7uç-Rð&rwŸ;ñ*JªLdc±z
+IZ
+WI*ØÃbÃô38à,T>
+/Ö
+öåiè
+xWïlÏDþ(oy2LjðDh8h±óXÌâ7Ÿ7(â£dbšúô­À­9È\Ñ(JŽÈö&]S.9º-i²Î]ßa°úÒÉjÚf`ŽÄÒ¡Í Dd
+Ì>õ­!òTfËðùŠ
+ÆY0BÊ
+%ÎP·#
+ÚÂÌ¬p$šêÂÈ¢Íiáòü)Š2j1:ŸíÖáâvîñ\6eQÅJBOÍ>ÜML	
+ØUçíá 
+m02uYr·àÑZnÔfÒYÚòÅny
+ž[º:oÈ:Èñàñßæ2x"óAÈK0n
+è2Ði¥n|þÔÏŸZr0@ìÖ1ÖQ§>ÚFa(=X*±£îÈ~,s¯²~ÙVÐÎH
+
+¥V%Ç
+³wjDÐJð9Àž­B"fÍ ÖŸq€sáÜ?k5/ù©t°Óp&W	:
+Þ$qi²sô£{á
+9¢
+Yb
+Òr
+8ÒAkè¶f%
+É]ÅéÌPÇ§?uJ(§tf9ÌKðdPüË1cCnšÉú
+:;+&ÁB5MÊÛÔ³§maTëšŸmH($õð%Q®®|ÞÌ²6îhÙXk[ô@6&
+©,&1lkZ0 1O
+dpÇ¹Ž!Á³L]3Ò L ¬HÒnB8ÍJªÞa4lz%A# ïsSî4×žm
+wršl&¢Y°E2çé€Œ@
+e©#
+[_v À6ñÔØšM
+µ0HÉÿó
+TW)ØUµUNSGµÌGÎm<ûìL£
+Ë¥Üm§`äÇA«xÊH~n>€Å¥`
+ñN-
+±)ÍÏ³6¡ÚµðmX)«9ÍÃýC Ühðò¡ÈÍ×à§PÖ°2Šg^-,M'Qµ-$$ìÖv7ôAÎ 764è¥<F Ì
+.ø[H h1ðAP*ZÃ¯ž¿­59
+ù(OÁ/À|
+wT³â<vÃ×Lòº*RÍ4
+ÿßv|Vš
+žóšUlNPJ>Ûë`
+Î@lzEÓQ+jüVw 4hÙK+óE
+Ñ/r
+ '
+çmpŒä)P%Ø¯ÿk5Ô2'JèÅ·
+
+KS!§b
+kß!O¡S~À«I¡Ú*¿°KfÃ:±
+ÒÈ
+ätF³M"hUHC·5akRÝ"]äÆÈÞžk<[N:ÞJc§e	P2àr. š>
+{ý/ªß>eé	§yËD0`ÉL7²i¢s žtàC£q!8"êÌ fC!îzùç@K@pX(@
+
+d@Â@®[îHtÀÞ1<Òv .$!©Ç
+ZÅDDž¥ÏŸ%
+·t«vÉ¡@; È.
+±ÛÌ)ñ!
+Q±pÑ)ÇÎÈì
+¡:mêØu4š
+ÙWÍ5Ÿ'.XAôÆñÿP
+iØÕ2_[
+ÑÌÁZÌ·MHß	3ËT!
+ã¢)Û:
+°Éj
+%
+.i
+;èÈ
+œ@áátVéŽtÐÑÃêÙGò,Cm3á/Àé¡¹Y>áj|®Èö{ø)N€KÃÌHÏ(àòâ?}f§PÈFNsòŒØ(8NPh1 	w/P=s*nŒ²^%l\4p\ÁC.;M-ìÓä5[øV!¢À¥éó$@áØ
+¢FØ*\E/ûE2G#\¢ûÀŠ#äz¶žWH®) ³ñ²Ú¢}
+
+On$@SÜåJú³
+F^4ëQy
+H%mùÚL%fÆÏ ,°-öõ	€£
+­²uóÚvB,w©
+[¥À$³mü\VÉ£ýCòš|õ¡Îœ
+ànÚ î¥Éï!F#èæîZ·ÈçÂ 
+¹é:I\XöG¡BËnIšm¬" ñ²¢+ÛÔ2$²ÓÌHÐ$
+éÌXã$ðÓÂ±NCþ3ÒJkÅtpQž	~aH·ÐÀaPºSq€ScŸÌcS8$Ý¢Q{`>óQA±íJ
+Hå	g2N¥
+2é&Q¯åÌp fÝ2-â%
+îQu;B*S&<±šZÄÚfç­Ë
+B(ç(3®@ªÓÖzæÉ%Ú
+Â¶j®
+òshiŸeL^MUUîw²1cH0.»¢]w[DU
+Gº
+~sú;
+DæÇñóçºuš!OONæYžÕÓà7š¶ÎP£c/;W­å Ý ?·*ÁÿÓånGx¢8ðÑr€h ¬r«
+¬³îçÂÓ·ýÚù2MYo	ué3ÍD
+¢+ï"ÞY)ê¿[Ébm
+}O
+	fÆ±­7/
+×\ÑN6woñ:õvÈk§§áÚ
+"$
+i1\ZoW)ç°FŒHe?×eâ¡¶Ë€áD€øèÈ@ÁUÏÂPJ©d¬Ú¡UŠ)µÈ%&lè!ÎÌÌdŒÛÎ4·"äImb(°
+lºÔÖë§;@©rKsJO×»[EÙ·²i)nZ*õ!«-÷¥²³e±öMÒ$UØg5ò`ºø
+xYÔM1%
+ë6[í$Ý
+Z¢j}šlJFú
+{Á
+jžªlÍg]`º ³;Óå2%¬"Þ§àÊ	ýXåw¿+ûÝ3LË;Ó`E©Ò&Ê<­±æ²ªófle"íËU×Ló(YÓÜ*)	œK>>BŠå9ZoûriÈ£Ö¶ñ(³hñÀ¥»AêEÌ
+Úž@£÷ÐZUiö&SÄRJrŠíŸC$Pjg·
+­z[u±;<5's3¿$µÇ:iüØy¯3><Iÿ¡@>R$>åpG*Æ$
+4Wè
+Æ¶!ŠbÁ±ªóìïêª±cn«EiCÝ¢ïÞYÅK¥š¿yJÚZûÏ7	Ji3ÑZ2$ÜV²tXMìbXÛÅ]í:
+àÕìoÃù
+)SruKN©
+îÖÓŸD£óöÑxg¡î#6fÑ0e<8çjmX
+êzeiÕööŽ§+°
+øi
+Ò|¬^2:°_W'oW@Ks
+*Àµy²ÆpwcE&€emZžY`ßž}è
+[ä×±Ž Úø;zjúO$K
+#Þk1aÄ'
+ú'OM59ö{jüºê
+b š\ïYz]tºøÇ&·zëÎvueY¥ÅkðÓÅA«õ62Ð]SI°
+«_K­
+Øšd
+p_
+fÜ %s>å6ÊB·+ÊA
+AÍ=bfù
+¹ êË«EaøHÔì¬è§M^³üÈ¥
+QYMÌu¶yÇŒØñ¬©ÆçÇé$z
+qôm×_°èíòÇûlÁcÜ¶ÇS¡àÉÀ'²Pb-üeðv(¥ T¿ïgô€c`_ÞEÔB
+y°*ºÜz@ÄppI}HàFgqËŽkæ
+©äQužWü
+HhxNè m@ÿäÒå}	âÃ¡eBÁÏåÚzHfîúm®õì£ËL®]ôL	
+kA,ky4ú}€Q»à±6Ö#LC\bèUj!Ò³ïU³È%
+{+Iä€=Xö-N&±éd×G2÷zê-
+ªj+¿NÈnèôû$u&¬4,ØèÌH®4[ÊÍHÿ'W_$ã·üâ
+â8Ë
+Xoªôc\bà9ÎŽ¯õ^âý)Ql	Bé÷ìCXµL 0ØÉlf!Q#{9³hØÎDHÛßKý4
+
+j¿·V¶²E Ýž€qÐÆi +°ÈîTm	~
+4¥ŠÂÅ{YUK)S}RÑ_kïüqÁ()
+~«µ¬BE3ôêØTö¶'^1å_Ã@×SÚÉŠ¹' ñJæ>ÛCÙiUãy?Â×ôÍLÙ
+ »	?õºçtÊµñøqÌ@ÀŸ_¢^«æð_»îù}Ñ¿IkHÇD8Äë
+ÄÜ7/)`Ð€²àRð>x­·ßSÄ ÀŒÖÕÌQ³°|L<Z4îbêýŠÆ(8ÕÖ3BŠ 5©Ð]6A^VëfgL9Õ°f
+{Þwp)2Ô%ÊÉpSÑ!ìTÌÉ]pãkËž9Æ
+C
+Ï;ç2IÉXKKí
+ý`t1{J 2g[ðÊÁu&¢îÕºº
+€¥àsçlkŠÝºŒŒ#8£ÉöI@bøzÝ0*]$Ð çbP?Qk
+
+ZaA!y&pøê6ÇS
+ÆZÆ²|±	jvX(Á»Õà${÷1[¬¥B0/ÅÁÓYÈ]Y~ª>M^¶€üÌ)K1]*å@Ç¯u
+Ùb!Š(k6CY@ËtŸ4
+|Rëqf^È 5#±óJÃÃ(¬@®æU­ûÝfü	ÚÅ#P2d8¢2Ï$ÍDJ
+åÅÏ68pTJÜ$ÈÝ}oR
+Ï`fWÅ
+nØŽ
+œ0(êhèqŠíßÃÞb%wåZ(`1]KŒqYæ§ZÓÐm4	Qç
+2&R€1Ýs=îíoù·aÔ+s|ÉÀ¬³Ê©^â}rÃ	îÒÜ°¥È9è_õkÁ+Ô'ºž:TU9Lõ),ØÌ²J
+ÆLõ­ÛJXÈN7²ÍÃÄ9_Wð
+îBÔ÷xPèÙ(¢
+c<Ü¡(2
+ý ®DäV3¢dâYàßVåSo.áŽ_Š¬äË+»Î×à-_žpÖ@é6å¯p`Õœk¢;š0ÕéW!žöÆ£4Ï²Ž!B±­!r]ú"Ù¹øã³âìû}ŸŽÓX¡D1Ë,;=.aædBBI°ÚœØÌè)ø³ë°pŸd!ºféÂÑûjfTâÈ>¬>ÒOŽHÐÕ[Ø?Ÿ¿ä78Ù=.¡Vxcô5ú!KH°ÀþaCòÕÊg¶#¢j-XïÉ@øU[€`Cª:EWU(õócf9.pÑjx)ªGJ4Åä®còhÌýônÆŠ¢ãŒ²ÍZt©ò|œR+Sñ¢BŒ
+at5_ªŸîGÂöFx$Ì¶)ÞQóØ0.sz]%4óÏBqìž.ZkI3ÜPTnœ¢/Óç
+Z¶À:<<yÞJ¹HOL
+.[_
+¬ÙmŽB&öñŸC$n<ÐI!°4Õq]¹qCºV"QRÎéÒPa,Ïš	ù·K&u®F|j,:ë$|ŒšØ¥ÐrÐë
+ª³ÆÜ¶ÂËíeÖ	ø·æ¶2![öqMÚr
+ Î
+k·ª4.öY^v
+šž
+ÙHùÌ~
+:Áš`w¹m|x«Áû©xbR¶°žù£p$/€¡ßÇ *ÖOýø"
+|&Ä®žŒfHO!76	 ©Ð¥
+2#C­òì¥ÆM'øB0ùJ#Ú=0íx:k®
+§h}xŠ¿ÏïçÈSÈü°³Ör\éÕu\qXâ
+	tIºŠàeÅc
+ Ââ%
+äÑH~œä+U~WÑO1êU»æ,Žs0Ä`èÌòCâ~b L
+³£Æ íÊF¢'H=0
+ÑTŒQ{VJ`åQ#ÂùÆÙ}ìÖT	~cZåÃ×w,Š	Ó2-+P
+$èß©ô^.
+1À²)E|KbÓjÛh/ñj`üÅH;M4"K¥îØÍz0?
+0{ÔñëÁ;[ù^lÀ+	®§ìÎŸ,â8%#Q&¯ùLÛBÃ
+0eäEa#Óz
+tÏ%æ8Îô&õþŽÓFÓsC³8>AÙ\÷ÑöBøÁ&íŸ
+ÿÃ^MÉNšËÿj×0`Ì7)ªÙ0®4Ý%eŒ
+P³PšÙG+"GìA»ÐŒÓø@§*r
+
+ÅâUÇÆQL¹jJÙBVìÛüÒÄÊj"Ý,$K
+µ¶u³5|+±­Û?µlhÄ>Só¡Tîv]Ü~Iå\E>1±Á%ãTå>¯K$Þ`yJ
+Ìÿ¥v8>ñª9Æcq^3Y$±£ÄF
+Qáì%ûž«X?]ëS¬È6È+±­F¢Ö®Ö"ËZ
+W\Õ	ÕÈÕh`#uë0Ù/BŒä1F!»ÁBAm7€ZÌ}€4>¶îX¿çPªFý&$ë°ãÈ·Ù<q}³ÎEµ¬7ÄéUÖûd_
+J
+<19€ mDìèd`ÈÝ7òæ"Œmûz
+ME%è?€!Â×@òJ4
+i©lNQÌ_Ê}
+©rdQPŒ@|bÐà*TÖKÉ'Cq|Â±­ÐÖ+
+$ó{
+
+S±5 Oå+PÙ=Q`©€ý
+ïæëµXšÆ<,Zd+îÏ;M6F
+[GÕØQrå(ïx-²4à-
+ éâåoêFlÈ£Nt`
+ÆÕµ&((ZYÈbZÐn	Jõ1Ÿ³r5q¥Žf²ÑFv$»Ü#AWCËGŒ€(ûØL:=3"OªGG+ðyûÀüÜ±C^"W0¡]gjÏ
+òEHôÈºHÂ"íq#ž;µ$M9	A
+è©?uaGÞŠNìÎ$:kAš?m:šq
+ËÀÆ·P	ìâ¬aÍÅe¥ŒMQjÐŽ
+PÙ·U)Ôîáµ`Üjo®ÓtÛTDSë
+j¶DštÒ¬³æºÖð7ëgåóŒÀzjrë
+6&ÄµdÏ|9Zf»P(ÁÝMÎúÓV	ØJWê<5k¢úpÁ7(Ñ	` 
+`4ªI¡»#
+£B'»šB~~©%)6Ik¢0Ñ)M5*»7¬žhXÌ
+B)Û£BLðniS[¡pZëMY¡
+Z®sm#ŸL]GC!°ûúÿØ»0°*n0ŠQPÄ©Æ¶Ó£
+ 
+ïÙ
+î0+¶å
+Lâò2
+ŽÀZÇgÄÑº€_ðéÃ"p_a­þ­œe`ŠÐ%hóŒwÕ~¢§ËžÑ1Ž+xÎ©Î©î#ÇáIxË-u
+dÊa_ôøŠ
+Tvè;O¶,Â+Ò¢D
+]Ymë^&Ëö,õìúfb*-³»ÍÒjîZËHoËY&ÛC}dDv3;ìÁg}òœ¶à[â¬í2ÌŠ§ b>Ù4ëQ²L,c$z.uÅIã.,ÓbN€|€0±z>	
+®Ø'±éåK°U]
+`ÓEÑÄ4PWxÁ"RèYfÉ±Í/]d)È2Ê> iÀcTßûÎ³
+8ó<KºÛlŒ
+òÔºcaŸ8d_Â2ÒÖPÁ<Wž}`)²w²ÑZ÷@IægdF
+°Áá:(`ÊW÷åLEÀè#~
+L.-PkËŒž§k*LÔ)ßè
+ÕiYaÆ/
+0Ìæ]îÁšb[7fgÐòX
+ÝØ4kæ6¯eXNú ÕT)<R!¡Ä9·Aß6;Q
+E°x
+XøÅæøEœüÄ±©}TªÃ
+,|R=/Ÿ?ÔØÆÆB&(&W£Ä]HNnbøššmØ¢.*¯JT¬R.-DwÍrJÌsHÄ
+tFs|Ž'YR25²|ÍxÌb`%ø
+5`>x>ºldHEæéK=Pôä¬
+Ìàó]0ô­Ý&Â]
+Wß(pF®5ò
+ÆÖRÐ
+ ÌË`j\!
+~¿rF!\qÅûtÅ`78ffåÔe y$iîÉpð+ñž*ÂL£Ï÷åãp³Ü²¡Æž8äñÙjÚsf³8ždv¯Á}¿h°
+Ó©Áÿ_Ìþº>ï4õp¡îéŒ^Èa,Gâ.å^Ç#ÞÜ7í» ÏU¿,àcë\
+£ ¿fÆAVô ]bD7g*€GZqè900*
+37dhfõª €%ÿ ðã
+øtFŠ2·aI8åd
+Ó`»(`Í@:Ê
+Â§B#|kr
+$Èü ÓMiKuVyf²ÐÆf[EIEúÕè%Nxz3	¿ÇÇàÆbA< ZU'@Y rŽ#utõÎÍuý9×,I>
+{dÚg@Bw€o*éx6.Xjšà€X
+Ô"¥ÏGfÖŒGäŒý%{5$
+.YÊL-yx,©·M³	ïé3{®3$D©ÊÇ(ïÌÕØYynwÐc1¶(ÚB¶*2TxÖç€]tZ6Ï«ÑtÇ#IB8|ÔÂnšqËkº4
+PX·9ò
+`kj¬oŒZH
+€i!|I
+þÙ
+ uJ
+eV#ÃÀ²¢
+TÛI1¡!ù:l'£®,Ro®sèû¶e¡DY*T
+[{Ãt`#·ÐêèëaþdëÆ<ÂÔÓ
+üfjL#	M5§g%úC>J#{]+Ò©!œñj(Ì¢Þ|è^'wPÄûnds©êà1côöÁÐ ¡ÌÒHË
+HOGŽSJ¿ÕW°QLÎÙ_p1ìLrr$à-æ,3Ñ0P"å êGJÆHŽò«€Ü-¥ïß«a&Ÿª%ð±j¡0íûñP&ÿ Ý	ê å[t<§îªD	BÂ¶`ê\	âªUºr
+p€EGSæq+©2Ž¬¹TNâÑ,»Y-pŒUs
+&¥/Ît
+gö5c
++/
+o7áQt :ODÒÈ2SGñÃx'Q8.®w,'D.ÔÝp
+ç×*šyà3LNdg
+	<Ÿ
+Má×Òñzú².ÕªÎðl<ØÅBÊ Èün¿9ÝÑÕØMæqº¡BQ¥Ê«ÇT²	6jµè°¹amî®@&)bŽ×º5Ü
+
+œ@Ÿy×Ò¢J+=%þMâèÅ'ãÁ[7;ë÷Ÿy
++1D8Ð±¡aæÈÖçÀÂÝªÅ,
+}>Âup&ÝýŒ*ÇÖ/t
+Ñ¬1ðh~Û¯Û ºKRhÉ[HUÈ/"'·¹9ÃŒ)ôÆêG&×»œ@T_*±ÔqCSÆYg#-Žxi[Šj{Xµ%âÇVUÀ
+î%K%4:Aã ± LŽœRÄp|F£ârkmÖ±Î ©¶tÍx8%VèÙ[-lÿ[ÆùdÛ|¡óÇNÃqÎâckùý`M(ò£íY(ÕºüPQV:AìÓz]F#5îÇ9+ 
+Ô`4Gä9!
+Î
+äŠÈ`:P°íëÁkltZÑÛÓ5ì
+
+Ûa©®[
+ï|5A]Ý#	âäÁ°$ÐãZ-pGDNwå4k
+ÃMó¹jŒŽÖ4m$
+9(á:äîÏÄ%
+x­Î5%
+jaWßÂñe=-
+ÊCÞ|
+ãÄêF,¡ÜZ6Ñ[oÎïàY9Zô2ç rPc`é%I£¹x
+š5óQÊP$D"â»"¹¥CJ*šµ#°LÃÍ`óeýÈéuw3¥_j
+u&wwúÔ:RuUÌWoÔÆEÍ.&:
+"2³âÑnÚöcº'5by)X[¬
+63Þí3¬{Æm¢®«Ü¥'¹Í,6:@ÄðuÖ3ÞóÛŽ÷ªš40å'Se
+e%Í~'¯)³ô8[ñ©
+°¶(PÏhÆZóVf¥?M~«<Š Ð}
+v<·Ù.;	ažûÈ-6ÔÜ@õ ZZà\pCÈ	41âÚÝ¹'rbå"î?y¢0ªbÅ>&@ËuzBÍÙ GÊÔ×8ùÌ>uÜyhâgvêI
+SOMØ,á/YPy)íRúÂ¥àÓ*%%Õ€04š
+è±°ótÑ
+üúAß4€Oá§Ï4qrPþD3¢5/ÜÁ»0GQä4·ÄÅ6x	Y=ŽÀ.D :¥K¶áëSšºÂ[
+_
+aÕà
+Î)÷n4e>ò¢cWÃ@FÊ	Âú«
+ÀcD;l,lð-AÈé¬ÿÂe×%îb|œ=T€3šÆšÇLz4  ŒJð°AÌyà£QÚÍÙÓ=JYÀÍ+¹ÎŽ9ðU5qbO­&/4'ØòÓ\wI) ^BÁW39téú;r>?gcZF­ªVeLšo³h¶ŽÖÅÓ® ížgí8yÎø`av9kÉŒrQëÍ5C{vÙçÐ¬à©œÒÇÀÖvPØkþ	Xªí¬àÄ7r)¯\KgP+NË'³_:§2
+Ö"
+õÜÂÔ%!*6õ+ýÃî
+NWÎXg
+7Öž£h*©ŸµÀ^õ7([õ«÷!VJÀeÄ
+Œ
+µh-
+¯ýôYRY#!übæq4£úáÕPÑa#]©j±
+Lª	qïæÆåž1ÁªÉ"ÈòEd¿8ËÕAIÔNëu#cŒÂ2yk @(f¢:až{
+¥2FyF³Žž@RoÚØ
+©e&Ä
+?ÈNcB\x>ìwhü?ZèYÀ$çLÑÃµ9A°ô?ÐOA?xÛcô]çŠdÌæ]d~c%Iö³[ŒlÄø^ÑžME&h}š2QLÔùÜhŽFW,©»Ær5NžïàÎÌZØc«L{Ð·À×¡}
+rÊ5À¡+oíìV×ÒVž
+Ú4^ÀY°ø*óG¡]èÐª¶*ËžÇ`ßäQ
+#[A&@ÇØ ÿ ç\ógö_%LÛ
+POtHÔÿjÝSð®<MÝyô»	=ûž\€A.€¹ä9J,gþt¿ŽÉçûiÏu+ç€6ÀÀMÚâMP	t°VâÈVTÅÀà
+iI°ÝEM`LäJ!\Ü0	vôÎ	u¶qË
+i"|U;¢
+ubB4hVTH6|é~=O[°Lª/±sª
+NXE\»e²
+l
+Æ+²ÓÁáà>	Ø­§µµ*Öb= 0²9ªqÙDÕkÜb íN€eñq KºåNP©)
+å¬Yk€Êa{"¢êôv>D
+ó£q#öÌGh,,i€6Kpí:kZó°,DÁÆ 1«¬2#õ«2#ï£
+,·v7ìØ)ÕàeLÇÙTñ<P¢ÌŒ{nSõÛž1FííÖcÖø*
+û,Â,ÔöÇC°8äõ9»­úCÉ
+|f¶Vž"[ûE
+Fß]E>#º^w(BiqlÄ\Z}õw¶÷(3 /Õíá?{ H¥ [àºmC_
+©¶ñÓþuðŽw ñL3cchÀ> šr)313e 
+ŒÆJÛ
+s¶,»²1RVCžXp­ÎUÍÒÑæ¬
+èK€CtŸ	Á
+]cš#ÿEº]÷¹±ô;¹
+ŠØ
+€`µF`ËöÒµ!¯lsÇ9ÛqjhS#ñ,×øŒv¥S
+)Ð`<¬ÖÁVqöçµ
+>Ó1@=#`P	8)$UVíAváùšü`=7uÞc¥öâÆ
+/æ9H±­l
+Öö	=PP()]Væ¶[;°qö[a°
+,7yeÚæcsyË&à\nß^9çX@]hõªc
+ðÀì@WúN×h[\ž×[°ýŽÆàé¹¢ý*_
+]­ Æ[šÛÊÁ1$&0ø$ÁzÝ!/À6t8QÀè	DíÔ×wâ2Þ,
+š/èÁŠEx"
+šT¹£:ÑmPÔH)ž>XZ2é5ŠãŸë0éª¬eQpgÀŽDÚçõÂ
+0­ÒfÉÈHéIí€Ÿj'PsÀÙ©<X,êÉä +ÏÚúÿV¥adn»Å
+'ŸåOpM-¶ÌŠF¢Q«š,À¡PŒfÚÕ
+û[r(â8:I]Ó¢¢Å±€¯¢·P
+RLZkÇF£Íª
+c+s¥Jk\Á&#g°Yñô{Ñ\ìcèH«­ŒÖŸ±@ŠÔ/£ŒÁÊsyÖ¬ìº"Î­\]WïlçŠ¡=HP
+æ>&2œ:­IÅ'|¿4a`Kw!(zD}hLÅF
+§G&Pp
+ž
+ 5ã~ù .ÈABîGnÅúR&ÌéÊµ³æÈÙ UL
+En]áµ|î©¡f?tu€R±»¥Mi|¬~ŠZ#(n|^ñy€m»&
+q
+
+­®©Tp£â¹ËÂâ
+Ö6_¶ñíS£ÀßÇÚ¿mÓ€MûZûåp
+üí¬?Û³;Ým·Ÿ¶#g?xªšž×ÎKEÊ
+Ä6
+Ôàþ°Ò üMsíZPM
+ûâ±
+Èh+]èãb[9VKÅÇ×¶y³øRMö/a8g
+¹
+
+WÉî7:è¡n fèQÂÄTùÜGk£RtPâØÌîé@RèÌpíyÎF#ÇmnÈÇ0A}ŠÉR)Ú5T¢²n5:çå$]Cîj7­bVü"í3'`c2Î®»%@8&@ÇóíÀBP|Ö'6=ÉRHp%X°ÇÏSÚ|³`.XVÏ$µe(° 
+-Ñè¹i<ØPHhð4Kzªçãçœª~kSœ¢öR¬
+Å
+Ì8y#¢Ò ìpk5=µeMÆHÌš·Qp-Ñ¶ž}EÒ²KâØïg,ß'MpP²1¥uH€í0g';å:(×ÖUXžÔItIæV^ÃSvkœV¶ÕžÎ­©`Î0îæÑö¯ª,®_SLç
+GýÐ?>
+JzB«nÝ3ÞÀ
+^#yC©­Âu&,¥^ŽTpw@àÑL³$
+é
+a}xÅIQí<p^¹5$(LêŒÞ²»ð
+Øh^I0Ž^Ìœ*5F91"éò#ÞÚïT÷€ÏM«Qv
+WHŠ¿*¯r|5ªïÀM
+æ+øA
+Iwå¿0ðžp¶o
+é$ÛwYL/`K
+1ŸÁ"ÓbD<XcŽ\
+N ù_G!wðTjW
+¿'¥lVe
+žÕ|m¶RÛÊU
+­}c¹oÐLÏãòèe]šÝ»YÒNxÁ=±^xß®÷¥v
+°àÇWÛÐ
+AýÀ}Ø>nÍHûhw):w»?Æ¢h²Lšð->]Øb4]£F)Ÿ
+ùå{º(5iLæ8P°C\w%ž#`Ï ÞîÎ7Øõo-õP(nSãG§ñ<®[1"8	©OðDØHsÚãñŽ\¬SÏX
+
+üÞ-lè5gÂó<k
+åä=Lš3ÂuÛù³
+nU^¹te&|Ã
+à¯èHN9
+U×Ûmþ·K×Løö|ÒÄ
+falfcŸ÷œMÂ+áì©
+³cÓadtr{ÿqÚj(
+­!àÀu§ª5¯PH»»ÖlÃù
+dQ'§Î5Ùú>_êdÎ_BN/ïjïfMŸ2,
+Œb÷G	µýXŒd\ÀÑÁ1PŒüyh³ŠÕ
+ÍúÞš
+@L5¬@3mÊfvÓk=¿'@ž
+æ|æ­×!°`
+ý£ ÷°òãÉÖjlGú£Ò²­ÍìVA€yVðïXÇ}Ivm:³Aùð
+á»ž(Ná"ø?
+/<FÖ#¹MDfYáŽ>ócV¹rRüè
+i~tÚ€5ŽÎuá·nXM
+q%t]%âWI!E+:¥výWÏìMtuîÝ!ÛxUb
+víß§ñÆ`©VO}>}MŒ
+7¬Î@
+5ŽŽ&PrdÊBê	æXž
+w}T.}JÛ¢Â¬dÀIÜÂôiPx¢· JÌŠEž²>XÂÖi1	X4Ó	ªøuÛÖ
+;Ò
+Û\AU·|FÙó'8m\Q5îúð*à¡èO¿
+À{C&vOÕîN&qëõÄõKïè×IÇUqÒñèž×»
+w" ÄÍ&Ê.h:>
+×§âäãqìøv\9^EhÇµ`Ì@õ58ü0ós0%);x 6áåeàLèâ2+Föi²õ0ä£)%mãOñp8s|êÄ ®WJ1ªÄ(Ò Ù» î
+æÇ
+\`&Ž,
+Zß
+r@b<%áÜc$|Yí
+Ûí§fÜéT"îx{
+ð
+ï§wnù!Ã¡ÜïÈÂH=Aa ÐTOÙÈñ:
+9\­$×çÈä1råø\ P$¿«>i~Ÿ!fêŠýââÜYX#>.ã
+)]
+I¢¬u>&]P¥ÏöÂ
+ëÇE0aU4w;z'Pœ@#-®±Op}9ç6±µú%5Í!k³¬`ÿCåVbñpÆN7pŽ2AFÎÚ0AÄã×qôxvÜ:Ä&OÊ+ÙFy!Öô
+¯ÝMÁÌãÒ1ê8³)=.)¯«ÇäN¹sŒâ\
+FbÆ>²&6yó¡à4&
+9ÉþNµRÁjØ·Š~
+ [%Ü^3°ŠäaÑÚDÛ
+ŽM
+øÝk«CjÙöÃ*ò¢B`[N Œe@âð
+²X`
+wqµçFx&®øóS¡¥B2§¿ ^Ú'?µs¢ÖÄŽ
+Qx(ÅÏÙDMw«2º	'Tt9¹åR[fùÛ1áuA{WaÖóiÌ:51ûN=Tf7æ)cÌ÷pWWC×gŽ\ÇÔñÈÊwEgåâ[ŸÖék[ü#sŽ±åî
+iHPE&e  5c(11+æ¬µwÓÏ¹Œ*
+uÞy&äÇÃ×VË.mV>mª; b^ë/ìJxUg
+mÓcÃß¡Ð@aÚHL±&a±šá§9ÝØòÉà«Äá)Û~lu:5¡v{Íù
+å+yâÀf%iž,>*æisÔÌl»Hæª²föpëì³D
+o"@cå"'6ŸemŒ|j?V^!ûTGS¶ÝXI1³?+Ì;¢µ\t«cÐ ¢VÝDØ¡¿/Ž	]ãrúGM
+­È}D'Hà "ŸÂ§Ôfž*ÙùGró]	/¡Éâ,q6ŒŠ!Éàx
+].k
+éhjSë
+e%ek¹Y¿FÊ9ÈÒRD&vàO!ÊUÆl÷: )nÅWA¢ë9nB+9aE@·
+ÊAV-N)¶ ÖÞÑ
+¬Å¹s¿lÕ<
+*Aãçg"Dh7çÈ<_õfxC0y©
+ÊgŸ`¡Ç9ûmg8s,0­Z;ñØ^xóKþoFLP¯ÆWØðYDè$Æèi&ñÎ
+è&ÜàKÍÓŽËÔû×ÑVÝÍÁâ¥
+À
+ø[Yn©43ö
+0LïZ-ñBÂ0NŽ2}ñ^+ddÆrÝÉæ±XHáR
+[
+Äcu€ìhK°eBh¹œw4+RÐiqÿM7¬¶ÂÕ1Ã­t ÇáJªþ®enäX4Në.;ÿ
+®s*aûášFªp`æ/Ó]ï;qyn1þa6³¢ goE¹ÃñE
+àOsµç3µ)æèl¡¯`'ìU¶©;©+°{¬	-$EÇÄ¡dôÁ6
+®jËÛQà{§Ý
+Þ9lÕ'7éSÂÒ{ðçÈÌë6È,FÔ+»ÄÀ
+8ØJ9u^.ûÛÎ}8LjÕK'¡©
+ÆåbqHCÚÒœ
+ö@
+àÌÞ&G%ø`ò»`àV6Åœ|BÝ,eOÎ#Ät­mPØjB³2
+¥Á\ô
+c4L
+ä¬§À0kœüŠ|ÿŸÐzc.ÖÚÕ
+éüqÊŽv°žo]Ÿ^N_·Ör¿ÅFÎo¢¢
+Â ^¯ì
+*BÚÌý
+óŠîr{Ü2ªÄD÷ð¢»ÔîÉÞ*8µSÏD:GÐà3×5%µD7&ÖÔuÖ®|5¬MAÄaÞìžiÝKQDwdÒ
+èüs(ºB`E7H¹Žä1C&öÊ
+ó 
+§ySéOëáwÛ<Am ­I"iÓÊrýOz7Ÿòª"Ë
+yá{ù·Ûs
+Ç6:èÀéd8ä ýðk5
+Eõ%Šíf]ÿDí0?£Ó7)CÁ+³-hõ×œçw&7j^OÇ>š­ŽBÙÞ
+Úg¹/^à@Þ
+çö·bØU)CÕ+Û)Œ¶Ñ
+×
+ð§àp_žS&lâP82¹è: õI5G{c$Qåá
+øk-ep/Í@y­¿aøŠ2/!ù³r³~P
+íÁì(åJž,0FÃêca}/r-`öÅ«
+?üö-ü~pT52ñ}¹ 
+iÃÕ·?C¯d\]RèiOž0ôÒ
+àÝ±^¿~©74+a
+ÚÀRG:;d°Û
+RÄÞÚó¹þ;
+Ð×ÎI ðäq³œTÀš³BBHxð6¥J'T.èñßSÇúsA¿ì­1fØÊY¶ñä
+_ ÐC
+ÅÈT}Õá"÷žÂÀÜ*-ô
+|×@àCÒdŒÔ°1êOóvcêKøä
+ì`1I¿2FQ·¯
+DV€Z4Pc`Ç`ÛÖpÃÉÙëí8z
+Q³
+ 
+087ÖÕÉpÝZ(Á[d:ûkmÖXkŸzo>wíŸËZXÖMÝ6³[)Øk8/U%ÍV2HÅTìKä5âëé'[×ŒCB
+:ö
+
+çq_
+÷á(%1äd9ÐæÊï­ÚÌ`*ÖXïYa
+ýTŽSËo~
+I
+	.Jè·v»ËE
+«ŽöÀÎs!n€jT¥M[/©ÞÍìÆÃ±¹g{Žñï¡1
+vÝlÝ
+2ê,ÉþÄ¯Ù®
+B­\zð4}ßAŒ]€"úâ'ü®VB1¹·{pÀ&Sy³AíL¥d±œQ@TG--,t¶ee
+Nê°m%û,­ðlšô?L#	*A},f]ì0nŽc°ÕÚËD
+KF@œicçXÄzBÇ*uïtp¯jë¶¯iân(¯Â`'Û{ŽOšêC"³re ÖR0&c§Œ1
+vì
+»A!ÝwD±ûüBÖ¥Î
+eÎUhT!ôZ9Ä@`­ÉP¹_²#âs"8Ç'Hpî)|QäsoÜnc¬HMÖð	¬îõ	nêN#€<|¡;paŠÉ2ì
+6Íœ€ÐŒr
+xWo£ŸA`Ár¢°fÒTÆ$B.ÁÀ/O
+!á:Û ³/
+Ö6^lä¿
+BHÅêó%ÃËèáÞ+ØUiò[ìÚGXD
+AÖâb¬	Qz¢ßÆ5\OÞ$ç
+üC3P¹ íÌÐP¡ÄÝÑÓ'Õ¯Ù\y		ÃžwD+
+£ÌqùRÅ
+3^?@»p(ž{Ý2Ðòí×ÓêGKÜÞºŠW\
+DªeKÿ`ÄBõáê;æÝdI0€¬±&tahEå»;¡ g_6s,×VzÃ`Y¡(Šáþ,F¢€ºC^PÖôý"Û8nœngŠmâ÷ÁöïBûÐkZþŸñ/â 8LÚ±ýöÇð²ßp6@Â¿>!ž
+BÜµ¥cÒvÌsº·kWàxaú{ù%0Ú)S°
+Jt2àT°NDWä
+T§
+;sLíÕ!CøOÏoZ#~ð~GÐãQ ÂÏb/þÞKHObÂS/RMPxwÙc
+¯Âoá¯ð5K
+#à)Ã#ái6,<û ÀgÎÍváð:5<Þ80ßm-pÁÐðäÐÌÍ-
+
+J
+>Ä
+ŒVÁý­#ïG}%S¥Ö€0ÌŠL|(
+d%%ü¯_Ä7âSxt.üQ?gÂÃñ,Œ~oÄ¹qÀðixá(Ÿ/ÿÂ;á[ñ§x2Œ€j	ËøTäð¯'N|;¢ð@
+U z
+ú0	 ø#°<þbé(tÆ`ý,¢PÕr.Æ|ãuÅ/¶2>žQ©Ø
+aô|äm,FîW9kš%kâÐãÇ(¯Õ/pÜÌ$¡`¿H#SÁ*ø§ ªöC>=MßŽ¶éA¹åÛ~nÑ€ñUnf3»w>y
+\rÆÔŠn/­×}!e}pì
+!Á}TN-Jí²ZÚî:Š"^è,!²3qs?øÍâg&2<-
+ÿ
+Â³á%€ø!üIEö
+F`wbàÄµ
+Q¹ÜñQ<Ç+0\²uQÁm{P:£çÔßî6ÿ
+Zªîø,ØÐ
+X5:¥ŒËl[ò	Kr&fhDjéw-öRòhµº€Ëèiçú0B»
+\QÓNr>qSQGt­àît"ab©ï
+¯àÎ]Eò<
+Ê¯É£ÙÞ
+ÕMsá4œš{­µÖñ*³®ªo|@Ô©
+ÐRå0LC¡X¡.}qA«1·Õ©'
+€kò!6"šnr[ôÖ<µ[¢)ý7FràQM#êü#.[§ŒÓÌÔìóG¬gíá
+:-
+úÔ|Œ5	Uäà\¶%Ëá})}Åy e(®=c£ú!q«ÕDY0~1 r3lx¿
+
+Mw|¹1^¥ž §GÈüÇî vuÜiŠäfmãhZ¶öáÅŠsŸOBõ¶fN¯O5õëgõç(Ù.g6
+?ïjAÑf4Ý
+N,c@¯LÌ¬Õ?kŸ"2ðl2
+kbò¿.ð­4ÍþKuji
+Ôÿ%ûù1\§ŠÇÌ
+xo,è
+æsN3~pL/\Þú¶9Ÿ¿
+ñ·o!rA%°l@¹9úèDWý{@
+6µEè YdÆsnÈvx€š,îÔØ7ª¿Œ28ŠÜg±CiÛçµ°v
+ð}Úß7Ð¥ÓÅ
+ZcÚ®ì
+J$7ß*Ð|B¯0:ÇU²lH8
+>
+ôàïŠøéŸ¢!òa	0`}ÒàW"ìèq\¡
+FñÒxk¥id=Wºr±ìB?ëR¢*Ä?%éS7ÝLO0SzŸŸyÀ»ÈVüÚè¯9ÿxq?ÌZÝÆÖæ±ñš±8Ç¶µ5@ó<Ïå«kè_pÝÚmŠå(	+ßÃ§Ib|ŽêßŒx1Æg¯átæÂ­dÝ<!çJG5Ö(¹2ýàðèÞ¯6ã.oþTó¯IdµŸ3KüÛ0·$Þ'uT`Æ\¬pgÖ%ØYfºÖËþ²h¬?œHNv\5W8š]÷(ÆÎ{
+ø]F}Š×Èéð8Ž¹šŠÄ|$)Q0ØŠWÂ¶Ô­CYTb¡œŒt?7[©xÂ`Å8ð°?ÉÊ£{ÐòêÛcœJg?f%'8c6E7Æò¬«JâÁpêŠ z
+èíÃ1aÎáÉÒ 8:ÓÐE²Lö)ys×ŸÞd(ù u«¿5(t¥|Mõ_ÉXlV¢jÖªT4¢$ûqÈ<ÇEËÑ×ž5Fÿá÷â ²ß?I4¶HÆiP¢tSéÆŽCò€ÐC$ÂG^Ñ[haxÚ?0ê
+®\HmÝi€G_ò£0ì³[
+6l>áE6
+é¢;Ð-8Nêb§¬²L
+©àòT-0ÿ0þ±Qlßl&k¢õ-Áó¢ì
+ŽoýE]ÏTÈºž°ôç_yÙC€0LÓöÛŽÀÆ<Àµ6dxjWŽDwË*I^  Ž­€å[¹dÿ
+3Úä°sJök^éD N€všÐûk
+^40×ª ÞvŽ9hÁÓ'³oK
+Vß
+^ N]¿D¯Òo4IÒ²šš
+C³#Ô³žËœ®íÿègŒf£F:îºx®úì®yî
+~þÕ
+
+GÆ`9ž>Š_=º?¡Žl?7Ïw/Ð35œVMí:á«å²[''ìÁf¢vÑý'5«+ä8À¯ILÃ§C[
+«|ö¢TÈüÞ)šó
+&d90iþ.·#øÏ\(Tjÿ}¡%ô*Ð&z¯Rr»~è	cÖ,è?Ú×ç&ïõžø
+KB{;ä»@ü
+öŸYðDK-Œ>
+6Ý
+x2ÖeªZý2FWÌ9#äwÕwane"]ŸÅ~Yó«
+ñ))"Ãï²æ-­©ÖPõA€<þŽn.­ã|ÚÑÀJQ°[¿gÔku	@9§Ù
+ªçòPc©ã­y0
+ü î~ñq³ß:>ùær'®õ
+,å%%Š$ÄRK£¢œuqºGnLêt%¿
++U×DkNÏëðI:ÖÙÉ¿à'ùå5£÷öYXŽL8åhcÙáÙF¿	8
+Œ°eãoyúéã×QÓ­V2hê±Ÿ!,,Kp2{ZÐá\ð2»~Ltàk×š]±A³@Jô9úÁ9ô°µ
+T­
+yh­rZðÇ	Ú~oÏ%­
+è€^6,.AÿÝŸd.:÷ÛÜþKO9^--üÃ¬×{Ý3ú
+82sÇW-
+µ
+\üÿ×ò
+IdþYUÑc
+çàÏý'=IÐÆýŽZY
+¿DÃw^]]ø*j%ÍäaœôÜðõl%dôÎŠ$E×ÄåÃ`H©æI8×À]CAs°ímÐØš*Éš ÑæŒ{Ñûný^Z©óºo©m
+œúqTdØ#Ì­·kh¡gŠ<Ñ/
+¢o:	÷u,e{Ît}l«^ÿÕ»L€GåqPáRÚé`äzÝ¡î.
+
+q±ÊrSG²ÕÊ+Zð0EEœ:/psRÝŽì
+!ÏQ@ßËü{Úž
+_.Wg±Ïc4ù
+¯Qv€
+Ý6Ù ekbýÃ{ÞÑŸ¥²þáª®TóA^D{£·FOŽ-åV[ô0%¹>Š<ËénÕý[ÿ\WoíòLOhD?·­K?mÀ:ëÇ5JÓvYdØø:í6OVöùoÍ@l5AÄlär®@îs©¹	ÃOÇ^ÓŠ
+`ùþBðï·'PÃlžß.ãt	öðHíf
+Íí6¹Ã:OµŠøãÒaÈÒ0
+°fq#A_ŽÐ§7(ôé÷Põ 9òà,¥èÇä'QIÁïg¿
+
+n<OÕëä}
+
+ôî
+N£3Áü!Í*E.(&­}«Ž¢É®HV
+ššîgXDúåß:°(%úàe
+ŸXSüÌèº.Ûy¶š
+TsÜÉ ÈÀô@NµüÜ6ŸŸÞ<É9Gœ*PíÛ
+bå¿ð ï °°
+*Àl/
+1¡#Ð rÖ2äS'p¢àÛÅñó?ÿ`ã}æ	¹Iª)ÊÛ,°Ÿ
+F3Ÿ!_tÔùæru©Ÿ|3Sà(1çÇ']áú7±ÌçÈ
+s
+À:@bØº¯¿Ke1Ý(p¯|m¡ïRÈŠ»¶÷/Â/š 
+b±ð C5û($»Í_Oá>Ô°k$U:çN_ ürÙ®ëX4¯ö^õªF^
+vÞ
+e×ÙÐè¹Ð ñúJÌ×f
+²ØQ|·cV¬Ë¿"øy'é"?yH`€1Y
+*P(÷nãy@ìÙðy/²V	Ò©ÇÀKqi=¢Aã?FZ#
+:rm;]$+=LX¹ÀM²Í÷C6\÷óíÐ{·)I£UK{á|_ _Dºí*£®VÏiD7aŠA¡ÀÜ6l<»8`
+)ŠÆyPŒ,Ô)JÏ;ÞWC@éPíVùÔ &ã§;eù²Uü,:h1=g
+ÌQ$|i\(âÓîâøwÑ$
+ºÌY=±b&4[¡N]Åè¥rR®\
+ºí£_áqyüÆéÑ¥ÚAš°ÙD=áä\8W÷`¯üÃœlò
+`b$n%ÿ
+ÛÉ_!p±Ü÷ñ-ÿžÈ¿ü°ÂkëÁâ§Ç
+:%+Cïbx4±ªó>"D÷sh'Ý/þúÕebBRÚ*·ÙYÝ+ýî[È³ÞLÕT;®zÄ
+@ç¿ÝÐ]
+ÀšÛý	MÇßí1Á.3hÿ<RÇô-»×Užhì
+œet}è9Yìk
+=ðÆgFáÏOÎ¹ Í;Ã?(þu'=ÄÆúÁú^%«?_¯wþý÷I(v€ü
+ú»ÑHj·îWÈœüIª
+õhtÑ`n	Vµ
+*ÍÔ«ðÌŸÞp×eAR¬'ßSê.ZiT|cè*ø}Kh¬~lûjõ
+;{<Z5=%fO/ÌÏb&|Z
+}¡Å |ÎXäQÓE"&
+fy[Çxõe B3YbKõi	F¶$~|dGÇzÐòAt÷#Å.Í
+öe}y­
+
+/F1DBÚu~~ß
+~0[|c~Iq8å"UI]×ÁQü^Ygè%|Û^èPUjo·	ùZñOô.
+×?W Å
+EÁgiB!Í€~ÌDÛ	rÈ|PjR
+5Ñ":!yn
+`<e8¯9ql-€È!6
+ZQ6v1fXÀAl×c9>=9ã»]gnn
+á  y61s^+S{e!Îa°8WÖFMWÅ}3ì?¡è.\{fe®^Ñ8ýýW	?Î0Û
+é'
+aqß~WÓ	¥]bXE(4]·4"Ž??Ú
+_€Tcn45I*Ÿ<÷;â9;tÚÛyÀ`Xô%?U<bXŽVãz	"ÏiŸ`	uZLdÀo:$p
+Ù:>
+e${jž
+é
+<~
+VXä*mð@P¿+Mìi&#}oWfÅZ³tO`
+
+±a¢j²X
+`I)
+;{
+åi^\&­=0nz
+žeL
+~$662YgeáVN2^=ÄTyzÿ&
+W
+¬aqu©_VJid3h;
+,E
+óxskò*P\!Yï3Sa4=2h\&ä
+]M
+*$Z
+C}M/è%¹@~ºoÝÌ2ïy[+£.B
+r6yÏY4y72
+#
+	}l(I¥pGS6hÅz)X?
+
+ç5³þ
+,t°:gY7÷Aø;|*Â]Js
+4,oÐñ"0z1ß
+v
+=²hiKø
+
+_wö{H!r<2¢@Ñ;4s>ë
+zp>±nb;|gnyÀ^xc]ºpÕOktœ/âoÑ€^ÆAœc³¯WFJ~~
+GB
+E
+âx!n#
+t|t@C0»8Ä]$?ëC>9:`ocEó
+4`]Z
+©ô0ema0!!p³æ3tç.Ñ,6Ypdo{\ÂódÆ,cñ<$]1M
+ì¹;!VW
+#Ss×xj\µvï+xv<N%"i>~ÎAÏ9'I;Mâf\U%z_ëm!|ÿvÕ[Å&EøËg"D[/·gT*DîÁkTn¥kD{31øeÃ>­dn ð,UK4Ýx
+Ñ	í\Q4&5K9s~L
+@MñdÜ+yÓ"4V|f9ä@9^y|#mWç>(4`
+%g3v,Ïv#øYe8ë[9Û6e,VÒ
+>M}|¯)«SÎ;Ð;å@;éC<{úxsZ93yFj°(cc|¡d,d
+
+uálŠš5®Wœ{O¥|²|H{!.ha{10uXñpësi%fä=N8~>zU[!íh¿-
+SUe{zÎ=îði
+$y{gièPÅy?VMQß
+ÜiŒ?
+XßjX]>i	Q.JÖIè]1	
+kÃTIs÷åfMuTk¯&¹rBbT"ÑbÖ!?ë9Švœí } ÷x·ä
+`
+:q+XÀRvGN9ó{*dvÌ|d}k4]ªZå8${ï0-qzŽBv
+F|o«Q`ÝÈwfú]A|g
+ëf~	O{
+UA%erÉKe
+Ü?
+i7Xö8&A]¢áB DvZ*
+â!sÍ$M7H?|ÿ{
+E_ÕL:#	_ötŠgVÿ$í"	M9ãcý2!)	Ñ[ŽcPF¶m
+="%uY3
+|wU
+Ç-@Tºb?`I!'KQ{8Ý*Ú=©
+û
+dE7b{€|zvÒOØ"@A
+ŠPï3ìkš}ö,ä ºt4êzh|ìQèkPQzñ#z
+i'
+ý
+Øb)
+ÈPI70;3
+yHA»/a(gÈÚ*ì
+»í
+@ÿI3P#Nõ~V/E:ÿòNþI±	ª
+c
+
+G>/\ÒF;\à"(kÀGqŒL€te	ýUÄD^9b~{9Mâ<=#
+
+ãPG_^W@TE^û<¥~·D&büyb=èAVhÜÄmëdC-WÏ,b>Z!q9E·  \\÷ojUÏÄKK{@ð+Å}ªuÞ{L
++rù
+Cs
+^J¿vt']ÅBÁ!ñ{œŒ||-FRjú~
+
+#i»Oµ.7 ¬z€U
+B|Lu$
+4/TGËU;ö?ºgU
+Xù
+ò	òS[
+Y
+Ao
+QBý\w^í@ÅR}Ušù{ÊuPFùrz ðu)5.-
+T
+{
+Ïiöd:æí
+ñÔf3N}uæ&
+Vâ"RÈzdp,.F!<"k:>À|géQÝG¢\ö	þ*Å7Û~þC}u+eL=<cµ
+å"F#PI8mi`¢E?&]U
+{DR]ên7^5:
+"ÉoÈbvZP P.âQ+Ô/ï\lŒ=G±A@TœtZ(zmáîB
+{z]~kULýg	6pg1ì0ð}²{ï×FÀRÎ
+²^#Êr¹mŸÔ	|ž%õ65`ÜdIS×? ð8
+K-rh¿euPz(­&
+à3 JY&_^F^@|
+ biy€ËLÕµGjsÿ3c/Wgt|0@
+ÐU;(jè%§78GnmúÅO#
+Þ#")Ó|ÜeR~¯
+g'è~
+ Š^ÌFmoãd©
+û=@p
+ÉÌ\3+!;êåtœE·?5ZjÔÈo÷[éŠ&óDü;àœxt;C¡T-&";Q^ÆøõÚ:Çú<j¡}uP`ÀŠO-^	smœVêhj%nÞ
+
+lz
+²XctöúzÔ	Üô|
+)nðzz,ê/IFYG fü]AQWPè
+xw3è%ÂhËÛ9Q
+
+r°ó	rÿ'
+§ôj
+ûEC[Èzaí[x¡±Ë{4D$t':tÅ*Õ{eÖ	¬z#Â%f%Ü{5õTKâ^ßB	úRŸ&7%5S\J@ IB0
+_Šk¶m)Gkm
+I
+Ÿa&njg1JM
+4 /Ï
+>²yYJ*^
+3("'a»2
+>ã,Ÿ+Gpsã,ÇB_3Ÿ&éLç&r<	
+I¿q3fŽVLÇBÙLE
+7²õW
+\&±øHû01kÿX¹-Â%1'If@²ÞUAT[ÐK!ŠH»{¹{ãÐO8G>/@-w4U_A
+'\
+ôbLÖ
+
+SüOñe
+±ñs){
+PtšSî3	¶oðzÐF^9OÒM
+hv]Wê
+46_Y t"ÏFÃdS
+3['YCò)qØy©&
+Ð&ü!!DÏZ;
+±oDymÂl» }oöy±:>0zh]Û.TÆ`VNK?ðjxlnÈáWÅ'ör
+@m
+WcGá:€DamY °:ÞA,q@qWIø;'/l¶OŠPn
+õ\±7'XWñoPzq/¹$gk³|RThs®©GÊ°mA"o¹m¢K9|I\
+C{ù ôSùkòß»gÆ@7ËZR«I1OÖ×é|ÔZyrwfètv!ø~0
+³@Ù{z
+iTŒb
+?°&§)1hhÈpA\Mm*
+¬yUfùwgB
+
+ðr@%]bÞå/6U8
+
+.-^i7ÆzJ-&PéaVJ
+K9
+ic*ÛNß"d!í8P:PBÓvàGS-M
+"b
+¥zU@ö 8
+â\¬`E
+hyF]iy~ÞSH`k%×R^
+Bîg2T
+ã ËdÝ8×
+qmýD?7ÙN	Ö	\ey"!j
+5N9>óKb~zRmlRë4"8
+
+Ä+WK'ú9-åQª
+)Ev
+Ï|%tà+Z³PŒu>ðd€@9zäd#Ë0OáZ¬"q
+{î6f~æ{9TÔ~M/P;ÿ"v)PŽVF#Ò
+;-:
+pv>ÿ1zìuVöV·
+úSE
+W~ y07êg}-äyu£q
+Zoh{/k4sA 	ÿgE÷/Eµï]iBF-#S/i|Š\(¥6W79°Psµ^?{°8TÂ`Ö8$ìYo
+
+ŒÁV%~4>I%
+Ô	NB6ÄR1**æ}î(QKn¥|¯]{v$õ	^do%ÆIÝ&ÛÞ.|-PŒ8€abUf:X7Ø9
+Ès94;2`Uÿ
+Wª 
+Â9Ð	x.|/iR»?D5@
+ùn=#
+MÕ93^0QG2I|ü¬teVÁ/ÀTÉÞfA`?T+DÖOØG?\'
+8mIs^©:=ÀUi"Ò'·¬@¡j«uMc2o1-¡J9S/Íz³;
+
+%r]Þ'GA(×RÔ	â3®"{qnÎŽ
+z
+o(Ò!¢
++6c&/:Ë]Õ3 t=lLW
+©gÆm]­Ä^J(y'HTjP@šÀG{WtbµAvF\@o\â^ÉE¬Š,qc:Ä9÷&hNdyc í\-ÛDÔdÞ$ÞYDÜp}ò%O?BL.m
+Yd§zÍ0<?ê)c_-v #@J»MÑo
+,
+Š]E5eYº
+j&5 »!Ì>qrŽ5
+yíbÎ2?ü5Ñ'>!QJm9+`?à=@jVô4¡yK\Ž|'
+iU
+
+HE³
+,Ê³.Ip6jpLë1
+
+]V­ ù
+©_LR«?>tûxQp<«ÅUýzxKÊÏ
+Ô9Ò1íA_7ñtvzø
+šd<ç&û)t
+a#3f3®*ñ'J*	[6]Ÿ9
+R5aXK
+a×
+®SKhú
+$
+ÙLäs°_õ8>)€{ìc+Hu-){4gAVhbJÅ4WY^-r%Ip0
+/YÏ?[Ác__OpalQ6
+@ÃæIXb^ôfxd1Ã>/ÁZoÊ&/jP#49lI
+Q(Eû	uÒw9/k
+uMùjC
+HY¹
+v Î}OdJCÔE?\K
+Ë{s[Àkh]·Ät	C3"§n &Î
+¶,[ÀÓhz$qqy~ÀHT+è)e-X5€F
+²YSl0z²
+U.mx
+Ì2,7¢œëHD¢dóö_9Q
+90$ý[sÔvÜ-/ÊQ%M	ýabl­;ñ'(c­;A cyW4Dz__L¿5hC%uÄ+
+ØGÛfK
+â%Ì
+ë6°Çpb÷=53Üö^enõ*dä
+û~Y14<K¬.{, 	õ{ôH#¢=èr;° (¢SÏ;d\wŽ^{
+Å
+áf
+'$­Nvi=kTW$T5n8^=)Ý[ç=}Ìò:Ìg$?Z,ÁHIJFt*Uë$ZGEÜŽ/©Mdp\lÈz¯°0lÎK{`~Hœjç@ñat"
+	H\Ÿ
+
+È
+¿
+Rp
+K!f)!¢HŽ>ù	å:°ö~üp5qàkC+Ž»!dXïX  #s§.
+9
+9-
+fwóXíyWIt\	I/ýrúcÚKù3:)#	n0.°+V2://ç6nª	0¢Æ
+>jü
+Ín<
+u
+L@}ª$
+.oa_~ö&1pÛKz *~iÙNÐrø.ñ/\,
+fZüü?æaI1DÇw,FA 0lÉÅ
+x{œ%Dül1!KYX
+ ŒXd
+¢
+D}\$	OKa:.eNÆ]šaØ
+
+?cßxhrVv!
+Ëxõ85l7lêÂ2RÒ$;ueÅ#€O5Wt
+#Y^4
+9í
+q¹nbNÓO.ySj0!Ï
+ÈSBY5Œ5×	Tf¬k
+ë5 *>TFB#(«QÏ·	I,at:è-û
+
+l<]«
+þ9IL#!)î
+P-1©3%¢O4weúJI¥
+¹¥»T-
+
+¯Yº/rŽ28î
+ÒTÈl­/kX ?+;%))Ü}UIN	ø
+wHüBþ
+Ÿ"
+È-òý"š'¹
+ /\
+z
Index: /indexers/branches/3.03a/mg/WIN32cfg.h
===================================================================
--- /indexers/branches/3.03a/mg/WIN32cfg.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/WIN32cfg.h	(revision 14757)
@@ -0,0 +1,163 @@
+/* config.h.  Generated automatically by configure.  */
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
+#endif
+
+/* Define if using alloca.c.  */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work.  */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro.  */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+/* #define HAVE_ALLOCA_H 1 */
+
+/* Define if you don't have vprintf but do have _doprnt.  */
+/* #undef HAVE_DOPRNT */
+
+/* Define if you have the vprintf function.  */
+#define HAVE_VPRINTF 1
+
+/* Define if on MINIX.  */
+/* #undef _MINIX */
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+/* #undef off_t */
+
+/* Define if the system does not provide POSIX.1 features except
+   with this defined.  */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define if you need to in order for stat and other things to work.  */
+/* #undef _POSIX_SOURCE */
+
+/* Define as the return type of signal handlers (int or void).  */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files.  */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+/* #define TIME_WITH_SYS_TIME 1 */
+
+/* Define if your <sys/time.h> declares struct tm.  */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define to the name of the distribution.  */
+#define PACKAGE "mg"
+
+/* Define to the version of the distribution.  */
+#define VERSION "1.2"
+
+/* Define to 1 if you have the valloc function.  */
+/* #define HAVE_VALLOC 1 */
+
+/* Define to 1 if ANSI function prototypes are usable.  */
+#define PROTOTYPES 1
+
+ 
+/* Define to 1 for better use of the debugging malloc library.  See
+   site ftp.antaire.com in antaire/src, file dmalloc/dmalloc.tar.gz.  */
+/* #undef WITH_DMALLOC */
+
+ 
+/* Define to 1 if GNU regex should be used instead of GNU rx.  */
+/* #undef WITH_REGEX */
+
+/* Some braindead header files do not have the requ'd function declarations */
+#define HAVE_FGETC_DECL 1
+#define HAVE_FREAD_DECL 1
+
+/* See if have this field in the prstatus_t structure */
+/* It stores the size of the process heap */
+/* #define HAVE_PR_BRKSIZE 1 */
+
+/* Define if you have the ftime function.  */
+/* #undef HAVE_FTIME */
+
+/* Define if you have the getpagesize function.  */
+/* #undef HAVE_GETPAGESIZE */
+
+/* Define if you have the getrusage function.  */
+/* #undef HAVE_GETRUSAGE */
+
+/* Define if you have the mallinfo function.  */
+/* #undef HAVE_MALLINFO */
+
+/* Define if you have the select function.  */
+#define HAVE_SELECT 1
+
+/* Define if you have the setbuffer function.  */
+/* #undef HAVE_SETBUFFER */
+
+/* Define if you have the strftime function.  */
+#define HAVE_STRFTIME 1
+
+/* Define if you have the strtol function.  */
+#define HAVE_STRTOL 1
+
+/* Define if you have the times function.  */
+/* #define HAVE_TIMES 1 */
+
+/* Define if you have the valloc function.  */
+/* #define HAVE_VALLOC 1 */
+
+/* Define if you have the <dirent.h> header file.  */
+/* #define HAVE_DIRENT_H 1 */
+
+/* Define if you have the <fcntl.h> header file.  */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file.  */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <memory.h> header file.  */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <ndir.h> header file.  */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <string.h> header file.  */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/dir.h> header file.  */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/ndir.h> header file.  */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/procfs.h> header file.  */
+/* #define HAVE_SYS_PROCFS_H 1 */
+
+/* Define if you have the <sys/time.h> header file.  */
+/* #define HAVE_SYS_TIME_H 1 */
+
+/* Define if you have the <unistd.h> header file.  */
+/* #define HAVE_UNISTD_H 1 */
+
+/* Define if you have the m library (-lm).  */
+#define HAVE_LIBM 1
Index: /indexers/branches/3.03a/mg/about_mg.html
===================================================================
--- /indexers/branches/3.03a/mg/about_mg.html	(revision 14757)
+++ /indexers/branches/3.03a/mg/about_mg.html	(revision 14757)
@@ -0,0 +1,75 @@
+<HTML>
+<HEAD>
+<TITLE>About MG</TITLE>
+</HEAD>
+<BODY>
+<H1>About MG</H1>
+ 
+<HR SIZE=4>
+
+MG is a public domain
+indexing and retrieval system for text, images, and textual images.
+MG is covered by a 
+<a href="http://deimos.kbs.citri.edu.au/mg/intro/copying.html">GNU 
+public licence</a>.
+<P>
+MG is available for ftp <a href="ftp://munnari.oz.au/pub/mg">here</a>
+
+<H2>Developers</H2>
+
+The MG system is an embodiment of ideas developed primarily by:
+<ul>
+<li> <a href="http://www.cosc.canterbury.ac.nz/~tim">Tim C. Bell</a>,
+	University of Canterbury;
+<li> <a href="http://www.cs.mu.oz.au/~alistair">Alistair Moffat</a>,
+	University of Melbourne;
+<li> <a href="http://www.cs.waikato.ac.nz/~ihw">Ian Witten</a>,
+	University of Waikato; and
+<li> <a href="http://www.cs.rmit.edu.au/~jz">Justin Zobel</a>,
+	RMIT.
+</ul>
+
+<H2>Programmers</H2>
+
+The bulk of the programming work has been undertaken by:
+<ul>
+<li><A HREF="http://www.cs.waikato.ac.nz/~singlis/">Stuart Inglis</A>,
+       University of Waikato;
+<li><A HREF="http://www.cs.waikato.ac.nz/~cgn/">Craig Nevill-Manning</A>,
+       University of Waikato;
+<li> Neil Sharman, University of Melbourne; and
+<li> Tim Shimmin, Collaborative Information Technology Research Institute (CITRI).
+</ul>
+A full list of contributors appears
+<A HREF="http://deimos.kbs.citri.edu.au/mg/intro/mgintro.html#xtocid2063010">
+here</a>.
+
+<H2>Institutional Support</H2>
+
+The MG project has been supported by the following organisations:
+<ul>
+<li>	The Australian Research Council;
+<li>	<a HREF="http://www.citri.edu.au/">CITRI</a>, Melbourne;
+<li>	The <a HREF="http://www.cpsc.ucalgary.ca/">University
+		of Calgary</a>, Canada;
+<li>	The <a HREF="http://www.cosc.canterbury.ac.nz/">University
+		of Canterbury</a>, New Zealand;
+<li>	The <a HREF="http://www.cs.mu.oz.au/">University
+		of Melbourne</a>, Australia;
+<li>	<a HREF="http://www.cs.rmit.edu.au/">RMIT</a>, Australia; and
+<li>	The <a HREF="http://www.cs.waikato.ac.nz/">University
+		of Waikato</a>, New Zealand.
+</ul>
+
+<H2>Backpointer</H2>
+
+If you didn't just come from there, the MG home page is accessible
+<a href="http://www.kbs.citri.edu.au/mg/">here</a>.
+
+<HR SIZE=4>
+<ADDRESS>alistair@cs.mu.oz.au</ADDRESS><BR>
+ 
+</BODY>
+</HTML>
+
+
Index: /indexers/branches/3.03a/mg/acconfig.h
===================================================================
--- /indexers/branches/3.03a/mg/acconfig.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/acconfig.h	(revision 14757)
@@ -0,0 +1,35 @@
+/* Special definitions for mg, processed by autoheader.
+   Created by [TS:Aug/95] 
+   by grepping for AC_DEFINE on configure.in and using the appropriate defs 
+   of acconfig.h used by GNU tar.
+*/
+
+/* Define to the name of the distribution.  */
+#undef PACKAGE
+
+/* Define to the version of the distribution.  */
+#undef VERSION
+
+/* Define if `union wait' is the type of the first arg to wait functions.  */
+#undef HAVE_UNION_WAIT
+
+/* Define to 1 if you have the valloc function.  */
+#undef HAVE_VALLOC
+
+/* Define to 1 if ANSI function prototypes are usable.  */
+#undef PROTOTYPES
+ 
+/* Define to 1 for better use of the debugging malloc library.  See
+   site ftp.antaire.com in antaire/src, file dmalloc/dmalloc.tar.gz.  */
+#undef WITH_DMALLOC
+ 
+/* Define to 1 if GNU regex should be used instead of GNU rx.  */
+#undef WITH_REGEX
+
+/* Some braindead header files do not have the requ'd function declarations */
+#undef HAVE_FGETC_DECL
+#undef HAVE_FREAD_DECL
+
+/* See if have this field in the prstatus_t structure */
+/* It stores the size of the process heap */
+#undef HAVE_PR_BRKSIZE
Index: /indexers/branches/3.03a/mg/aclocal.m4
===================================================================
--- /indexers/branches/3.03a/mg/aclocal.m4	(revision 14757)
+++ /indexers/branches/3.03a/mg/aclocal.m4	(revision 14757)
@@ -0,0 +1,140 @@
+# Local additions to Autoconf macros.
+# Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+# François Pinard <pinard@iro.umontreal.ca>, 1992.
+
+# [TS:Aug/95] - chopped out the NLS stuff which I don't support
+
+## ------------------------------- ##
+## Check for function prototypes.  ##
+## ------------------------------- ##
+
+AC_DEFUN(fp_C_PROTOTYPES,
+[AC_REQUIRE([fp_PROG_CC_STDC])
+AC_MSG_CHECKING([for function prototypes])
+if test "$ac_cv_prog_cc_stdc" != no; then
+  AC_MSG_RESULT(yes)
+  AC_DEFINE(PROTOTYPES)
+  U= ANSI2KNR=
+else
+  AC_MSG_RESULT(no)
+  U=_ ANSI2KNR=ansi2knr
+fi
+AC_SUBST(U)dnl
+AC_SUBST(ANSI2KNR)dnl
+])
+
+## ----------------------------------------- ##
+## ANSIfy the C compiler whenever possible.  ##
+## ----------------------------------------- ##
+
+# @defmac AC_PROG_CC_STDC
+# @maindex PROG_CC_STDC
+# @ovindex CC
+# If the C compiler in not in ANSI C mode by default, try to add an option
+# to output variable @code{CC} to make it so.  This macro tries various
+# options that select ANSI C on some system or another.  It considers the
+# compiler to be in ANSI C mode if it defines @code{__STDC__} to 1 and
+# handles function prototypes correctly.
+#
+# If you use this macro, you should check after calling it whether the C
+# compiler has been set to accept ANSI C; if not, the shell variable
+# @code{ac_cv_prog_cc_stdc} is set to @samp{no}.  If you wrote your source
+# code in ANSI C, you can make an un-ANSIfied copy of it by using the
+# program @code{ansi2knr}, which comes with Ghostscript.
+# @end defmac
+
+AC_DEFUN(fp_PROG_CC_STDC,
+[AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
+AC_CACHE_VAL(ac_cv_prog_cc_stdc,
+[ac_cv_prog_cc_stdc=no
+ac_save_CFLAGS="$CFLAGS"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX			-Aa -D_HPUX_SOURCE
+# SVR4			-Xc
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" -Xc
+do
+  CFLAGS="$ac_save_CFLAGS $ac_arg"
+  AC_TRY_COMPILE(
+[#if !defined(__STDC__) || __STDC__ != 1
+choke me
+#endif	
+], [int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};],
+[ac_cv_prog_cc_stdc="$ac_arg"; break])
+done
+CFLAGS="$ac_save_CFLAGS"
+])
+AC_MSG_RESULT($ac_cv_prog_cc_stdc)
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno) ;;
+  *) CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+])
+
+## --------------------------------------------------------- ##
+## Use AC_PROG_INSTALL, supplementing it with INSTALL_SCRIPT ##
+## substitution.					     ##
+## --------------------------------------------------------- ##
+
+AC_DEFUN(fp_PROG_INSTALL,
+[AC_PROG_INSTALL
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL} -m 755'
+AC_SUBST(INSTALL_SCRIPT)dnl
+])
+
+## ----------------------------------- ##
+## Check if --with-dmalloc was given.  ##
+## ----------------------------------- ##
+
+# I just checked, and GNU rx seems to work fine with a slightly
+# modified GNU m4.  So, I put out the test below in my aclocal.m4,
+# and will try to use it in my things.  The idea is to distribute
+# rx.[hc] and regex.[hc] together, for a while.  The WITH_REGEX symbol
+# (which should also be documented in acconfig.h) is used to decide
+# which of regex.h or rx.h should be included in the application.
+#
+# If `./configure --with-regex' is given, the package will use
+# the older regex.  Else, a check is made to see if rx is already
+# installed, as with newer Linux'es.  If not found, the package will
+# use the rx from the distribution.  If found, the package will use
+# the system's rx which, on Linux at least, will result in a smaller
+# executable file.
+
+AC_DEFUN(fp_WITH_DMALLOC,
+[AC_MSG_CHECKING(if malloc debugging is wanted)
+AC_ARG_WITH(dmalloc,
+[  --with-dmalloc          use dmalloc, as in
+                          ftp://ftp.letters.com/src/dmalloc/dmalloc.tar.gz],
+[if test "$withval" = yes; then
+  AC_MSG_RESULT(yes)
+  AC_DEFINE(WITH_DMALLOC)
+  LIBS="$LIBS -ldmalloc"
+  LDFLAGS="$LDFLAGS -g"
+else
+  AC_MSG_RESULT(no)
+fi], [AC_MSG_RESULT(no)])
+])
+
+## --------------------------------- ##
+## Check if --with-regex was given.  ##
+## --------------------------------- ##
+
+AC_DEFUN(fp_WITH_REGEX,
+[AC_MSG_CHECKING(which of rx or regex is wanted)
+AC_ARG_WITH(regex,
+[  --with-regex            use older regex in lieu of GNU rx for matching],
+[if test "$withval" = yes; then
+  ac_with_regex=1
+  AC_MSG_RESULT(regex)
+  AC_DEFINE(WITH_REGEX)
+  AC_LIBOBJ([regex])
+fi])
+if test -z "$ac_with_regex"; then
+  AC_MSG_RESULT(rx)
+  AC_CHECK_FUNC(re_rx_search, , [AC_LIBOBJ([rx])])
+fi
+])
Index: /indexers/branches/3.03a/mg/build_options.in
===================================================================
--- /indexers/branches/3.03a/mg/build_options.in	(revision 14757)
+++ /indexers/branches/3.03a/mg/build_options.in	(revision 14757)
@@ -0,0 +1,2 @@
+set stem_method = 3
+set do_indexes = 1
Index: /indexers/branches/3.03a/mg/config.guess
===================================================================
--- /indexers/branches/3.03a/mg/config.guess	(revision 14757)
+++ /indexers/branches/3.03a/mg/config.guess	(revision 14757)
@@ -0,0 +1,470 @@
+#!/bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+#
+# This file 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    alpha:OSF1:V*:*)
+	# After 1.2, OSF1 uses "V1.3" for uname -r.
+	echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^V//'`
+	exit 0 ;;
+    alpha:OSF1:*:*)
+	# 1.2 uses "1.2" for uname -r.
+	echo alpha-dec-osf${UNAME_RELEASE}
+        exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit 0;;
+    Pyramid*:OSx*:*:*)
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit 0 ;;
+    sun4*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:*:*)
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit 0 ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    mips:*:5*:RISCos)
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit 0 ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit 0 ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit 0 ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    AViiON:dgux:*:*)
+	if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
+	     -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	fi
+ 	exit 0 ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit 0 ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit 0 ;;
+    *:IRIX:*:*)
+	echo mips-sgi-irix${UNAME_RELEASE}
+	exit 0 ;;
+    i[34]86:AIX:*:*)
+	echo i386-ibm-aix
+	exit 0 ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		sed 's/^		//' << EOF >dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+		rm -f dummy.c dummy
+		echo rs6000-ibm-aix3.2.5
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit 0 ;;
+    *:AIX:*:4)
+	if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if grep bos410 /usr/include/stdio.h >/dev/null 2>&1; then
+		IBM_REV=4.1
+	elif grep bos411 /usr/include/stdio.h >/dev/null 2>&1; then
+		IBM_REV=4.1.1
+	else
+		IBM_REV=4.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit 0 ;;
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit 0 ;;
+    9000/[3478]??:HP-UX:*:*)
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/7?? | 9000/8?7 ) HP_ARCH=hppa1.1 ;;
+	    9000/8?? )            HP_ARCH=hppa1.0 ;;
+	esac
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    3050*:HI-UX:*:*)
+	sed 's/^	//' << EOF >dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+	rm -f dummy.c dummy
+	echo unknown-hitachi-hiuxwe2
+	exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?7:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit 0 ;;
+    hp7??:OSF1:*:* | hp8?7:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit 0 ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*X-MP:UNICOS:*:*)
+	echo xmp-cray-unicos
+        exit 0 ;;
+    CRAY*Y-MP:UNICOS:*:*)
+	echo ymp-cray-unicos
+        exit 0 ;;
+    CRAY-2:UNICOS:*:*)
+	echo cray2-cray-unicos
+        exit 0 ;;
+    hp3[0-9][05]:NetBSD:*:*)
+	echo m68k-hp-netbsd${UNAME_RELEASE}
+	exit 0 ;;
+    i[34]86:BSD/386:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:FreeBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit 0 ;;
+    *:NetBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	exit 0 ;;
+    *:GNU:*:*)
+	echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit 0 ;;
+    *:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux
+	exit 0 ;;
+# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.  earlier versions
+# are messed up and put the nodename in both sysname and nodename.
+    i[34]86:DYNIX/ptx:4*:*)
+	echo i386-sequent-sysv4
+	exit 0 ;;
+    i[34]86:*:4.*:* | i[34]86:SYSTEM_V:4.*:*)
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+	else
+		echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}
+	fi
+	exit 0 ;;
+    i[34]86:*:3.2:*)
+	if /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+		echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL
+	elif test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-unknown-isc$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-unknown-sysv32
+	fi
+	exit 0 ;;
+    Intel:Mach:3*:*)
+	echo i386-unknown-mach3
+	exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit 0 ;;
+    M680[234]0:*:R3V[567]*:*)
+	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0)
+        uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4.3 && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m680[234]0:LynxOS:2.2*:*)
+	echo m68k-lynx-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit 0 ;;
+    i[34]86:LynxOS:2.2*:*)
+	echo i386-lynx-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    TSUNAMI:LynxOS:2.2*:*)
+	echo sparc-lynx-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    rs6000:LynxOS:2.2*:*)
+	echo rs6000-lynx-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >dummy.c <<EOF
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+  printf ("m68k-sony-newsos\n"); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  printf ("%s-next-nextstep%s\n", __ARCHITECTURE__,  version==2 ? "2" : "3");
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-unknown-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+  printf ("i386-sequent-ptx\n"); exit (0);
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+  printf ("vax-dec-bsd\n"); exit (0);
+#else
+  printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit 0 ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit 0 ;;
+    c34*)
+	echo c34-convex-bsd
+	exit 0 ;;
+    c38*)
+	echo c38-convex-bsd
+	exit 0 ;;
+    c4*)
+	echo c4-convex-bsd
+	exit 0 ;;
+    esac
+fi
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
Index: /indexers/branches/3.03a/mg/config.h.in
===================================================================
--- /indexers/branches/3.03a/mg/config.h.in	(revision 14757)
+++ /indexers/branches/3.03a/mg/config.h.in	(revision 14757)
@@ -0,0 +1,177 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+#undef _ALL_SOURCE
+#endif
+
+/* Define if using alloca.c.  */
+#undef C_ALLOCA
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro.  */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+#undef HAVE_ALLOCA_H
+
+/* Define if you don't have vprintf but do have _doprnt.  */
+#undef HAVE_DOPRNT
+
+/* Define if you have the vprintf function.  */
+#undef HAVE_VPRINTF
+
+/* Define if on MINIX.  */
+#undef _MINIX
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+#undef off_t
+
+/* Define if the system does not provide POSIX.1 features except
+   with this defined.  */
+#undef _POSIX_1_SOURCE
+
+/* Define if you need to in order for stat and other things to work.  */
+#undef _POSIX_SOURCE
+
+/* Define as the return type of signal handlers (int or void).  */
+#undef RETSIGTYPE
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+#undef TIME_WITH_SYS_TIME
+
+/* Define if your <sys/time.h> declares struct tm.  */
+#undef TM_IN_SYS_TIME
+
+/* Define to the name of the distribution.  */
+#undef PACKAGE
+
+/* Define to the version of the distribution.  */
+#undef VERSION
+
+/* Define to 1 if you have the valloc function.  */
+#undef HAVE_VALLOC
+
+/* Define to 1 if ANSI function prototypes are usable.  */
+#undef PROTOTYPES
+
+ 
+/* Define to 1 for better use of the debugging malloc library.  See
+   site ftp.antaire.com in antaire/src, file dmalloc/dmalloc.tar.gz.  */
+#undef WITH_DMALLOC
+
+ 
+/* Define to 1 if GNU regex should be used instead of GNU rx.  */
+#undef WITH_REGEX
+
+/* Some braindead header files do not have the requ'd function declarations */
+#undef HAVE_FGETC_DECL
+#undef HAVE_FREAD_DECL
+
+/* See if have this field in the prstatus_t structure */
+/* It stores the size of the process heap */
+#undef HAVE_PR_BRKSIZE
+
+/* Define if you have the ftime function.  */
+#undef HAVE_FTIME
+
+/* Define if you have the ftruncate function.  */
+#undef HAVE_FTRUNCATE
+
+/* Define if you have the getpagesize function.  */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the getrusage function.  */
+#undef HAVE_GETRUSAGE
+
+/* Define if you have the mallinfo function.  */
+#undef HAVE_MALLINFO
+
+/* Define if you have the select function.  */
+#undef HAVE_SELECT
+
+/* Define if you have the setbuffer function.  */
+#undef HAVE_SETBUFFER
+
+/* Define if you have the strcasecmp function.  */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the strerror function.  */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strftime function.  */
+#undef HAVE_STRFTIME
+
+/* Define if you have the strstr function.  */
+#undef HAVE_STRSTR
+
+/* Define if you have the strtol function.  */
+#undef HAVE_STRTOL
+
+/* Define if you have the times function.  */
+#undef HAVE_TIMES
+
+/* Define if you have the valloc function.  */
+#undef HAVE_VALLOC
+
+/* Define if you have the <dirent.h> header file.  */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the <fcntl.h> header file.  */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <limits.h> header file.  */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <memory.h> header file.  */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <ndir.h> header file.  */
+#undef HAVE_NDIR_H
+
+/* Define if you have the <string.h> header file.  */
+#undef HAVE_STRING_H
+
+/* Define if you have the <sys/dir.h> header file.  */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have the <sys/ndir.h> header file.  */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if you have the <sys/procfs.h> header file.  */
+#undef HAVE_SYS_PROCFS_H
+
+/* Define if you have the <sys/time.h> header file.  */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the m library (-lm).  */
+#undef HAVE_LIBM
+
+/* Define if big endian */
+#undef WORDS_BIGENDIAN
Index: /indexers/branches/3.03a/mg/config.sub
===================================================================
--- /indexers/branches/3.03a/mg/config.sub	(revision 14757)
+++ /indexers/branches/3.03a/mg/config.sub	(revision 14757)
@@ -0,0 +1,793 @@
+#!/bin/sh
+# Configuration validation subroutine script, version 1.1.
+#   Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can. 
+#
+# This file 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+# First pass through any local machine types.
+case $1 in
+	*local*)
+		echo $1
+		exit 0
+		;;
+	*)
+	;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS (if any).
+basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+if [ $basic_machine != $1 ]
+then os=`echo $1 | sed 's/.*-/-/'`
+else os=; fi
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp )
+		os=
+		basic_machine=$1
+		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+		;;
+	-lynx)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	tahoe | i[345]86 | i860 | m68k | m68000 | m88k | ns32k | arm | pyramid \
+		| tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \
+		| alpha | we32k | ns16k | clipper | sparclite | i370 | sh \
+		| powerpc | sparc64 | 1750a | dsp16xx | mips64 | mipsel \
+		| pdp11 | mips64el | mips64orion | mips64orionel )
+		basic_machine=$basic_machine-unknown
+		;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	vax-* | tahoe-* | i[345]86-* | i860-* | m68k-* | m68000-* | m88k-* \
+	      | sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
+	      | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+	      | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
+	      | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
+	      | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
+	      | pdp11-* | sh-* | powerpc-* | sparc64-* | mips64-* | mipsel-* \
+	      | mips64el-* | mips64orion-* | mips64orionel-* )
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-cbm
+		;;
+	amigados)
+		basic_machine=m68k-cbm
+		os=-amigados
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-cbm
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	cray2)
+		basic_machine=cray2-cray
+		os=-unicos
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i[345]86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+		os=-sysv32
+		;;
+	i[345]86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+		os=-sysv4
+		;;
+	i[345]86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+		os=-sysv
+		;;
+	i[345]86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+		os=-solaris2
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+        pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pentium-*)
+		# We will change tis to say i586 once there has been
+		# time for various packages to start to recognize that.
+		basic_machine=i486-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	xmp)
+		basic_machine=xmp-cray
+		os=-unicos
+		;;
+        xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	mips)
+		basic_machine=mips-mips
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sparc)
+		basic_machine=sparc-sun
+		;;
+        cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative must end in a *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[345]* \
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigados* | -msdos* | -newsos* | -unicos* | -aos* \
+	      | -nindy* | -vxworks* | -ebmon* | -hms* | -mvs* | -clix* \
+	      | -riscos* | -linux* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -netbsd* | -freebsd* | -riscix* \
+	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
+	      | -ptx* | -coff* | -winnt*)
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	*-acorn)
+		os=-riscix1.2
+		;;
+        pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigados
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+        *-gould)
+		os=-sysv
+		;;
+        *-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+        *-sgi)
+		os=-irix
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-lynxos*)
+				vendor=lynx
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
Index: /indexers/branches/3.03a/mg/configure
===================================================================
--- /indexers/branches/3.03a/mg/configure	(revision 14757)
+++ /indexers/branches/3.03a/mg/configure	(revision 14757)
@@ -0,0 +1,7764 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="src/text/mgquery.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS PACKAGE VERSION CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT AWK YACC CC CFLAGS ac_ct_CC INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP U ANSI2KNR ALLOCA LIBOBJS JNIINC JNISUFFIX JNIFLAGS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+	      localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$0" : 'X\(//\)[^/]' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CXX_set=${CXX+set}
+ac_env_CXX_value=$CXX
+ac_cv_env_CXX_set=${CXX+set}
+ac_cv_env_CXX_value=$CXX
+ac_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_env_CXXFLAGS_value=$CXXFLAGS
+ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_cv_env_CXXFLAGS_value=$CXXFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+			  [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+			  [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-dmalloc          use dmalloc, as in
+                          ftp://ftp.letters.com/src/dmalloc/dmalloc.tar.gz
+  --with-regex            use older regex in lieu of GNU rx for matching
+
+Some influential environment variables:
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+	   test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+	"s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=$`echo $ac_var`
+	echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+	       sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+	ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+          ac_config_headers="$ac_config_headers config.h"
+
+test "$program_prefix" != NONE &&
+  program_transform_name="s,^,$program_prefix,;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s,\$,$program_suffix,;$program_transform_name"
+# Double any \ or $.  echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm conftest.sed
+
+
+PACKAGE=mg
+VERSION=1.2
+
+LDFLAGS=
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+
+
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CXX" && break
+done
+test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
+
+  CXX=$ac_ct_CXX
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C++ compiler default output file name" >&5
+echo $ECHO_N "checking for C++ compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+	;;
+    conftest.$ac_ext )
+	# This is the source file.
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	# FIXME: I believe we export ac_cv_exeext for Libtool,
+	# but it would be cool to find out if it's true.  Does anybody
+	# maintain Libtool? --akim.
+	export ac_cv_exeext
+	break;;
+    * )
+	break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C++ compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5
+echo $ECHO_N "checking whether the C++ compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { echo "$as_me:$LINENO: error: cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  export ac_cv_exeext
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cxx_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cxx_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$AWK" && break
+done
+
+for ac_prog in 'bison -y' byacc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_YACC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_YACC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+  echo "$as_me:$LINENO: result: $YACC" >&5
+echo "${ECHO_T}$YACC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX 10.20 and later	-Ae
+# HP-UX older versions	-Aa -D_HPUX_SOURCE
+# SVR4			-Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	    break 3
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+all:
+	@echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  SET_MAKE=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+
+echo "$as_me:$LINENO: checking for AIX" >&5
+echo $ECHO_N "checking for AIX... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef _AIX
+  yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+cat >>confdefs.h <<\_ACEOF
+#define _ALL_SOURCE 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+
+echo "$as_me:$LINENO: checking for library containing strerror" >&5
+echo $ECHO_N "checking for library containing strerror... $ECHO_C" >&6
+if test "${ac_cv_search_strerror+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_strerror=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char strerror ();
+int
+main ()
+{
+strerror ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_strerror="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_strerror" = no; then
+  for ac_lib in cposix; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char strerror ();
+int
+main ()
+{
+strerror ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_strerror="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_strerror" >&5
+echo "${ECHO_T}$ac_cv_search_strerror" >&6
+if test "$ac_cv_search_strerror" != no; then
+  test "$ac_cv_search_strerror" = "none required" || LIBS="$ac_cv_search_strerror $LIBS"
+
+fi
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+if test "${ac_cv_header_minix_config_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for minix/config.h" >&5
+echo $ECHO_N "checking for minix/config.h... $ECHO_C" >&6
+if test "${ac_cv_header_minix_config_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_minix_config_h" >&5
+echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking minix/config.h usability" >&5
+echo $ECHO_N "checking minix/config.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <minix/config.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking minix/config.h presence" >&5
+echo $ECHO_N "checking minix/config.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <minix/config.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: minix/config.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: minix/config.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: minix/config.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: minix/config.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: minix/config.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: minix/config.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: minix/config.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: minix/config.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for minix/config.h" >&5
+echo $ECHO_N "checking for minix/config.h... $ECHO_C" >&6
+if test "${ac_cv_header_minix_config_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_minix_config_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_minix_config_h" >&5
+echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6
+
+fi
+if test $ac_cv_header_minix_config_h = yes; then
+  MINIX=yes
+else
+  MINIX=
+fi
+
+
+if test "$MINIX" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define _POSIX_SOURCE 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _POSIX_1_SOURCE 2
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _MINIX 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for ${CC-cc} option to accept ANSI C" >&5
+echo $ECHO_N "checking for ${CC-cc} option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CFLAGS="$CFLAGS"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX			-Aa -D_HPUX_SOURCE
+# SVR4			-Xc
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" -Xc
+do
+  CFLAGS="$ac_save_CFLAGS $ac_arg"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if !defined(__STDC__) || __STDC__ != 1
+choke me
+#endif
+
+int
+main ()
+{
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc="$ac_arg"; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+CFLAGS="$ac_save_CFLAGS"
+
+fi
+
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno) ;;
+  *) CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+
+echo "$as_me:$LINENO: checking for function prototypes" >&5
+echo $ECHO_N "checking for function prototypes... $ECHO_C" >&6
+if test "$ac_cv_prog_cc_stdc" != no; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  cat >>confdefs.h <<\_ACEOF
+#define PROTOTYPES 1
+_ACEOF
+
+  U= ANSI2KNR=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  U=_ ANSI2KNR=ansi2knr
+fi
+
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset x;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *ccp;
+  char **p;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  ccp = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++ccp;
+  p = (char**) ccp;
+  ccp = (char const *const *) p;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+  }
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_const=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6
+if test "${ac_cv_type_off_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((off_t *) 0)
+  return 0;
+if (sizeof (off_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_off_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_off_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6
+if test $ac_cv_type_off_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((size_t *) 0)
+  return 0;
+if (sizeof (size_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_size_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_size_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6
+if test "${ac_cv_header_time+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_time=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_time=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
+echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6
+if test "${ac_cv_struct_tm+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm *tp; tp->tm_sec;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_struct_tm=time.h
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5
+echo "${ECHO_T}$ac_cv_struct_tm" >&6
+if test $ac_cv_struct_tm = sys/time.h; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TM_IN_SYS_TIME 1
+_ACEOF
+
+fi
+
+
+if test "$ac_cv_prog_cc_stdc" = '-Xc'; then
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+
+int
+main ()
+{
+ FILE *rubbish = popen("yes", "r");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+CC="`echo $CC | sed 's/-Xc/-Xa/'`"    ac_cv_prog_cc_stdc='-Xa'
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+echo "$as_me:$LINENO: checking for main in -lm" >&5
+echo $ECHO_N "checking for main in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_m_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_main" >&5
+echo "${ECHO_T}$ac_cv_lib_m_main" >&6
+if test $ac_cv_lib_m_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+  LIBS="-lm $LIBS"
+
+fi
+
+
+
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+  as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in dir; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+else
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in x; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+fi
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+
+
+for ac_header in fcntl.h limits.h sys/time.h unistd.h string.h memory.h sys/procfs.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "fread" >/dev/null 2>&1; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_FREAD_DECL 1
+_ACEOF
+
+fi
+rm -f conftest*
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "fgetc" >/dev/null 2>&1; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_FGETC_DECL 1
+_ACEOF
+
+fi
+rm -f conftest*
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/procfs.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "pr_brksize" >/dev/null 2>&1; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_PR_BRKSIZE 1
+_ACEOF
+
+fi
+rm -f conftest*
+
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+echo "$as_me:$LINENO: checking for working alloca.h" >&5
+echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6
+if test "${ac_cv_working_alloca_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_working_alloca_h=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_working_alloca_h=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5
+echo "${ECHO_T}$ac_cv_working_alloca_h" >&6
+if test $ac_cv_working_alloca_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA_H 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for alloca" >&5
+echo $ECHO_N "checking for alloca... $ECHO_C" >&6
+if test "${ac_cv_func_alloca_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  if HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_alloca_works=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_alloca_works=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5
+echo "${ECHO_T}$ac_cv_func_alloca_works" >&6
+
+if test $ac_cv_func_alloca_works = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA 1
+_ACEOF
+
+else
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble.  Some versions do not even contain alloca or
+# contain a buggy version.  If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=alloca.$ac_objext
+
+cat >>confdefs.h <<\_ACEOF
+#define C_ALLOCA 1
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5
+echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6
+if test "${ac_cv_os_cray+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "webecray" >/dev/null 2>&1; then
+  ac_cv_os_cray=yes
+else
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5
+echo "${ECHO_T}$ac_cv_os_cray" >&6
+if test $ac_cv_os_cray = yes; then
+  for ac_func in _getb67 GETB67 getb67; do
+    as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+    break
+fi
+
+  done
+fi
+
+echo "$as_me:$LINENO: checking stack direction for C alloca" >&5
+echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6
+if test "${ac_cv_c_stack_direction+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_stack_direction=0
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+int
+find_stack_direction ()
+{
+  static char *addr = 0;
+  auto char dummy;
+  if (addr == 0)
+    {
+      addr = &dummy;
+      return find_stack_direction ();
+    }
+  else
+    return (&dummy > addr) ? 1 : -1;
+}
+
+int
+main ()
+{
+  exit (find_stack_direction () < 0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_stack_direction=1
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_stack_direction=-1
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5
+echo "${ECHO_T}$ac_cv_c_stack_direction" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+if test $ac_cv_c_compiler_gnu = yes; then
+    echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5
+echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6
+if test "${ac_cv_prog_gcc_traditional+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+    ac_pattern="Autoconf.*'x'"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then
+  ac_cv_prog_gcc_traditional=yes
+else
+  ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+  if test $ac_cv_prog_gcc_traditional = no; then
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then
+  ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+  fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5
+echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6
+  if test $ac_cv_prog_gcc_traditional = yes; then
+    CC="$CC -traditional"
+  fi
+fi
+
+echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6
+if test "${ac_cv_type_signal+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+# undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int
+main ()
+{
+int i;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_signal=void
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_signal=int
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+
+for ac_func in vprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+echo "$as_me:$LINENO: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6
+if test "${ac_cv_func__doprnt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define _doprnt innocuous__doprnt
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char _doprnt (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef _doprnt
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char _doprnt ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub__doprnt) || defined (__stub____doprnt)
+choke me
+#else
+char (*f) () = _doprnt;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != _doprnt;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func__doprnt=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func__doprnt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6
+if test $ac_cv_func__doprnt = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DOPRNT 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in ftime select strftime strtol getrusage times mallinfo setbuffer getpagesize
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+for ac_func in ftruncate strstr strcasecmp
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case $LIBOBJS in
+    "$ac_func.$ac_objext"   | \
+  *" $ac_func.$ac_objext"   | \
+    "$ac_func.$ac_objext "* | \
+  *" $ac_func.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;;
+esac
+
+fi
+done
+
+
+
+
+# *** Custom checking (based on GNU tar configure.in) ***
+# ---------------------------------------------------------------------------
+echo "$as_me:$LINENO: checking for HP-UX needing gmalloc" >&5
+echo $ECHO_N "checking for HP-UX needing gmalloc... $ECHO_C" >&6
+if test "`(uname -s) 2> /dev/null`" = 'HP-UX'; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  case $LIBOBJS in
+    "gmalloc.$ac_objext"   | \
+  *" gmalloc.$ac_objext"   | \
+    "gmalloc.$ac_objext "* | \
+  *" gmalloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS gmalloc.$ac_objext" ;;
+esac
+
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_VALLOC 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+for ac_func in valloc
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+fi
+
+# we need to set an extended JNI path for Mac OS/Darwin, as jni.h is on
+# a non-standard Path
+# is there a better way to do this??
+echo "$as_me:$LINENO: checking for OS to set JNI options" >&5
+echo $ECHO_N "checking for OS to set JNI options... $ECHO_C" >&6
+# set defaults
+JNIINC=""
+JNISUFFIX="so"
+JNIFLAGS="-shared"
+
+if test "`(uname -s) 2> /dev/null`" = 'Darwin'; then
+  echo "$as_me:$LINENO: result: Darwin" >&5
+echo "${ECHO_T}Darwin" >&6
+  JNIINC="-I/System/Library/Frameworks/JavaVM.framework/Headers/ "
+  JNISUFFIX="jnilib"
+  JNIFLAGS="-dynamiclib -fno-common -single_module -framework JavaVM"
+fi
+if test "`(uname -s) 2> /dev/null`" = 'SunOS'; then
+  echo "$as_me:$LINENO: result: Solaris" >&5
+echo "${ECHO_T}Solaris" >&6
+  JNIINC="-I\$(JAVA_HOME)/include/solaris "
+fi
+if test "`(uname -s) 2> /dev/null`" = 'Linux'; then
+  echo "$as_me:$LINENO: result: Linux" >&5
+echo "${ECHO_T}Linux" >&6
+  JNIINC="-I\$(JAVA_HOME)/include/linux "
+fi
+
+
+
+
+
+echo "$as_me:$LINENO: checking if malloc debugging is wanted" >&5
+echo $ECHO_N "checking if malloc debugging is wanted... $ECHO_C" >&6
+
+# Check whether --with-dmalloc or --without-dmalloc was given.
+if test "${with_dmalloc+set}" = set; then
+  withval="$with_dmalloc"
+  if test "$withval" = yes; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  cat >>confdefs.h <<\_ACEOF
+#define WITH_DMALLOC 1
+_ACEOF
+
+  LIBS="$LIBS -ldmalloc"
+  LDFLAGS="$LDFLAGS -g"
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi;
+
+echo "$as_me:$LINENO: checking which of rx or regex is wanted" >&5
+echo $ECHO_N "checking which of rx or regex is wanted... $ECHO_C" >&6
+
+# Check whether --with-regex or --without-regex was given.
+if test "${with_regex+set}" = set; then
+  withval="$with_regex"
+  if test "$withval" = yes; then
+  ac_with_regex=1
+  echo "$as_me:$LINENO: result: regex" >&5
+echo "${ECHO_T}regex" >&6
+  cat >>confdefs.h <<\_ACEOF
+#define WITH_REGEX 1
+_ACEOF
+
+  case $LIBOBJS in
+    "regex.$ac_objext"   | \
+  *" regex.$ac_objext"   | \
+    "regex.$ac_objext "* | \
+  *" regex.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS regex.$ac_objext" ;;
+esac
+
+fi
+fi;
+if test -z "$ac_with_regex"; then
+  echo "$as_me:$LINENO: result: rx" >&5
+echo "${ECHO_T}rx" >&6
+  echo "$as_me:$LINENO: checking for re_rx_search" >&5
+echo $ECHO_N "checking for re_rx_search... $ECHO_C" >&6
+if test "${ac_cv_func_re_rx_search+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define re_rx_search to an innocuous variant, in case <limits.h> declares re_rx_search.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define re_rx_search innocuous_re_rx_search
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char re_rx_search (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef re_rx_search
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char re_rx_search ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_re_rx_search) || defined (__stub___re_rx_search)
+choke me
+#else
+char (*f) () = re_rx_search;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != re_rx_search;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_re_rx_search=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_re_rx_search=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_re_rx_search" >&5
+echo "${ECHO_T}$ac_cv_func_re_rx_search" >&6
+if test $ac_cv_func_re_rx_search = yes; then
+  :
+else
+  case $LIBOBJS in
+    "rx.$ac_objext"   | \
+  *" rx.$ac_objext"   | \
+    "rx.$ac_objext "* | \
+  *" rx.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS rx.$ac_objext" ;;
+esac
+
+fi
+
+fi
+
+
+# text for endianness
+echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
+if test "${ac_cv_c_bigendian+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_bigendian=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+# It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+  # try to guess the endianness by grepping values into an object file
+  ac_cv_c_bigendian=unknown
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+  ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+  if test "$ac_cv_c_bigendian" = unknown; then
+    ac_cv_c_bigendian=no
+  else
+    # finding both strings is unlikely to happen, but who knows?
+    ac_cv_c_bigendian=unknown
+  fi
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+int
+main ()
+{
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long l;
+    char c[sizeof (long)];
+  } u;
+  u.l = 1;
+  exit (u.c[sizeof (long) - 1] == 1);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6
+case $ac_cv_c_bigendian in
+  yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+  no)
+     ;;
+  *)
+    { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+
+# ---------------------------------------------------------------------------
+if test "$ac_cv_func_alloca" = 'no'; then
+  case $LIBOBJS in
+    "xmalloc.$ac_objext"   | \
+  *" xmalloc.$ac_objext"   | \
+    "xmalloc.$ac_objext "* | \
+  *" xmalloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS xmalloc.$ac_objext" ;;
+esac
+
+  case $LIBOBJS in
+    "error.$ac_objext"   | \
+  *" error.$ac_objext"   | \
+    "error.$ac_objext "* | \
+  *" error.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS error.$ac_objext" ;;
+esac
+
+fi
+
+
+# ---------------------------------------------------------------------------
+
+                                                                      ac_config_files="$ac_config_files Makefile src/text/Makefile src/images/Makefile src/scripts/Makefile lib/Makefile jni/Makefile java/org/greenstone/mg/Makefile"
+          ac_config_commands="$ac_config_commands default"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[	 ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[	 ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+	 sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+		   instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+		   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "src/text/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/text/Makefile" ;;
+  "src/images/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/images/Makefile" ;;
+  "src/scripts/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/scripts/Makefile" ;;
+  "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
+  "jni/Makefile" ) CONFIG_FILES="$CONFIG_FILES jni/Makefile" ;;
+  "java/org/greenstone/mg/Makefile" ) CONFIG_FILES="$CONFIG_FILES java/org/greenstone/mg/Makefile" ;;
+  "default" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
+  "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@PACKAGE@,$PACKAGE,;t t
+s,@VERSION@,$VERSION,;t t
+s,@CXX@,$CXX,;t t
+s,@CXXFLAGS@,$CXXFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CXX@,$ac_ct_CXX,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@AWK@,$AWK,;t t
+s,@YACC@,$YACC,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@LN_S@,$LN_S,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@U@,$U,;t t
+s,@ANSI2KNR@,$ANSI2KNR,;t t
+s,@ALLOCA@,$ALLOCA,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@JNIINC@,$JNIINC,;t t
+s,@JNISUFFIX@,$JNISUFFIX,;t t
+s,@JNIFLAGS@,$JNIFLAGS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+	cat >$tmp/stdin
+	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+				     sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+	 # Absolute (can't be DOS-style, as IFS=:)
+	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 echo "$f";;
+      *) # Relative
+	 if test -f "$f"; then
+	   # Build tree
+	   echo "$f"
+	 elif test -f "$srcdir/$f"; then
+	   # Source tree
+	   echo "$srcdir/$f"
+	 else
+	   # /dev/null tree
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([	 ]*\)#\([	 ]*define[	 ][	 ]*\)'
+ac_dB='[	 ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([	 ]*\)#\([	 ]*\)undef\([	 ][	 ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+	cat >$tmp/stdin
+	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+	 # Absolute (can't be DOS-style, as IFS=:)
+	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 # Do quote $f, to prevent DOS paths from being IFS'd.
+	 echo "$f";;
+      *) # Relative
+	 if test -f "$f"; then
+	   # Build tree
+	   echo "$f"
+	 elif test -f "$srcdir/$f"; then
+	   # Source tree
+	   echo "$srcdir/$f"
+	 else
+	   # /dev/null tree
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[	 ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*\)\(([^)]*)\)[	 ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[	 ]*#[	 ]*undef[	 ][	 ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if grep "^[	 ]*#[	 ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[	 ]*#[	 ]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo '  fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[	 ]*#[	 ]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+      { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+  ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+  ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+  ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_dest" : 'X\(//\)[^/]' \| \
+	 X"$ac_dest" : 'X\(//\)$' \| \
+	 X"$ac_dest" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+  case $ac_dest in
+    default ) test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h ;;
+  esac
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
Index: /indexers/branches/3.03a/mg/configure.in
===================================================================
--- /indexers/branches/3.03a/mg/configure.in	(revision 14757)
+++ /indexers/branches/3.03a/mg/configure.in	(revision 14757)
@@ -0,0 +1,133 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(src/text/mgquery.c)
+AC_CONFIG_HEADER(config.h)
+AC_ARG_PROGRAM
+
+dnl
+PACKAGE=mg
+VERSION=1.2
+
+LDFLAGS=
+
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
+AC_SUBST(PACKAGE)
+AC_SUBST(VERSION)
+
+dnl Checks for programs.
+AC_PROG_CXX
+AC_PROG_AWK
+AC_PROG_YACC
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_AIX
+AC_ISC_POSIX
+AC_MINIX
+fp_C_PROTOTYPES
+AC_C_CONST
+AC_TYPE_OFF_T
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+AC_STRUCT_TM
+
+dnl --- This should be in the stdc checking -----------------
+if test "$ac_cv_prog_cc_stdc" = '-Xc'; then
+dnl The Pyramids running SMP_DC.OSx on MIPS r3000 chips with
+dnl /usr/opt/cc3.11/bin/cc treat -Xc as full ANSI mode - no POSIX or
+dnl XOPEN extensions (like popen).
+dnl Unfortunately -D_{XOPEN,POSIX}_SOURCE can't provide all that mg
+dnl needs. So drop back to -Xa
+AC_TRY_COMPILE(
+[#include <stdio.h>
+], [ FILE *rubbish = popen("yes", "r"); ],,
+[CC="`echo $CC | sed 's/-Xc/-Xa/'`"    ac_cv_prog_cc_stdc='-Xa'])
+fi
+dnl ----------------------
+
+
+dnl Checks for libraries.
+dnl Replace `main' with a function in -lm:
+AC_CHECK_LIB(m, main)
+
+dnl Checks for header files.
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h limits.h sys/time.h unistd.h string.h memory.h sys/procfs.h)
+AC_EGREP_HEADER(fread, stdio.h, AC_DEFINE(HAVE_FREAD_DECL))
+AC_EGREP_HEADER(fgetc, stdio.h, AC_DEFINE(HAVE_FGETC_DECL))
+AC_EGREP_HEADER(pr_brksize, sys/procfs.h, AC_DEFINE(HAVE_PR_BRKSIZE))
+
+dnl Checks for library functions.
+AC_FUNC_ALLOCA
+AC_PROG_GCC_TRADITIONAL
+AC_TYPE_SIGNAL
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS(ftime select strftime strtol getrusage times mallinfo setbuffer getpagesize)
+AC_REPLACE_FUNCS(ftruncate strstr strcasecmp)
+
+
+# *** Custom checking (based on GNU tar configure.in) ***
+# ---------------------------------------------------------------------------
+AC_MSG_CHECKING(for HP-UX needing gmalloc)
+if test "`(uname -s) 2> /dev/null`" = 'HP-UX'; then
+  AC_MSG_RESULT(yes)
+  AC_LIBOBJ(gmalloc)
+  AC_DEFINE(HAVE_VALLOC)
+else
+  AC_MSG_RESULT(no)
+  AC_CHECK_FUNCS(valloc)
+fi
+
+# we need to set an extended JNI path for Mac OS/Darwin, as jni.h is on
+# a non-standard Path
+# is there a better way to do this??
+AC_MSG_CHECKING(for OS to set JNI options)
+# set defaults
+JNIINC=""
+JNISUFFIX="so"
+JNIFLAGS="-shared"
+
+if test "`(uname -s) 2> /dev/null`" = 'Darwin'; then
+  AC_MSG_RESULT(Darwin)
+  JNIINC="-I/System/Library/Frameworks/JavaVM.framework/Headers/ "
+  JNISUFFIX="jnilib"
+  JNIFLAGS="-dynamiclib -fno-common -single_module -framework JavaVM"
+fi
+if test "`(uname -s) 2> /dev/null`" = 'SunOS'; then
+  AC_MSG_RESULT(Solaris)
+  JNIINC="-I\$(JAVA_HOME)/include/solaris "
+fi
+if test "`(uname -s) 2> /dev/null`" = 'Linux'; then
+  AC_MSG_RESULT(Linux)
+  JNIINC="-I\$(JAVA_HOME)/include/linux "
+fi
+
+AC_SUBST(JNIINC)
+AC_SUBST(JNISUFFIX)
+AC_SUBST(JNIFLAGS)
+
+fp_WITH_DMALLOC
+fp_WITH_REGEX
+
+# text for endianness
+AC_C_BIGENDIAN
+
+# ---------------------------------------------------------------------------
+if test "$ac_cv_func_alloca" = 'no'; then
+dnl    support functions for alloca.c
+  AC_LIBOBJ(xmalloc)
+  AC_LIBOBJ(error)
+fi
+
+
+# ---------------------------------------------------------------------------
+
+AC_OUTPUT([Makefile src/text/Makefile src/images/Makefile 
+          src/scripts/Makefile lib/Makefile
+	  jni/Makefile java/org/greenstone/mg/Makefile ], 
+[test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h])
Index: /indexers/branches/3.03a/mg/docs/Makefile
===================================================================
--- /indexers/branches/3.03a/mg/docs/Makefile	(revision 14757)
+++ /indexers/branches/3.03a/mg/docs/Makefile	(revision 14757)
@@ -0,0 +1,5 @@
+DISTFILES = Makefile mgmerge.README mg_invf_dump.changes \
+  README.man mg.1 mgintro.1 mgintro++.1
+
+dist:
+	ln $(DISTFILES) $(distdir)
Index: /indexers/branches/3.03a/mg/docs/README.man
===================================================================
--- /indexers/branches/3.03a/mg/docs/README.man	(revision 14757)
+++ /indexers/branches/3.03a/mg/docs/README.man	(revision 14757)
@@ -0,0 +1,1 @@
+The rest of the man files are in the respective src directories.
Index: /indexers/branches/3.03a/mg/docs/mg.1
===================================================================
--- /indexers/branches/3.03a/mg/docs/mg.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/docs/mg.1	(revision 14757)
@@ -0,0 +1,462 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg 1 \*(Dt CITRI
+.\"=====================================================================
+.\" Author:
+.\"     Nelson H. F. Beebe
+.\"     Center for Scientific Computing
+.\"     Department of Mathematics
+.\"     University of Utah
+.\"     Salt Lake City, UT 84112
+.\"     USA
+.\"     Email: beebe@math.utah.edu (Internet)
+.\"=====================================================================
+.if t .ds Bi B\s-2IB\s+2T\\h'-0.1667m'\\v'0.20v'E\\v'-0.20v'\\h'-0.125m'X
+.if n .ds Bi BibTeX
+.if t .ds Te T\\h'-0.1667m'\\v'0.20v'E\\v'-0.20v'\\h'-0.125m'X
+.if n .ds Te TeX
+.\"=====================================================================
+.SH NAME
+mg \- full-text inverted index support
+.\"=====================================================================
+.SH DESCRIPTION
+.B mg
+is a suite of programs that can be used to create
+and query full-text inverted indexes for a
+collection of documents.
+.PP
+An inverted index is essentially a list of
+pointers to occurrences of every word in a
+collection of documents, so that, for example, in
+a collection of Shakespeare's works, one can pose
+questions like
+.I "How often is a fool mentioned in the plays?"
+and
+.I "Are Romeo and Juliet ever mentioned in the same sentence?"
+While search utilities like the UNIX
+.BR grep (1)
+family can be used for simple queries, they suffer
+from several limitations:
+.TP \w'\(bu'u+2n
+\(bu
+Each invocation requires a separate pass over the
+documents, which becomes impossibly slow if the
+document collection is very large.
+.TP
+\(bu
+It is difficult to compose Boolean queries like
+.IR "Caesar AND Brutus AND NOT Antony" .
+.TP
+\(bu
+They provide no mechanism for ranking matches
+according to importance, which is extremely
+important when queries are complex and numerous
+matches are found.
+.TP
+\(bu
+They provide no mechanism for displaying
+surrounding context (although the Free Software
+Foundation
+implementations for the GNU Project remedy this
+with their
+.BI \-A " num"
+(after)
+and
+.BI \-B " num"
+(before)
+switches).
+.TP
+\(bu
+They provide no mechanism for searching for
+occurrences in the same paragraph, unless
+preprocessing is done on the files to wrap
+paragraphs into long lines.  Even that will often
+fail, because input buffer sizes may be limited to
+a few hundred characters.
+.TP
+\(bu
+They provide no easy way to deal with grammatical
+word-ending variants, except by explicit
+enumeration, such as searching for
+.IR compress ,
+.IR compressed ,
+.IR compresses ,
+.IR compressing ,
+and
+.IR compression .
+.PP
+Most computer users have been faced with the
+problem of finding information from a large
+collection of files, such as electronic mail,
+on-line documentation, or source code.  Inverted
+indices provide a highly-effective solution to
+this problem.
+.PP
+The
+.B mg
+software is described in Appendix A of the book
+.RS
+.nf
+Ian H. Witten, Alistair Moffat, and Timothy C. Bell
+.I "Managing Gigabytes: Compressing and Indexing Documents and Images"
+Van Nostrand Reinhold
+1994
+xiv + 429 pages
+US$54.95
+ISBN 0-442-01863-0
+Library of Congress catalog number TA1637 .W58 1994
+.fi
+.RE
+.PP
+Many of the algorithms implemented in
+.B mg
+represent significant advances over previous work,
+both in speed, and in storage requirements.  On a
+fast workstation, in tens of minutes, or a few
+hours,
+.BR mgbuild (1)
+can create an index to
+.I all
+of the words in hundreds of thousands of documents
+occupying hundreds of megabytes, or even more than
+a gigabyte, of disk space.
+.BR mgquery (1)
+can then be used to answer complex queries, with
+responses often returned in a second or less.
+.B mg
+also contains algorithms to deal with images, so
+that with a small amount of descriptive text for
+each image, it is possible to do searches in
+collections of images, and to have retrievals
+display the images using a viewer like
+.BR xv (1).
+.PP
+.B mg
+can deal with compressed text and image files and
+surprisingly, it usually runs faster than it would
+if the files were not compressed!  Thus, the
+considerable disk space savings possible from
+file compression are not lost because of the need
+for fast document search and retrieval.
+.PP
+The Free Software Foundation GNU Project
+compression utilities
+.BR gzip (1)
+and
+.BR gunzip (1)
+are recommended for general use over older
+alternatives, like
+.BR compress (1),
+because of their speed and high compression
+ratios.
+.\"=====================================================================
+.SH AVAILABILITY
+The
+.B mg
+software can be obtained via anonymous ftp to the
+Australian archive host
+.I "munnari.oz.au [128.250.1.21]"
+from the directory
+.IR "/pub/mg" .
+.\"=====================================================================
+.SH "TYPICAL USE OF mg"
+Although
+.B mg
+consists of more than 20 separate programs, many
+of which have complicated command-line options,
+take heart: most users require only two or three
+of these programs, and nothing more than a
+document name on the command line.
+.PP
+A
+.I document
+for
+.B mg
+is a fragment of text suitable for retrieval as a
+unit when it is found to contain a requested word,
+or words.  In a collection of poetry, a document
+might be a stanza, while in a novel, it could be a
+paragraph.  In an index of first lines of poems, a
+document would likely be just a single line.
+.PP
+Just what constitutes a document is decided by a
+user-modifiable UNIX shell script,
+.BR mg_get (1).
+The default script provided with the
+.B mg
+source distribution knows about these named
+document collections:
+.TP \w'mailfiles'u+2n
+.I alice
+Lewis Carroll's
+.I "Alice in Wonderland"
+book.
+.TP
+.I allfiles
+all mail files in the directory tree
+.IR $HOME/Mail ,
+including all of its nested subdirectories.
+.TP
+.I mailfiles
+individual mail messages in
+.IR $HOME/mbox
+and
+.IR $HOME/.sentmail.
+.TP
+.I davinci
+A small collection of text and images from the
+work of Leonardo da Vinci.
+.PP
+A document collection name is used by
+.B mg
+as a
+.BR csh (1)
+.I case
+statement selector, and as a subdirectory name in the
+.B $MGDATA
+directory, or the current directory, if
+.B MGDATA
+is not defined.
+.\"=====================================================================
+.SH "EXTENDING mg_get"
+This section describes how to extend
+.BR mg_get (1)
+to handle a new document collection.
+.PP
+Let us take two examples: all \*(Bi
+.I .bib
+files, and all \*(Te files, contained in
+subdirectories under the login directory.
+.PP
+For \*(Bi, each bibliographic entry will be
+considered a separate document.  In order to
+facilitate easy identification of entries, we
+shall require them to begin at the start of a
+line; the
+.BR bibclean (1)
+utility can be used to standardize the format of
+.I .bib
+files, and to validate their string values, so
+that this requirement is met.
+.PP
+For \*(Te, each paragraph will be a separate
+document, and we assume that paragraphs are
+separated by blank lines.  We assume that files
+with extensions
+.IR .atx ,
+.IR .ltx ,
+.IR .stx ,
+and
+.I .tex
+contain input to common \*(Te macro package
+variants.
+.PP
+Make a personal copy of the
+.I mg_get
+script, using the one in the
+.B mg
+source distribution
+.RI ( mg-1.0/mg/mg_get.sh ),
+or the one in the local binary program directory,
+at many sites called
+.IR /usr/local/bin/mg_get .
+.PP
+Examination of the
+.I mg_get
+script shows that each document collection name is
+used in a
+.BR csh (1)
+.I case
+statement selector, and that most of work is done
+by very simple
+.BR awk (1)
+programs that extract documents from files.  In
+your private copy of the
+.I mg_get
+file, after the line
+.PP
+.nf
+  breaksw #davinci
+.fi
+.PP
+and before the line
+.PP
+.nf
+  default:
+.fi
+.PP
+insert this new code:
+.PP
+.nf
+  case bibfiles:
+# Takes a list of files that contain BibTeX entries, and splits them up
+#   by putting ^B after each entry. Assumes that each entry
+#   begins with a line '^@'.
+  switch ($flag)
+    case '-init':
+    breaksw
+
+    case '-text':
+      find $HOME -name '*.bib' -print | \e
+        sort | \e
+        xargs -l100 awk \e
+          '/^@/&&NR!=1{print "^B"} {print $0} END{print "^B"}'
+    breaksw #-text
+
+    case '-cleanup':
+    breaksw #-cleanup
+
+  endsw #flag
+  breaksw #bibfiles
+
+  case texfiles:
+# Takes a list of TeX files and split them up
+#   by putting ^B after each paragraph. Assumes that each entry
+#   begins with a line '^@'.
+  switch ($flag)
+    case '-init':
+    breaksw
+
+    case '-text':
+      find $HOME -name '*x' -print | \e
+        egrep '[.]tex$|[.]ltx$|[.]atx$|[.]stx$' | \e
+        sort | \e
+        xargs -l100 nawk '   /^ *$/ {if (b!=1) printf "^B";b=1} \e
+            \e!/^ *$/ {print;b=0} \e
+            END {printf "^B"}'
+    breaksw #-text
+
+    case '-cleanup':
+    breaksw #-cleanup
+
+  endsw #flag
+  breaksw #texfiles
+.fi
+.PP
+The ^B characters here are Control-B characters,
+.I not
+caret-B pairs.
+.PP
+If you have a large number of \*(Bi or \*(Te
+files, it is likely that a list of them would be
+too long for the UNIX shell to hold in a single
+variable, or on a single command line.  Thus,
+instead of storing the output of
+.BR find (1)
+in a variable, we proceed more cautiously, and
+employ it to produce a list of the required files,
+then pipe them to
+.BR xargs (1),
+which in turn passes up to 100 filenames at a time
+to
+.BR nawk (1)
+for document selection.
+.PP
+Install this modified
+.I mg_get
+script in your private directory for executable
+programs (e.g.
+.IR $HOME/bin ),
+create a directory
+.I $HOME/mgdata
+to hold the index, issue a
+.B rehash
+command if you are using
+.BR csh (1)
+or
+.BR tcsh (1),
+ensure that
+.I mg_get
+occurs in your search path
+.I before
+any system-wide one (the command
+.BI which " mg_get"
+will tell you which version will be selected),
+then create the inverted indexes by
+.BI mgbuild " bibfiles"
+and
+.B mgbuild
+.IR texfiles .
+These commands may take several minutes to run if
+you have a lot of \*(Bi or \*(Te files, or a large
+home directory tree.  Once they are complete, you
+can then query the index with the commands
+.BI mgquery " bibfiles"
+and
+.B mgquery
+.IR texfiles .
+These should respond very rapidly.
+.PP
+In order to keep your index up-to-date, you should
+arrange for it to be recreated automatically and
+regularly, probably every night.  You can do this
+with
+.BR cron (1).
+Use the command
+.B "crontab \-e"
+to edit your
+.I crontab
+file and add two lines like this:
+.PP
+.nf
+00 04 * * * mgbuild bibfiles >$HOME/mgdata/bibfiles.log 2>&1
+15 04 * * * mgbuild texfiles >$HOME/mgdata/texfiles.log 2>&1
+.fi
+.PP
+Save the file and exit the editor.  Now, every
+night at 4am and 4:15am,
+.BR mgbuild (1)
+will reconstruct your inverted indexes, and the
+results of the builds will be saved in log files
+in your
+.I $HOME/mgdata
+directory.
+.\"=====================================================================
+.SH "SEE ALSO"
+.na
+.BR awk (1),
+.BR bibclean (1),
+.BR bibtex (1),
+.BR compress (1),
+.BR csh (1),
+.BR grep (1),
+.BR gunzip (1),
+.BR gzip (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1),
+.BR nawk (1),
+.BR tcsh (1),
+.BR tex (1),
+.BR xargs (1),
+.BR xmg (1),
+.BR xv (1).
+.\"=====================================================================
+.\" This is for GNU Emacs file-specific customization:
+.\" Local Variables:
+.\" fill-column: 50
+.\" End:
Index: /indexers/branches/3.03a/mg/docs/mgintro++.1
===================================================================
--- /indexers/branches/3.03a/mg/docs/mgintro++.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/docs/mgintro++.1	(revision 14757)
@@ -0,0 +1,212 @@
+.\"------------------------------------------------------------  
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4 
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.ds r \&\s-1MG\s0
+.if n .ds - \%--
+.if t .ds - \(em
+.\"------------------------------------------------------------  
+.am SS
+.LP
+..
+.\"------------------------------------------------------------
+.TH MGINTRO++ 1 \*(Dt CITRI
+.\"--------------------------------------------------------------
+.SH NAME
+mgintro++ \- extended introduction to the MG system
+.\"-------------------------------------------------------------
+.SH DESCRIPTION
+This manual assumes the reader has already read
+.BR mgintro (1).
+.\"-------------------------------------------------------------
+.SS Creating Different Databases
+If a user wants to build databases other than for some
+predefined ones, such as "alice", "davinci", "mailfiles", "allfiles",
+then the user has a couple of choices.
+Ultimately (s)he must produce a text file with control-Bs 
+terminating the documents. 
+To do this one can produce one or more such files, or write a
+"get" command (typically in the form of a script or c program).
+.\"-------------------------------------------------------------
+.SS Using Input Files for mgbuild
+If you don't want to write a "get" script and just want to use
+one or more text files as input, then you must first generate
+the file with control-Bs. For a simple example, you could take
+any text file(s) such as "test1.txt" and "test2.txt", and use 
+.BR vi (1)
+to insert control-Bs by typing "control-V b".
+Next you should create a file with "set" statements 
+in the following form:
+.PP
+.IP
+\fBset pipe = 0 # do not use pipe - use file instead 
+.br
+\fBset input_files = 'test1.txt test2.txt'
+.LP
+Let's call this file, "build_options".
+Now issue the command:
+.IP
+.B mgbuild -s build_options test
+.LP
+This should build a database called "test" in the $MGDATA directory,
+based on the source data of "test1.txt" and "test2.txt".
+The build_options file is simply sourced by 
+.BR mgbuild (1)
+after it has set up its variables. 
+Therefore, any settings one makes in the
+build_options file will override the standard settings.
+See 
+.BR mgbuild (1) 
+for more information.
+.\"-------------------------------------------------------------
+.SS Writing A Get Program
+Instead of using files as input, it is often more convenient to 
+write a "get" program. This program is called by 
+.BR mgbuild (1)
+to get the text data with control-Bs as document terminators.
+It should take three options:
+.br
+(i) -init; (ii) -text; (iii) -cleanup.
+.br
+Get will be called with "init" first and with "cleanup" at the end.
+It will call get with "text" when it wants the text and it should
+write the text to stdout.
+.br
+See 
+.BR mg_get (1)
+for an example.
+.\"-------------------------------------------------------------
+.SS Regular Builds
+The MG system provides a static database; 
+there are no update commands.
+So if one wants to keep one's database reasonably up-to-date
+then one can have this done automatically on a regular basis by 
+.BR cron (1).
+A crontab file can be created using:
+crontab -e
+A crontab file contains lines of the form:
+.nf
+.IP
+\fBminute hour day-of-month month day-of-week shell-command.
+.LP
+.fi
+See
+.BR crontab (1)
+for more information.
+.nf
+An example crontab entry is:
+.IP
+\fB15 02 * * * mgbuild allfiles >$MGDATA/allfiles/allfiles.log 2>&1
+.LP
+.fi
+This will build up the mg database for "allfiles", your mail in
+the folders, every morning at 2:15am. 
+.\"
+.\"-------------------------------------------------------------
+.SS Command Structure
+There are 22 commands that make up the mg system. However,
+a user may only need to be aware of a few: 
+.BR mgbuild (1),
+.BR mgquery (1), 
+and perhaps
+.BR mg_get (1). 
+Many of the commands are called by 
+.BR mgbuild(1).
+The commands can be broken up into a hierarchy.
+.PP
+--------------------------------------
+.br
+MG--+--image compression
+    |  |
+    |  +--mgbilevel
+    |  |
+    |  +--mgfelics
+    |  |
+    |  +--mgtic
+    |  |
+    |  +--mgticbuild
+    |  |
+    |  +--mgticdump
+    |  |
+    |  +--mgticprune
+    |  |
+    |  +--mgticstat
+    |
+    +--text 
+       |
+       +--compression
+       |  |
+       |  +--mg_passes -T1
+       |  |
+       |  +--mg_passes -T2
+       |  |
+       |  +--mg_compression_dict
+       |  |
+       |  +--mg_fast_comp_dict
+       |
+       +--indexing
+       |  |
+       |  +--mg_passes -N1
+       |  |
+       |  +--mg_passes -N2
+       |  |
+       |  +--mg_perf_hash_build
+       |  |
+       |  +--mg_invf_dict
+       |  |
+       |  +--mg_invf_rebuild
+       |  
+       +--weights
+       |  |
+       |  +--mg_weights_build
+       |
+       +--query
+       |  |
+       |  +--mgquery
+       |
+       +--tools
+          |
+          +--mg_invf_dump
+          |
+          +--mg_text_estimate
+          |
+          +--mgdictlist
+          |
+          +--mgstat
+.br
+--------------------------------------
+.PP
+.nf
+.BR mgbuild (1)
+calls the following commands:
+.RS
+.BR mg_passes (1), mg_compression_dict (1)
+.BR mg_perf_hash_build (1), mg_invf_dict (1), mg_invf_rebuild (1)
+.BR mg_weights_build (1)
+.RE
+.fi
+.\"--------------------------------------------
+.SH SEE ALSO
+.BR mgintro (1),
+.BR mgbuild (1),
+.BR mg_get (1)
+.br
+"Guide To The \*r System", in Appendix A of the book:
+.PP
+.RS
+.nf
+Ian H. Witten, Alistair Moffat, and Timothy C. Bell
+.I "Managing Gigabytes: Compressing and Indexing Documents and Images"
+Van Nostrand Reinhold
+1994
+xiv + 429 pages
+US$54.95 
+ISBN 0-442-01863-0
+Library of Congress catalog number TA1637 .W58 1994.
+.fi
+.RE
+
Index: /indexers/branches/3.03a/mg/docs/mgintro.1
===================================================================
--- /indexers/branches/3.03a/mg/docs/mgintro.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/docs/mgintro.1	(revision 14757)
@@ -0,0 +1,155 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.ds r \&\s-1MG\s0
+.if n .ds - \%--
+.if t .ds - \(em
+.\"------------------------------------------------------------
+.am SS
+.LP
+..
+.\"------------------------------------------------------------
+.TH MGINTRO 1 \*(Dt CITRI
+.\"--------------------------------------------------------------
+.SH NAME
+mgintro \- introduction to the MG system
+.\"--------------------------------------------------------------
+.SH DESCRIPTION
+The MG (Managing Gigabytes) system is a collection of
+programs which comprise a full-text retrieval system.
+A full-text retrieval system allows one to create a
+database out of some given documents and then do queries
+upon it to retrieve any relevant documents.
+It is "full-text" in the sense that every word in the
+text is indexed and the query operates only on this index 
+to do the searching.
+.PP
+For example, one could have a database on the book,
+"Alice in Wonderland." A document could be represented by
+each paragraph in the book.
+Having built up the "Alice" database, one could do queries
+such as "cat alice grin" and retrieve any paragraphs which
+match the query. The matching could either be boolean, that
+is the retrieved paragraphs contain a boolean expression of
+the query terms e.g. "cat alice grin"; or the matching
+could be ranked i.e. the most relevant documents to the query
+in relevance order, using some standard heuristic measure.
+.\"--------------------------------------------------------------
+.SS Motivation
+If one wants to find some particular information which
+is stored in a computer text file then one has a few alternative
+courses of action. One can operate directly on the text files
+with utilities such as grep or can process the text files into
+some form of database. Grep is generally limited to identifying
+lines by matching on regular expressions. If the collection 
+of files which grep operates on becomes large, then continual
+passes over the entire text on each query becomes expensive.
+However, its usage is simple as no auxiliary files must be created.
+.PP
+A database consists of some data and indexes into that data. By having
+indexes one can query a large database quickly. Standard databases
+divide the data up into records of fields. This means that the granularity
+of search is a field. In a full-text system, such as \*r,
+there are no fields 
+(or there is an arbitrary sized list of word fields per document) 
+and instead every word is indexed. 
+Using this method, we can except free-form information and yet be fast on searches.
+The next question is what is the overhead of this database.
+In \*r most files which are produced are in a compressed form. The
+two notable compressed files being the given data and the index, called
+an "inverted file". By compressing the files it is possible to have the
+size of the database smaller than the size of the source data.
+.\"--------------------------------------------------------------
+.SS Typical Usage
+The most common use for \*r
+has been as a search database on unix mail files.
+However, any set of text data can be used, one just needs to determine
+what constitutes a document (see 
+.BR mgintro++ (1)
+).
+\*r has also been used on large collections such
+as Comact (Commonwealth Acts of Australia) which is around 132 megabytes 
+and also on sizes up to around 2 gigabytes for TREC 
+(a mixture of collections such as the Wall Street Journal 
+and Associated Press).
+.\"--------------------------------------------------------------
+.SS Getting Started with \*r
+The first thing to do is install the package; 
+please follow the INSTALL instructions.
+Having done this, it is necessary to set a couple of environment variables.
+MGDATA should be set to a directory which is to hold subdirectories for
+each database that you build. For example: 
+.IP
+.B mkdir ~/mgdata; setenv MGDATA ~/mgdata.
+.LP
+If you want to try out building some sample databases then there is
+some sample data such as the "Alice In Wonderland" book. To make sure
+this is accessible you should set the environment variable MGSAMPLE.
+For example: 
+.IP
+.B setenv MGSAMPLE ~/mg/SampleData
+.LP
+Here, "~/mg/SampleData" should contain alice.z .
+.PP
+To build the Alice database (to be contained in $MGDATA/alice subdirectory), 
+type the command 
+.IP
+.B mgbuild alice 
+.LP
+Assuming all went well and some status messages 
+were printed indicating the build was completed, then type 
+.IP
+.B mgquery alice 
+.LP
+to query the database. 
+You can type a few words at the prompt, hit return and
+some relevant documents, Alice paragraphs, should be retrieved.
+Type ".set query ranked" to do ranking queries. Please refer to the 
+.BR mgquery (1)
+man-page for more information on the commands and options of 
+.BR mgquery (1).
+.PP
+The next thing to do is to use \*r
+on a more personal database. If you have
+your mail stored in subdirectories of ~/Mail, such as is done if you use the
+typical set up of 
+.BR elm (1), 
+then type 
+.IP
+.B mgbuild allfiles 
+.LP
+If, however, you keep all your mail in ~/mbox or ~/sentmail, then type 
+.IP
+.B mgbuild mailfiles
+.LP
+.\"--------------------------------------------------------------
+.SH AVAILABILITY
+The \*r software for SunOS 4, Solaris, HPUX, and MIPS,
+can be ftped from: munnari.oz.au [128.250.1.21] in the directory
+/pub/mg. 
+.\"--------------------------------------------------------------
+.SH SEE ALSO
+.na
+.BR mgintro++ (1),
+.BR mgbuild (1),
+.BR mgquery (1)
+.br
+"Guide To The \*r System", in Appendix A of the book:
+.PP
+.RS
+.nf
+Ian H. Witten, Alistair Moffat, and Timothy C. Bell
+.I "Managing Gigabytes: Compressing and Indexing Documents and Images"
+Van Nostrand Reinhold
+1994
+xiv + 429 pages
+US$54.95
+ISBN 0-442-01863-0
+Library of Congress catalog number TA1637 .W58 1994.
+.fi
+.RE
Index: /indexers/branches/3.03a/mg/docs/mgmerge.README
===================================================================
--- /indexers/branches/3.03a/mg/docs/mgmerge.README	(revision 14757)
+++ /indexers/branches/3.03a/mg/docs/mgmerge.README	(revision 14757)
@@ -0,0 +1,230 @@
+A CRASH COURSE GUIDE TO MGMERGE
+===============================
+
+Shane Hudson
+15 November 1994
+
+
+This document is intended as a note to the maintainers of mgmerge
+outlining the mgmerge utility, the changes
+that had to be made to the existing mg code to make mgmerge
+work, and the new source code for mgmerge.
+
+
+****  NOTE:    ****
+All the NEW/CHANGED files are in the file "new_mg.tar" which
+you should have received with this; files that were
+not changed are NOT in the tar file  so it will have to be
+extracted "on top of" the existing code. You'll figure it out :)
+
+
+****  DESCRIPTION:   ****
+mgmerge adds documents to an existing mg database
+without the need to rebuild the database from scratch.
+It works by building a temporary new database from the
+new documents, then merging the "old" and "new" databases
+to give one merged database.
+
+
+The source consists of:
+    mgmerge.sh		The main script, a lot like mgbuild.sh
+    mg_get_merge.sh	Script to retrieve new documents, a lot like
+			mg_get.sh
+    mg_merge.h		header file used by mg_invf_merge.c
+			and mg_text_merge.c
+    mg_text_merge.c	Program to append one compressed text file
+			to another
+    mg_invf_merge.c	Program to merge two inverted files and
+			stemmed dictionaries
+
+See the man pages for mgmerge, mg_get_merge, mg_text_merge and
+mg_invf_merge for a brief overview.
+
+mg_get_merge.sh should really be put into mg_get.sh, with a "-merge"
+option if it is being called by the mgmerge utility, but I was
+too lazy to change it to that.
+
+
+The files updated by mgmerge are:
+
+*.text			with mg_text_merge
+*.text.idx		with mg_text_merge
+*.text.idx.wgt		with mg_weights_build (after merging)
+*.invf			with mg_invf_merge
+*.invf.idx		with      "
+*.invf.dict		with      "
+*.weight		with mg_invf_merge or mg_weights_build
+*.invf.dict.blocked	with mg_invf_dict (after merging)
+
+The *.text.stats file and *.text.dict file remain the same.
+Any other database files (ie, *.invf.dict.hash)
+will be out of date after a merge and will need to be recomputed.
+
+--------------------------------------------------------------------------
+
+MG_TEXT_MERGE
+=============
+
+The two "merging" utilities are mg_text_merge and mg_invf_merge
+
+mg_text_merge simply appends the compressed text for the new
+documents to the old compressed text file.
+For this to succeed, the two files should have been created
+with the same parameters to mg_passes and the same compression
+model must be used. So *.text.dict from the old (static) database
+is used as the model for compressing the new documents.
+The default "-C" option to mg_compression_dict in mgbuild was
+changed to "-S" so novel words in the new documents can be coded.
+The option must be the same in mgmerge -- it is "-S" there too.
+
+---------------
+
+EFFECT on FILE COMPRESSION PERFORMANCE
+
+Since the compression model is not being updated,compression
+performance for the text will slowly degrade. The only solution
+is a periodic rebuild from scratch.
+
+---------------------------------------------------------------------------
+
+MG_INVF_MERGE
+=============
+
+mg_invf_merge updates the stemmed dictionary and
+inverted file.
+For reasons of simplicity, the stemmed dictionaries merged
+are in the ".invf.dict" format, NOT the ".invf.dict.blocked"
+format. 
+So if a database is to be merged the .invf.dict file should
+not be deleted after the .invf.dict.blocked file used by mgquery
+has been created.
+Also for simplicity, level 3 inverted files are not supported, nor
+are skipped format files.
+
+
+
+Merging the inverted files requires every entry in each file
+to be decoded and merged if an entry for the same term appears
+in the other inverted file.
+This can be a slow process if the old inverted file is very large.
+Especially since each entry is decoded bit-by-bit with
+the bit-level I/O rouutines.
+As was noted on page 94 of the book "Managing Gigabytes" (hereafter 
+called "MG"), switching from bernoulli coding (called "Bblock" in
+the mg source code) to gamma or delta coding for the
+inter-document gaps would be an advantage since they require no
+parameters.
+With Bblock coding, N (the number of documents) is a parameter and
+as N changes whenever documents are added, every entry must
+be decoded and recoded.
+My approach was to keep Bblock coding, but keep the N parameter
+constant by recording the artificial N  used to code document
+gaps (called "Nstatic") as well as the real number of documents.
+
+Then, any entry in the old inverted file (called "IFold") that
+is not merged with an entry in the new inverted file (called "IFnew")
+can be copied directly to the merged inverted file (called "IFmerge").
+This can give a significant increase in speed, since usually the
+size of IFnew is very small if only a few documents are being added.
+
+To store Nstatic, a field "static_num_of_docs" was added to
+the invf_dict_header and stem_dict_header structs defined
+in invf.h
+Any program that decodes inverted file entries also had to be changed.
+(The existing mg source code that I changed has been returned with
+this document.)
+Most changes were simply altering a line that
+called BIO_Bblock_Init() so it used the static_num_of_docs
+value rather than num_of_docs.
+
+So since the file format has changed, any existing collection will
+have to be rebuilt first even using mgmerge with it is not
+intended.
+
+-------------
+
+EFFECT on INVERTED FILE COMPRESSION PERFORMANCE
+
+As more merges are accumulatively performed on a database, the
+compression performance will decline.
+The solution is an option in mg_invf_merge to do a "slow"
+merge where every inverted file entry is decoded and recoded using
+the real value of N.
+This is not a lot slower than a fast merge when compared to the
+cost of completely rebuilding the collection from scratch, and 
+the option can be used periodically (when, say, 40% of the
+inverted file has been added since the previous slow merge).
+
+-----------------
+
+THE EXACT WEIGHTS FILE
+
+Recomputing exact document weights requires a complete scan over the
+merged inverted file. This is a waste since the weights for old
+documents will (hopefully) not change much anyway, and the weights
+for new documents can be computed exactly when merging the inverted files,
+at no extra time cost.
+So mg_invf_merge computes the weights for new documents and
+updates the .weight file.
+The weights for old documents are left untouched.
+mgmerge has an option to recompute the weights file.
+This is not much more expensive in terms of time, and is only
+periodically needed.
+
+The effect of leaving the old weights unchanged is difficult to
+asess since the "correct" ranking of documents for a query is
+subjective.
+The frequency with which a rebuild of the weights file with the
+"-w" option should be done is hard to guess.
+But if most merges involves only a few documents, it makes sense
+to not bother recomputing it since the change in old weights values
+is very small and the weights only stray from their "true"
+values slowly over accumulated merging.
+
+-------------------------------------------------------------------------
+
+EXPERIMENTAL RESULTS
+====================
+
+With some small test collections (only a few Mb of text)
+and a slow merge, and a weights file rebuild,
+mgmerge typically took under 20% of the time to completely
+rebuild. Using the default options (fast merge, dont rebuild weights)
+took around 10% or more.
+For larger collections, the savings were greater, especially if the
+added text is very small.
+For example, when the last 6Kb of text of the GNUBib collection was
+added to the rest of it (14Mb) using mgmerge, the total mgmerge time
+was around 20 seconds whereas a complete mgbuild took 280 seconds.
+Only one larger collection was tested (resource contraints prevented
+testing on any really large collections): two short (one-line)
+documents were added to the Gutenberg collection, which comprised
+of nearly 74Mb of source text and had an inverted file size of 9Mb.
+mgmerge took 42 seconds (or 142 seconds with a slow merge and rebuilding the
+weights file), and I'd estimate that an mgbuild on the same machine would 
+have taken at least 20 minutes.
+
+To summarise, mgmerge is not as fast as some sophisticated method
+such as the fixed-length blocks described in section 5.7 of "MG",
+but its huge advantage is that it required almost no changes to
+the existing mg code and is still far better than using mgbuild
+every time a document needs to be added to a collection.
+
+----------------------------------------------------------------------------
+
+OTHER NOTES
+===========
+
+Since it works like mgbuild, mgmerge needs mg_get_merge
+to return the SAME text each time "mg_get_merge -text .." is called.
+
+----
+
+One other thing discovered (but not fixed) was a bug in "invf.pass2.c":
+It crashes on parsed words longer than 128 characters.
+So if any text with words >128 chars is piped to mg_passes,
+the "-N1" and "-N2" options (the memory-efficient inversion method)
+had better be used and not the "-I1"/"-I2" option (which would only
+work on small collections anyway, being the memory-inefficient
+method).
+
Index: /indexers/branches/3.03a/mg/install-sh
===================================================================
--- /indexers/branches/3.03a/mg/install-sh	(revision 14757)
+++ /indexers/branches/3.03a/mg/install-sh	(revision 14757)
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
Index: /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGDocInfo.java
===================================================================
--- /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGDocInfo.java	(revision 14757)
+++ /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGDocInfo.java	(revision 14757)
@@ -0,0 +1,42 @@
+/*
+ *    MGDocInfo.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.mg;
+
+
+/** DocInfo 'struct' class for a search result from mg
+ *  used by MGQueryResult
+ *
+ * @See MGQueryResult
+ */
+public class MGDocInfo
+{
+    public long num_ = 0;
+    public float rank_ = 0;
+
+    public MGDocInfo(long doc, float rank)
+    {
+	num_ = doc;
+	rank_ = rank;
+    }
+
+    public String toString()
+    {
+	return "" + num_ + " (" + rank_ + ")";
+    }
+}
Index: /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGEquivTermInfo.java
===================================================================
--- /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGEquivTermInfo.java	(revision 14757)
+++ /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGEquivTermInfo.java	(revision 14757)
@@ -0,0 +1,53 @@
+/*
+ *    MGEquivTermInfo.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.mg;
+
+
+/** EquivTermInfo 'struct' class for a search result from mg
+ *  used by MGQueryResult
+ *
+ * @see MGQueryResult
+ */
+public class MGEquivTermInfo
+{
+    /** the term itself */
+    public String term_ = null;
+
+    /** the number of documents containing this term */
+    public long match_docs_ = 0;
+
+    /** overall term freq - word level */
+    public long term_freq_ = 0;
+
+
+    public MGEquivTermInfo(String term, long match, long freq)
+    {
+	term_ = term;
+	match_docs_ = match;
+	term_freq_ = freq;
+    }
+
+
+    public String toString()
+    {
+	String result = "\"" + term_ + "\"";
+	result += " (" + match_docs_ + "/" + term_freq_ + ")";
+	return result;
+    }
+}
Index: /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGPassesWrapper.java
===================================================================
--- /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGPassesWrapper.java	(revision 14757)
+++ /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGPassesWrapper.java	(revision 14757)
@@ -0,0 +1,154 @@
+/*
+ *    MGPassesWrapper.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.mg;
+
+
+/** java wrapper class for access to gs3_mg_passes in C
+ *
+ * the native side implemented in MGPassesWrapperImpl.c
+ */
+
+public class MGPassesWrapper
+{
+    static {
+	System.loadLibrary("mgpassjni");
+	initIDs();
+    }
+    
+    static final public char INVF_LEVEL_1 = '1';
+    static final public char INVF_LEVEL_2 = '2';
+    static final public char INVF_LEVEL_3 = '3';
+    
+    static final public int TEXT_PASS_1 = 0;
+    static final public int TEXT_PASS_2 = 1;
+    static final public int INDEX_PASS_1 = 2;
+    static final public int INDEX_PASS_2 = 3;
+    static final public int SPECIAL_PASS = 4;
+
+    static final public int NO_STEM_OR_CASE = 0;
+    static final public int CASE_ONLY = 1;
+    static final public int STEM_ONLY = 2;
+    static final public int STEM_AND_CASE = 3;
+
+    static final public String STEMMER_ENGLISH = "english";
+    static final public String STEMMER_FRENCH = "french";
+    static final public String STEMMER_LOVIN = "lovin";
+    static final public String STEMMER_SIMPLE_FRENCH = "simple-french";
+
+    static final private char END_OF_DOCUMENT = (char) 2;
+
+    public MGPassesWrapper() {
+	initCSide();
+    }
+
+    /** initialise the pass through the documents */
+    public native boolean init();
+    
+    /** add a pass declaration */
+    public void addPass(int pass) {
+	switch (pass) {
+	case TEXT_PASS_1:
+	    addPass('T','1');
+	    break;
+	case TEXT_PASS_2:
+	    addPass('T','2');	    
+	    break;
+	case INDEX_PASS_1:
+	    addPass('I','1');
+	    break;
+	case INDEX_PASS_2:
+	    addPass('I','2');
+	    break;
+	case SPECIAL_PASS:
+	    addPass('S','1');
+	    break;
+	}
+    }
+    /** set the base path */
+    public native void setBasePath(String basepath);
+   /** set the file name */
+    public native void setFileName(String filename);
+
+    public native void setStemOptions(String stemmer_type, int stem_method);
+
+    public native void setInvfLevel(char level);
+
+    /** Specify  the size of the document buffer in kilobytes.
+	If any document is larger than  bufsize,  the  program
+	will  abort with an error message. 
+     */
+    public native void setBufferSize(long bufsize);
+    
+    /** Maximum amount of memory to use for  the index  pass-2  file
+	inversion  in  megabytes.
+    */
+    public native void setInversionMemLimit(int limit);
+
+    /** If true, treat   SGML  tags  as  non-words  when  building  the
+	inverted file.
+    */
+    public native void ignoreSGMLTags(boolean ignore);
+    
+    /** if mg_passes fails, the document that caused teh failure will be
+	output to teh trace file or STDERR. 
+    */
+    public native void dumpFailedDocument(boolean dump);
+    
+    /** output statistics on the compression performance to  a  file  
+	called  *.compression.stats.    frequency  specifies  the  interval
+	(in kilobytes of source text) between outputting each line of 
+	statistics. 
+    */
+    public native void outputCompStats(int frequency);
+
+    /** activate tracing, a line will be output every tracepos input bytes */
+    public native void enableTracing(int tracepos);
+    /** process a Greenstone document, which may consist of many MG documents (seeparated by ^B */
+    public boolean processDocument(String docs_text) {
+	// need -1 in the following to keep empty strings at the end
+	String [] docs = docs_text.split(String.valueOf(END_OF_DOCUMENT), -1);
+	System.err.println("GS document split into "+docs.length+" mg documents");
+	for (int i=0; i<docs.length; i++) {
+	    try {
+		processMGDocument(docs[i].getBytes("UTF-8"));
+	    } catch (Exception e) {
+		e.printStackTrace();
+	    }
+	}
+	return true;
+    }
+   
+    /** finalise the pass through the documents */
+    public native boolean finish();
+
+    /** get the exit value once finished */
+    public native int exitValue();
+ 
+    /** initialises field and method IDs for java side to enable access on C side */
+    private static native void initIDs();
+
+    /** initialises any C side stuff */
+    private native boolean initCSide();
+
+    private native void addPass(char pass_type, char pass_num);
+
+    /** process a MG document */
+    private native boolean processMGDocument(byte[] text);
+
+}
Index: /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGQueryResult.java
===================================================================
--- /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGQueryResult.java	(revision 14757)
+++ /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGQueryResult.java	(revision 14757)
@@ -0,0 +1,155 @@
+/*
+ *    MGQueryResult.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.mg;
+
+
+import java.util.Vector;
+
+
+/** a java version of QueryResult for mg
+ *
+ * contains get methods for the java side, and simple
+ * set methods to be called from c side
+ *
+ */
+public class MGQueryResult
+{
+    /** the list of MGDocInfo */
+    protected Vector docs_ = null;
+    /** the list of MGTermInfo */
+    protected Vector terms_ = null;
+    /** the total number of docs found - not likely to be the size of docs_ */
+    protected long total_num_docs_ = 0;
+
+
+    MGQueryResult() {
+	docs_ = new Vector();
+	terms_ = new Vector();
+    }
+
+
+    /** clear the info from the last query
+	should be called before setting any new docs/terms */
+    public void clear() {
+	total_num_docs_ = 0;
+	docs_.clear();
+	terms_.clear();
+    }
+
+    public boolean isClear() {
+	return (total_num_docs_ == 0 && docs_.isEmpty() && terms_.isEmpty());
+    }
+
+    /** returns the result as a String - useful for printing out results */
+    public String toString()
+    {
+	String result = "";
+	result += "docs (ranks): ";
+	for (int i = 0; i < docs_.size(); i++) {
+	    if (i > 0) result += ", ";
+	    result += ((MGDocInfo) docs_.elementAt(i)).toString();
+	}
+	result += "\nterms: ";
+	for (int i = 0; i < terms_.size(); i++) {
+	    if (i > 0) result += ", ";
+	    result += ((MGTermInfo) terms_.elementAt(i)).toString();
+	}
+	result += "\nactual number of docs found = " + total_num_docs_;
+	return result;
+    }
+
+
+    /** a shorter representation - just terms and total docs - not the 
+	individual docnums and ranks */
+    public String toShortString() {
+	String result = "";
+	result += "\nterms: ";
+	for (int i = 0; i < terms_.size(); i++) {
+	    if (i > 0) result += ", ";
+	    result += ((MGTermInfo) terms_.elementAt(i)).toString();
+	}
+	result += "\nactual number of docs found = "+total_num_docs_;
+	return result;
+    }
+
+
+    // set methods used by c++ code
+
+    public void setTotalDocs(long num) {
+	total_num_docs_=num;
+    }
+
+
+    public void addDoc(long doc, float rank) {
+	MGDocInfo doc_info = new MGDocInfo(doc, rank);
+	///ystem.out.println("(Java) Added doc " + doc_info);
+
+	docs_.add(doc_info);
+    }
+
+
+    public void addTerm(String term, int stem)
+    {
+	MGTermInfo ti = new MGTermInfo();
+	ti.term_ = term;
+	ti.stem_method_ = stem;
+	terms_.add(ti);
+	///ystem.out.println("(Java) Added term " + ti);
+    }
+
+
+    public void addEquivTerm(String term, String equivTerm,
+			     long match, long freq)
+    {
+	// Find the term to add the equivalent to
+	MGTermInfo ti = null;
+	for (int i = (terms_.size() - 1); i >= 0; i--) {
+	    ti = (MGTermInfo) terms_.elementAt(i);
+	    // Found
+	    if (ti.term_ == term) {
+		break;
+	    }
+	}
+
+	if (ti == null) {
+	    System.err.println("Internal error: No term exists to add to.\n");
+	}
+	else {
+	    ti.addEquivTerm(equivTerm, match, freq);
+	    ///ystem.out.println("(Java) Added equivalent term " + equivTerm + ", match: " + match + ", freq: " + freq);
+	}
+    }
+
+
+    // Get methods for the java side - GS2MGSearch.java, GS2MGRetrieve.java
+    public Vector getDocs() {
+	return docs_;
+    }
+
+
+    public Vector getTerms() {
+	return terms_;
+    }
+
+
+    public long getTotalDocs() {
+	return total_num_docs_;
+    }
+}
+
Index: /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGRetrieveWrapper.java
===================================================================
--- /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGRetrieveWrapper.java	(revision 14757)
+++ /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGRetrieveWrapper.java	(revision 14757)
@@ -0,0 +1,102 @@
+/*
+ *    MGRetrieveWrapper.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.mg;
+
+
+/** java wrapper class for access to mg in C
+ *
+ * the native side implemented in MGWrapperImpl.c
+ * uses MGQueryResult to hold the result of a query.
+ * the result of a getDocument is a String
+ * uses the jni
+ *
+ *@see MGQueryResult
+ */
+public class MGRetrieveWrapper {
+    /** the query result, filled in by runQuery */
+//    protected MGQueryResult mg_query_result_ = null;
+    
+    /** pointer to c MGWrapperData class - cached indexData and queryInfo */
+    protected long mg_data_ptr_ = 0;
+    
+    static {
+        System.loadLibrary ("mgretrievejni"); 
+        initIDs ();
+    }
+    
+    public MGRetrieveWrapper () { System.out.println("in MGRetrieveWrapper.java");
+//        mg_query_result_ = new MGQueryResult ();
+        initCSide ();
+    }
+    
+    /** initialises field and method IDs for java side to enable access on C side */
+        private static native void initIDs ();
+    
+    /** initialises the mg_data_ptr_ */
+    private native boolean initCSide ();
+
+    /** unloads the data */
+    public native boolean unloadIndexData ();
+    
+    /** sets the index to search - default is 'dtx' */
+    public native void setIndex (String index);
+
+    /** returns a document: number docnum at level level
+     * the base_dir and text_path paths should join together to provide
+     * the absolute location of the mg text files eg ..../index/text/demo
+     * returns the doc in utf-8
+     */
+    public native String getDocument (String base_dir, String text_dir, long docnum);
+    
+    
+//    the following is for search service // query param methods
+//    
+//    /** if on=true, sets default casefolding on - it's off by default */
+//    public native void setCase (boolean on);
+//    /** if on=true, sets default stemming on - it's off by default */
+//    public native void setStem (boolean on);
+//    /** default is 50 */
+//    public native void setMaxDocs (int num);
+//    /** if on=true, a query returns term freq info - default is on */
+//    public native void setReturnTerms (boolean on);
+//    /** sets the default boolean operator - AND(=1)/OR(=0) */
+//    public native void setMatchMode (int mode);
+//    
+//    /** returns a string with all the current query param settings */
+//    public native String getQueryParams ();
+//    
+//    /** sets maxnumeric */
+//    public native void setMaxNumeric (int maxnumeric);
+//    
+//    /** actually carry out the query.
+//     * Use the set methods to set query results.
+//     * Writes the result to query_result.
+//     * - maintains state between requests as can be slow
+//     * base_dir and index_path should join together to provide
+//     * the absolute location of the mg index files eg ..../index/dtx/demo
+//     * base_dir must end with a file separator (OS dependant)
+//     */
+//    public native void runQuery (String base_dir, String text_dir, String query_string);
+//    
+//    
+//    /** get the result out of the wrapper */
+//    public MGQueryResult getQueryResult () {
+//        return mg_query_result_;
+//    }
+}
Index: /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGSearchWrapper.java
===================================================================
--- /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGSearchWrapper.java	(revision 14757)
+++ /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGSearchWrapper.java	(revision 14757)
@@ -0,0 +1,103 @@
+/*
+ *    MGSearchWrapper.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.mg;
+
+
+/** java wrapper class for access to mg in C
+ *
+ * the native side implemented in MGWrapperImpl.c
+ * uses MGQueryResult to hold the result of a query.
+ * the result of a getDocument is a String
+ * uses the jni
+ *
+ *@see MGQueryResult
+ */
+public class MGSearchWrapper
+{
+    /** the query result, filled in by runQuery */
+    protected MGQueryResult mg_query_result_ = null;
+
+    /** pointer to c MGWrapperData class - cached indexData and queryInfo */
+    protected long mg_data_ptr_ = 0;
+
+    static {
+	System.loadLibrary("mgsearchjni");
+	initIDs();
+    }
+
+    public MGSearchWrapper() {  System.out.println("in MGSearchWrapper.java");
+	mg_query_result_ = new MGQueryResult();
+	initCSide();
+    }
+
+    /** initialises field and method IDs for java side to enable access on C side */
+    private static native void initIDs();
+
+    /** initialises the mg_data_ptr_ */
+    private native boolean initCSide();
+
+    /** returns a document: number docnum at level level 
+     * the base_dir and text_path paths should join together to provide
+     * the absolute location of the mg text files eg ..../index/text/demo
+     * returns the doc in utf-8
+     */
+//    public native String getDocument(String base_dir, String text_dir, long docnum);
+
+    /** unloads the data */
+    public native boolean unloadIndexData();
+
+    // query param methods
+
+    /** if on=true, sets default casefolding on - it's off by default */
+    public native void setCase(boolean on);
+    /** if on=true, sets default stemming on - it's off by default */
+    public native void setStem(boolean on);
+    /** default is 50 */
+    public native void setMaxDocs(int num);
+    /** if on=true, a query returns term freq info - default is on */
+    public native void setReturnTerms(boolean on);
+    /** sets the index to search - default is 'dtx' */
+    public native void setIndex(String index);
+    /** sets the default boolean operator - AND(=1)/OR(=0) */
+    public native void setMatchMode(int mode);
+
+    /** returns a string with all the current query param settings */
+    public native String getQueryParams();
+
+    /** sets maxnumeric */
+    public native void setMaxNumeric(int maxnumeric); 
+
+    /** actually carry out the query.
+	Use the set methods to set query results.
+	Writes the result to query_result.
+     * - maintains state between requests as can be slow  
+     * base_dir and index_path should join together to provide
+     * the absolute location of the mg index files eg ..../index/dtx/demo 
+     * base_dir must end with a file separator (OS dependant)
+     */
+    public native void runQuery(String base_dir, String text_dir, String query_string);
+
+
+    /** get the result out of the wrapper */
+    public MGQueryResult getQueryResult()
+    {
+	return mg_query_result_;
+    }
+}
+
Index: /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGTermInfo.java
===================================================================
--- /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGTermInfo.java	(revision 14757)
+++ /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGTermInfo.java	(revision 14757)
@@ -0,0 +1,72 @@
+/*
+ *    MGTermInfo.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.mg;
+
+
+import java.util.Vector;
+
+
+/** TermInfo 'struct' class for a search result from mg
+ *  used by MGQueryResult
+ *
+ * @see MGQueryResult
+ */
+public class MGTermInfo
+{
+    /** the term itself */
+    public String term_ = null;
+
+    /** the stem and casefold method used
+	0 = none
+	1 = casefold only
+	2 = stem only
+	3 = casefold and stem */
+    public int stem_method_ = 0;
+
+    /** list of stemmed and casefolded equivalent terms - if stem_method_ is non-zero 
+      - Vector of Strings */
+    public Vector equiv_terms_ = null;
+
+
+    public MGTermInfo()
+    {
+	equiv_terms_ = new Vector();
+    }
+
+
+    public void addEquivTerm(String equivTerm, long match, long freq)
+    {
+	equiv_terms_.add(new MGEquivTermInfo(equivTerm, match, freq));
+    }
+
+
+    /** output the class as a string */
+    public String toString()
+    {
+	String result = "\"" + term_ + "\"";
+	result += " stem(" + stem_method_ + ")";
+	result += " equiv terms(";
+	for (int i = 0; i < equiv_terms_.size(); i++) {
+	    if (i > 0) result += ", ";
+	    result += equiv_terms_.elementAt(i);
+	}
+	result += ")";
+	return result;
+    }
+}
Index: /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGWrapper.java
===================================================================
--- /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGWrapper.java	(revision 14757)
+++ /indexers/branches/3.03a/mg/java/org/greenstone/mg/MGWrapper.java	(revision 14757)
@@ -0,0 +1,102 @@
+/*
+ *    MGWrapper.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.mg;
+
+
+/** java wrapper class for access to mg in C
+ *
+ * the native side implemented in MGWrapperImpl.c
+ * uses MGQueryResult to hold the result of a query.
+ * the result of a getDocument is a String
+ * uses the jni
+ *
+ *@see MGQueryResult
+ */
+public class MGWrapper
+{
+    /** the query result, filled in by runQuery */
+    protected MGQueryResult mg_query_result_ = null;
+
+    /** pointer to c MGWrapperData class - cached indexData and queryInfo */
+    protected long mg_data_ptr_ = 0;
+
+    static {
+	System.loadLibrary("mgjni");
+	initIDs();
+    }
+
+    public MGWrapper() {
+	mg_query_result_ = new MGQueryResult();
+	initCSide();
+    }
+
+    /** initialises field and method IDs for java side to enable access on C side */
+    private static native void initIDs();
+
+    /** initialises the mg_data_ptr_ */
+    private native boolean initCSide();
+
+    /** returns a document: number docnum at level level 
+     * the base_dir and text_path paths should join together to provide
+     * the absolute location of the mg text files eg ..../index/text/demo
+     * returns the doc in utf-8
+     */
+    public native String getDocument(String base_dir, String text_dir, long docnum);
+
+    /** unloads the data */
+    public native boolean unloadIndexData();
+
+    // query param methods
+
+    /** if on=true, sets default casefolding on - it's off by default */
+    public native void setCase(boolean on);
+    /** if on=true, sets default stemming on - it's off by default */
+    public native void setStem(boolean on);
+    /** default is 50 */
+    public native void setMaxDocs(int num);
+    /** if on=true, a query returns term freq info - default is on */
+    public native void setReturnTerms(boolean on);
+    /** sets the index to search - default is 'dtx' */
+    public native void setIndex(String index);
+    /** sets the default boolean operator - AND(=1)/OR(=0) */
+    public native void setMatchMode(int mode);
+
+    /** returns a string with all the current query param settings */
+    public native String getQueryParams();
+
+    /** sets maxnumeric */
+    public native void setMaxNumeric(int maxnumeric); 
+
+    /** actually carry out the query.
+	Use the set methods to set query results.
+	Writes the result to query_result.
+     * - maintains state between requests as can be slow  
+     * base_dir and index_path should join together to provide
+     * the absolute location of the mg index files eg ..../index/dtx/demo 
+     * base_dir must end with a file separator (OS dependant)
+     */
+    public native void runQuery(String base_dir, String text_dir, String query_string);
+
+
+    /** get the result out of the wrapper */
+    public MGQueryResult getQueryResult()
+    {
+	return mg_query_result_;
+    }
+}
Index: /indexers/branches/3.03a/mg/java/org/greenstone/mg/Makefile.in
===================================================================
--- /indexers/branches/3.03a/mg/java/org/greenstone/mg/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/mg/java/org/greenstone/mg/Makefile.in	(revision 14757)
@@ -0,0 +1,62 @@
+
+SHELL = /bin/sh
+VPATH = @srcdir@
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+bindir = @bindir@
+srcdir = @srcdir@
+libdir = @libdir@
+subdir = java/org/greenstone/mg
+top_srcdir = @top_srcdir@
+transform = @program_transform_name@
+
+AR = ar
+CC = @CC@
+CXX = @CXX@
+JAVAC = $(JAVA_HOME)/bin/javac
+JAVAH = $(JAVA_HOME)/bin/javah
+JAR = $(JAVA_HOME)/bin/jar
+CFLAGS = @CFLAGS@ -ansi -DSILENT -DSHORT_SUFFIX
+CXXFLAGS = @CXXFLAGS@ -DSILENT -DSHORT_SUFFIX
+DEFS = @DEFS@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBS =  -lstdc++ @LIBS@
+TOUCH = echo timestamp >
+AWK = @AWK@
+
+MGHOME=../../../..
+JAVACLASSDIR=./classes
+JAVASRCDIR=../../..
+JAVACOPTIONS= -deprecation -g -O
+JAVACLASSPATH=$(JAVACLASSDIR):
+
+datadir = $(prefix)/share
+libexecdir = $(exec_prefix)/libexec
+localedir = $(datadir)/locale
+mandir = $(prefix)/man/man1
+
+
+all: setup compile
+
+setup:
+	mkdir -p $(JAVACLASSDIR)
+
+compile: setup
+	$(JAVAC) -d $(JAVACLASSDIR) -sourcepath $(JAVASRCDIR) $(JAVACOPTIONS) *.java
+	$(JAVAH) -classpath $(JAVACLASSPATH) -d $(MGHOME)/jni org.greenstone.mg.MGWrapper
+	$(JAVAH) -classpath $(JAVACLASSPATH) -d $(MGHOME)/jni org.greenstone.mg.MGPassesWrapper
+	$(JAR) cf $(MGHOME)/mg.jar -C $(JAVACLASSDIR) org
+
+clean:
+	rm -rf $(JAVACLASSDIR) $(MGHOME)/mg.jar $(MGHOME)/jni/org_greenstone_mg_MGWrapper.h $(MGHOME)/jni/org_greenstone_mg_MGPassesWrapper.h
+
+install:
+
+distclean: clean
+	rm -f Makefile
+
+
Index: /indexers/branches/3.03a/mg/java/org/greenstone/mg/Queryer.java
===================================================================
--- /indexers/branches/3.03a/mg/java/org/greenstone/mg/Queryer.java	(revision 14757)
+++ /indexers/branches/3.03a/mg/java/org/greenstone/mg/Queryer.java	(revision 14757)
@@ -0,0 +1,175 @@
+/*
+ *    Queryer.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.mg;
+
+import java.util.Vector;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/** Queryer - java port of c++ Queryer 
+ * - uses MGWrapper to access mg
+ * only has get document and search - full text browse not implemented
+ *
+ * run as:
+ * java org.greenstone.mg.Queryer <basedir> <indexdir> <textdir>
+ *@see MGWrapper
+ */
+public class Queryer {
+  
+    /** outputs to std out a help message describing the commands used by 
+     * Queryer 
+     */
+    public void printHelp()
+    {
+	System.out.println( "commands available are:\n"+
+			    "\t.q\t\tquit\n"+
+			    "\t.h\t\tprint this help message\n"+
+			    "\t.d\t\tprint the current query parameter settings\n" +
+			    "\t.i<index>\tsearch index <index>\n"+
+			    "\t.t0/.t1\t\tquery type some/all\n"+
+			    "\t.c0/.c1\t\tcasefolding off/on\n"+
+			    "\t.s0/.s1\t\tstemming off/on\n"+
+			    "\t.o0/.o1\t\tshort output off/on\n"+
+			    "\t.m<num>\t\tset max docs to return to num\n\n"+
+			    "\t.p<docnum>\tprint document docnum\n"+
+			    "\t<query string>\tdo a query\n");
+    }
+
+
+    public static void main(String[] args)
+    {
+	if (args.length != 3) {
+	    System.out.println("Usage: java org.greenstone.mg.Queryer <basedir> <indexdir> <textdir>");
+	    return;
+	}
+
+	Queryer self = new Queryer();
+
+	String base_dir = args[0];
+	String index_path = args[1];
+	String text_path = args[2];
+
+	// the jni class to access mg stuff
+	MGWrapper wrapper = new MGWrapper();
+	wrapper.setIndex(index_path);
+
+	System.out.println("Welcome to Java Queryer :-)");
+	self.printHelp();
+
+	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+	boolean shortOutput = false;
+
+	String command; // user input
+	char x; // the command letter
+	String data = null; // any auxiliary input to a command
+	while (true) {
+	    System.out.print(">"); // the prompt
+            try {
+                command = br.readLine();
+                command = command.trim();
+		if (command.startsWith(".")) {
+		    // a system command
+		    x = command.charAt(1);
+		    if (command.length() > 2) {
+			data = command.substring(2);
+			data = data.trim();
+		    }
+
+		    switch (x) {
+		    case 'q': // clean up and exit
+			wrapper.unloadIndexData();
+			return;
+		    case 'h': // print help message
+			self.printHelp();
+			break;
+		    case 'd': // print query param settings
+			String info = wrapper.getQueryParams();
+			System.out.println(info);
+			break;
+		    case 'p': // print doc
+			int docnum = Integer.parseInt(data);
+			String doc = wrapper.getDocument(base_dir, text_path, docnum);
+			System.out.println(doc);
+			break;
+		    case 'm': //match docs
+			int match = Integer.parseInt(data);
+			wrapper.setMaxDocs(match);
+			break;
+		    case 's': // set stem on/off
+			int stem = Integer.parseInt(data);
+			if (stem==0 ){
+			    wrapper.setStem(false);
+			} else if(stem==1) {
+			    wrapper.setStem(true);
+			} else {
+			    System.err.println("Error: stem should be 0 or 1");
+			}
+			break;
+		    case 'c': // set case on/off
+			int casef = Integer.parseInt(data);
+			if (casef==0) {
+			    wrapper.setCase(false);
+			} else if (casef==1) {
+			    wrapper.setCase(true);
+			} else {
+			    System.err.println("Error: case should be 0 or 1");
+			}
+			break;
+		    case 'i': // set index
+			wrapper.setIndex(data);
+			break;
+		    case 't': // set query type some/all
+			int type = Integer.parseInt(data);
+			if (type==0 || type==1) {
+			    wrapper.setMatchMode(type);
+			} else {
+			    System.err.println("Error: type should be 0 (some) or 1 (all)");
+			}
+			break;
+		    case 'o': // set output short/long
+			int output = Integer.parseInt(data);
+			if (output==0) {
+			    shortOutput = false;
+			} else if (output==1) {
+			    shortOutput = true;
+			} else {
+			    System.err.println("Error: output should be 0 or 1");
+			}
+			break;
+		    }
+		}
+		else {
+		    // a query
+		    wrapper.runQuery(base_dir, text_path, command);
+		    MGQueryResult res = wrapper.getQueryResult();
+		    System.out.println("(Java) Matching documents: " + res.getTotalDocs());
+		    if (shortOutput) {
+			System.out.println(res.toShortString());
+		    } else {
+			System.out.println(res.toString());
+		    }
+		}
+
+	    } catch (Exception e) {
+		System.out.println("Queryer error: "+e.getClass() + " "+e.getMessage());
+		e.printStackTrace();
+	    }
+	}
+    }
+}
Index: /indexers/branches/3.03a/mg/java/org/greenstone/mg/winMake.bat
===================================================================
--- /indexers/branches/3.03a/mg/java/org/greenstone/mg/winMake.bat	(revision 14757)
+++ /indexers/branches/3.03a/mg/java/org/greenstone/mg/winMake.bat	(revision 14757)
@@ -0,0 +1,47 @@
+@echo off
+
+set MGHOME=..\..\..\..
+
+rem ---- Where to put class files ----
+set JAVACLASSDIR=classes
+
+rem ---- Name and location of java programs ----
+set JAVAC="%JAVA_HOME%\bin\javac"
+set JAVAH="%JAVA_HOME%\bin\javah"
+set JAVA="%JAVA_HOME%\bin\java"
+set JAVADOC="%JAVA_HOME%\bin\javadoc"
+set JAR="%JAVA_HOME%\bin\jar"
+
+set JAVACOPTIONS= -deprecation -g -O
+
+
+if ""%1"" == """" goto all
+if ""%1"" == ""all"" goto all
+if ""%1"" == ""install"" goto install
+if ""%1"" == ""clean"" goto clean
+
+:unknown
+	echo Error: Unrecognized argument %1.
+	goto done
+
+:all
+	if not exist %JAVACLASSDIR% mkdir %JAVACLASSDIR%
+	echo Compiling MG Java classes ...
+        %JAVAC% -d %JAVACLASSDIR% %JAVACOPTIONS% *.java
+	%JAVAH% -classpath %JAVACLASSDIR% -d %MGHOME%\jni org.greenstone.mg.MGWrapper
+	%JAVAH% -classpath %JAVACLASSDIR% -d %MGHOME%\jni org.greenstone.mg.MGPassesWrapper
+	%JAR% cf %MGHOME%\mg.jar -C %JAVACLASSDIR% org
+	goto done
+
+:install
+	goto done
+
+:clean
+	echo Cleaning up...
+	if exist %JAVACLASSDIR% rmdir /S /Q %JAVACLASSDIR%
+        if exist %MGHOME%\mg.jar del %MGHOME%\mg.jar
+        if exist %MGHOME%\jni\org_greenstone_mg_MGWrapper.h del %MGHOME%\jni\org_greenstone_mg_MGWrapper.h
+        if exist %MGHOME%\jni\org_greenstone_mg_MGPassesWrapper.h del %MGHOME%\jni\org_greenstone_mg_MGPassesWrapper.h
+	goto done
+
+:done
Index: /indexers/branches/3.03a/mg/jni/MGPassesWrapperImpl.c
===================================================================
--- /indexers/branches/3.03a/mg/jni/MGPassesWrapperImpl.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/jni/MGPassesWrapperImpl.c	(revision 14757)
@@ -0,0 +1,243 @@
+/*
+ *    MGPassesWrapperImpl.c
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <jni.h>
+#include <assert.h>
+#include "sysfuncs.h"
+#include "org_greenstone_mg_MGPassesWrapper.h"
+
+#include "mg_passes_4jni.h"
+#include "mg_files.h"
+
+/* if we need to use java objects, we should initialise their field ids here*/
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_initIDs(JNIEnv *j_env, jclass j_cls)
+{
+  return;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_initCSide(JNIEnv *j_env, jobject j_obj)
+{
+  clear_variables();
+  return 1;  /* true - no errors */
+}  
+
+/* add a pass type T1, T2, I1, I2, S */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_addPass(JNIEnv *j_env, 
+					       jobject j_obj, 
+					       jchar j_pass_type,
+					       jchar j_pass_num)
+{
+  /* get the level as a c char */
+  const char pass_type = j_pass_type;
+  const char pass_num = j_pass_num;
+  add_pass(pass_type, pass_num);
+  
+}
+
+/* Set the filename */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_setFileName(JNIEnv *j_env, 
+						   jobject j_obj,
+						   jstring j_filename)
+{
+  /* Get the filename as a C string */
+  const char* filename = (*j_env)->GetStringUTFChars(j_env, j_filename, NULL);
+ 
+  assert(filename != NULL);
+  set_filename(filename);
+  
+  /* Release the string */
+ (*j_env)->ReleaseStringUTFChars(j_env, j_filename, filename);
+
+}
+
+/* Set the base path */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_setBasePath(JNIEnv *j_env, 
+						   jobject j_obj,
+						   jstring j_basepath)
+{
+  /* Get the base_path as a C string */
+  const char* basepath = (*j_env)->GetStringUTFChars(j_env, j_basepath, NULL);
+  assert(basepath != NULL);
+ 
+  set_basepath(basepath);
+  
+  /* Release the string */
+  (*j_env)->ReleaseStringUTFChars(j_env, j_basepath, basepath);
+
+}
+
+/* set the level for the inverted file */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_setInvfLevel(JNIEnv *j_env, 
+						    jobject j_obj, 
+						    jchar j_level)
+{
+  /* get the level as a c char */
+  const char level = j_level;
+  set_invf_level(level);
+  
+}
+
+/* set the stemmer and stem method */
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mg_MGPassesWrapper_setStemOptions(JNIEnv *j_env, 
+						      jobject j_obj,
+						      jstring j_stemmer, 
+						      jint j_method)
+{
+
+  const char* stemmer = (*j_env)->GetStringUTFChars(j_env, j_stemmer, NULL);
+  int method = j_method;
+
+  assert(stemmer != NULL);
+  set_stem_options(stemmer, method);
+  
+  /* Release the string */
+  (*j_env)->ReleaseStringUTFChars(j_env, j_stemmer, stemmer);
+ }
+
+/** Specify  the size of the document buffer in kilobytes.
+    If any document is larger than  bufsize,  the  program
+    will  abort with an error message. 
+*/
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_setBufferSize(JNIEnv *j_env, 
+						     jobject j_obj, 
+						     jlong j_bufsize){
+  long buffer = j_bufsize;
+  set_buffer_size(buffer);
+}
+    
+/** Maximum amount of memory to use for  the index  pass-2  file
+    inversion  in  megabytes.
+*/
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_setInversionMemLimit(JNIEnv *j_env, 
+							    jobject j_obj, 
+							    jint j_limit) {
+  int limit = j_limit;
+  set_inversion_limit(limit);
+}
+
+/** If true, treat   SGML  tags  as  non-words  when  building  the
+    inverted file.
+*/
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_ignoreSGMLTags(JNIEnv *j_env, 
+						      jobject j_obj, 
+						      jboolean j_ignore){
+  int ignore = j_ignore;
+  ignore_sgml_tags(ignore);
+}
+
+/** if mg_passes fails, the document that caused the failure will be
+    output to the trace file or STDERR. 
+*/
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_dumpFailedDocument(JNIEnv *j_env, 
+							  jobject j_obj, 
+							  jboolean j_dump) {
+  int dump = j_dump;
+  dump_failed_document(dump);
+}
+
+/** output statistics on the compression performance to  a  file  
+    called  *.compression.stats.    frequency  specifies  the  interval
+    (in kilobytes of source text) between outputting each line of 
+    statistics. 
+*/
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_outputCompStats(JNIEnv *j_env, 
+						       jobject j_obj, 
+						       jint j_frequency){
+  int comp_stat_point = j_frequency;
+  set_comp_stat_point(comp_stat_point);
+  
+}
+/** activate tracing, a line will be output every tracepos input bytes */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_enableTracing(JNIEnv *j_env, 
+						     jobject j_obj, 
+						     jint j_tracepos){
+  int tracepos = j_tracepos;
+  set_trace_point(tracepos);
+}
+
+/** specify the name of the trace file */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGPassesWrapper_setTraceFile(JNIEnv *j_env, 
+						     jobject j_obj, 
+						     jstring j_tracefile){
+
+  const char* tracefile = (*j_env)->GetStringUTFChars(j_env, j_tracefile, NULL);
+  assert(tracefile != NULL);
+  set_trace_file(tracefile);
+  /* Release the string */
+  (*j_env)->ReleaseStringUTFChars(j_env, j_tracefile, tracefile);
+}
+
+/* initialise the pass through the documents. must be called after all
+   the set methods 
+*/
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mg_MGPassesWrapper_init(JNIEnv *j_env, 
+					    jobject j_obj) {
+
+  init_driver();
+  return 1;
+}
+
+
+/* process one document */
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mg_MGPassesWrapper_processMGDocument(JNIEnv *j_env, 
+						       jobject j_obj,
+						       jbyteArray j_doc_text) {
+  /* Get the text as a C string */
+  int length = (*j_env)->GetArrayLength(j_env, j_doc_text);
+  u_char * text_buffer = (u_char *)(*j_env)->GetByteArrayElements(j_env, j_doc_text, NULL);
+  process_document(text_buffer, length);
+  /* Release the string */
+  (*j_env)->ReleaseByteArrayElements(j_env, j_doc_text, text_buffer,0);
+  return 1;
+}
+
+/* finalise the pass through the documents */
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mg_MGPassesWrapper_finish(JNIEnv *j_env, 
+					    jobject j_obj) {
+  
+  finalise_driver();
+  return 1;
+}
+
+/** get the exit value once finished */
+JNIEXPORT jint JNICALL 
+Java_org_greenstone_mg_MGPassesWrapper_exitValue(JNIEnv *j_env, 
+					    jobject j_obj) {
+
+  return get_exit_value();
+}
+
Index: /indexers/branches/3.03a/mg/jni/MGRetrieveWrapperImpl.c
===================================================================
--- /indexers/branches/3.03a/mg/jni/MGRetrieveWrapperImpl.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/jni/MGRetrieveWrapperImpl.c	(revision 14757)
@@ -0,0 +1,318 @@
+/*
+ *    MGRetrieveWrapperImpl.c
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "MGWrapperImpl.h"
+#include <jni.h>
+#include "org_greenstone_mg_MGRetrieveWrapper.h"
+
+#include "backend.h"
+#include "environment.h"
+#include "text_get.h"
+#include "stemmer.h"
+
+#define MAX_INDEXES_CACHED 3
+
+/* copied from mgquery, needed to convert paragraph numbers to document numbers
+   for greenstone */
+#if defined(PARADOCNUM) ||  defined(NZDL)
+static int GetDocNumFromParaNum(query_data *qd, int paranum) {
+  int Documents = qd->td->cth.num_of_docs;
+  int *Paragraph = qd->paragraph;
+  int low = 1, high = Documents;
+  int mid = (low+high)/2;
+
+  while ((mid = (low+high)/2) >=1 && mid <= Documents)
+    {
+      if (paranum > Paragraph[mid])
+        low = mid+1;
+      else if (paranum <= Paragraph[mid-1])
+        high = mid-1;
+      else
+        return mid;
+    }
+  FatalError(1, "Bad paragraph number.\n");
+  return 0;
+}
+#endif
+
+
+/*********************************************
+   initialisation stuff
+ *********************************************/
+
+/* cached ids for java stuff */
+jfieldID FID_mg_data = NULL; /* MGWrapperData */
+jfieldID FID_query_result = NULL; /* MGQueryResult */
+jmethodID MID_addDoc = NULL; /* MGQueryResult.addDoc() */
+jmethodID MID_addTerm = NULL; /* MGQueryResult.addTerm() */
+jmethodID MID_addEquivTerm = NULL; /* MGQueryResult.addEquivTerm() */
+jmethodID MID_setTotalDocs = NULL; /* MGQueryResult.setTotalDocs() */
+jmethodID MID_clearResult = NULL; /* MGQueryResult.clear() */
+
+
+/*******************************************
+   Index caching
+ *******************************************/
+
+query_data* cached_indexes[MAX_INDEXES_CACHED] = { NULL };
+
+
+/* Get the index data necessary to perform a query or document retrieval */
+query_data*
+loadIndexData(char* base_dir, char* index_path, char* text_path)
+{
+  char* index_path_name;
+  char* text_path_name;
+  query_data* qd;
+  int i = 0;
+
+  /* Form the path name of the desired indexes */
+  index_path_name = (char*) malloc(strlen(base_dir) + strlen(index_path) + 1);
+  assert(index_path_name != NULL);
+  strcpy(index_path_name, base_dir);
+  strcat(index_path_name, index_path);
+  printf("Index pathname: %s\n", index_path_name);
+
+  text_path_name = (char*) malloc(strlen(base_dir) + strlen(text_path) + 1);
+  assert(text_path_name != NULL);
+  strcpy(text_path_name, base_dir);
+  strcat(text_path_name, text_path);
+  printf("Text pathname: %s\n", text_path_name);
+
+  /* Search through the cached indexes for the desired one */
+  while (i < MAX_INDEXES_CACHED && cached_indexes[i] != NULL) {
+    printf("(Cached) Pathname: %s\n", cached_indexes[i]->pathname);
+    printf("(Cached) Textpathname: %s\n", cached_indexes[i]->textpathname);
+
+    /* Check if the index has already been loaded */
+    if ((strcmp(index_path_name, cached_indexes[i]->pathname) == 0) &&
+	(strcmp(text_path_name, cached_indexes[i]->textpathname) == 0)) {
+      /* Index has already been loaded and cached, so return it */
+      printf("Found index!\n");
+      free(index_path_name);
+      free(text_path_name);
+      return cached_indexes[i];
+    }
+
+    i++;
+  }
+
+  /* Text strings no longer needed */
+  free(index_path_name);
+  free(text_path_name);
+
+  /* The index is not cached, so load it now */
+  qd = InitQuerySystem(base_dir, index_path, text_path, NULL);
+  if (!qd) {
+    printf("Error: Could not InitQuerySystem()...\n");
+    return NULL;
+  }
+
+  /* The index loaded OK, so cache it */
+  /* This could be a little more sophisticated, eg. replace least frequently used index */
+  if (i >= MAX_INDEXES_CACHED)
+    i = MAX_INDEXES_CACHED - 1;
+
+  /* Free the index being replaced */
+  if (cached_indexes[i] != NULL)
+    FinishQuerySystem(cached_indexes[i]);
+
+  /* Cache the loaded index, and return it */
+  cached_indexes[i] = qd;
+  return cached_indexes[i];
+}
+
+/*
+ * Class:     org_greenstone_mg_MGRetrieveWrapper
+ * Method:    initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGRetrieveWrapper_initIDs(JNIEnv *j_env, jclass j_cls)
+{
+  /* a long-"J" */
+  FID_mg_data = (*j_env)->GetFieldID(j_env, j_cls, "mg_data_ptr_", "J");
+  assert(FID_mg_data != NULL);
+
+}
+
+/*
+ * Class:     org_greenstone_mg_MGRetrieveWrapper
+ * Method:    initCSide
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mg_MGRetrieveWrapper_initCSide
+(JNIEnv *j_env, jobject j_obj)
+{
+  /* Allocate a MGWrapperData object to store query parameters */
+  MGWrapperData* data = (MGWrapperData*) malloc(sizeof(MGWrapperData));
+  assert(data != NULL);
+
+  /* Set default values - no stemming, no case-folding, boolean OR queries */
+  data->defaultStemMethod = 0;
+  data->defaultBoolCombine = 0;
+
+  /* Allocate a QueryInfo object to store more query parameters */
+  data->queryInfo = (QueryInfo*) malloc(sizeof(QueryInfo));
+  assert(data->queryInfo != NULL);
+
+  /* Set default values - 50 documents max, return term freqs, sort by rank */
+  data->queryInfo->index = NULL;
+  data->queryInfo->maxDocs = 50;
+  data->queryInfo->needTermFreqs = 1;
+
+  /* Save the object on the Java side */
+  (*j_env)->SetIntField(j_env, j_obj, FID_mg_data, (long) data);
+
+  /* Initialise MG environment variables */
+  InitEnv();
+  SetEnv("expert", "true", NULL);
+  SetEnv("mode", "docnums", NULL);
+  
+  return 1;  /* true - no errors */
+}
+
+/*
+ * Class:     org_greenstone_mg_MGRetrieveWrapper
+ * Method:    unloadIndexData
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mg_MGRetrieveWrapper_unloadIndexData
+(JNIEnv* j_env, jobject j_obj)
+{
+  /* Free all the loaded indexes */
+  int i = 0;
+  while (i < MAX_INDEXES_CACHED && cached_indexes[i] != NULL) {
+    FinishQuerySystem(cached_indexes[i]);
+    cached_indexes[i] = NULL;
+    i++;
+  }
+
+  return 1;  /* true - no errors */
+}
+/* Choose MG index to search */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGRetrieveWrapper_setIndex(JNIEnv *j_env, jobject j_obj,
+					  jstring j_index)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+
+  /* Get the index name as a C string */
+  const char* index = (*j_env)->GetStringUTFChars(j_env, j_index, NULL);
+  assert(index != NULL);
+  printf("Choosing index %s...\n", index);
+
+  /* Free the previous index name */
+  if (data->queryInfo->index)
+    free(data->queryInfo->index);
+
+  /* Allocate memory for the index name, and fill it */
+  data->queryInfo->index = (char*) malloc(strlen(index) + 1);
+  assert(data->queryInfo->index != NULL);
+  strcpy(data->queryInfo->index, index);
+
+  /* Release the index string */
+  (*j_env)->ReleaseStringUTFChars(j_env, j_index, index);
+}
+
+/*
+ * Class:     org_greenstone_mg_MGRetrieveWrapper
+ * Method:    getDocument
+ * Signature: (Ljava/lang/String;Ljava/lang/String;J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_greenstone_mg_MGRetrieveWrapper_getDocument
+(JNIEnv *j_env, jobject j_obj,
+					     jstring j_base_dir, jstring j_text_path,
+					     jlong j_docnum)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+
+  char* index_path;
+  const char* base_dir;
+  const char* text_path;
+  query_data* qd;
+
+  u_long pos, len;
+  u_char* c_buffer = NULL;
+  u_char* uc_buffer = NULL;
+  int ULen;
+
+  jstring result;
+
+  /* Make sure an index has been specified */
+  index_path = data->queryInfo->index;
+  assert(index_path != NULL);
+
+  /* Obtain C versions of the two string parameters */
+  base_dir = (*j_env)->GetStringUTFChars(j_env, j_base_dir, NULL);
+  if (base_dir == NULL) {
+    return NULL;
+  }
+  text_path = (*j_env)->GetStringUTFChars(j_env, j_text_path, NULL);
+  if (text_path == NULL) {
+    (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
+    return NULL;
+  }
+
+  /* Load the appropriate index for satisfying this request */
+  printf("Document retrieval, index path: %s\n", index_path);
+  qd = loadIndexData((char*) base_dir, (char*) index_path, (char*) text_path);
+
+  /* The C text strings are no longer needed */
+  (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
+  (*j_env)->ReleaseStringUTFChars(j_env, j_text_path, text_path);
+
+  /* Check that the index was loaded successfully */
+  if (qd==NULL) {
+    return NULL;
+  }
+  /*assert(qd != NULL);*/
+
+  /* Get the document position and length in the text file */
+  printf("Fetching document number %ld...\n", (unsigned long) j_docnum);
+  FetchDocStart(qd, (unsigned long) j_docnum, &pos, &len);
+  printf("Fetched document start. Pos: %ld, Len: %ld\n", pos, len);
+
+  /* Allocate memory for the document text (from mg/src/text/mgquery.c:RawDocOutput()) */
+  c_buffer = (u_char*) malloc(len);
+  assert(c_buffer != NULL);
+  uc_buffer = (u_char*) malloc((int) (qd->td->cth.ratio * 1.01 * len) + 100);
+  assert(uc_buffer != NULL);
+
+  /* Seek to the correct position in the file and read the document text */
+  Fseek (qd->td->TextFile, pos, 0);
+  Fread (c_buffer, 1, len, qd->td->TextFile);
+
+  /* Decompress the document text into another buffer, and terminate it */
+  DecodeText (qd->cd, c_buffer, len, uc_buffer, &ULen);
+  uc_buffer[ULen] = '\0';
+
+  /* Load the document text into a Java string */
+  result = (*j_env)->NewStringUTF(j_env, uc_buffer);
+  assert(result != NULL);
+
+  /* Free C buffers */
+  free(c_buffer);
+  free(uc_buffer);
+
+  /* Return the document text */
+  return result;
+}
+
Index: /indexers/branches/3.03a/mg/jni/MGSearchWrapperImpl.c
===================================================================
--- /indexers/branches/3.03a/mg/jni/MGSearchWrapperImpl.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/jni/MGSearchWrapperImpl.c	(revision 14757)
@@ -0,0 +1,631 @@
+/*
+ *    MGSearchWrapperImpl.c
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "MGWrapperImpl.h"
+#include <jni.h>
+#include "org_greenstone_mg_MGSearchWrapper.h"
+
+#include "backend.h"
+#include "environment.h"
+#include "text_get.h"
+#include "stemmer.h"
+
+
+#define MAX_INDEXES_CACHED 3
+
+/* copied from mgquery, needed to convert paragraph numbers to document numbers
+   for greenstone */
+#if defined(PARADOCNUM) ||  defined(NZDL)
+static int GetDocNumFromParaNum(query_data *qd, int paranum) {
+  int Documents = qd->td->cth.num_of_docs;
+  int *Paragraph = qd->paragraph;
+  int low = 1, high = Documents;
+  int mid = (low+high)/2;
+
+  while ((mid = (low+high)/2) >=1 && mid <= Documents)
+    {
+      if (paranum > Paragraph[mid])
+        low = mid+1;
+      else if (paranum <= Paragraph[mid-1])
+        high = mid-1;
+      else
+        return mid;
+    }
+  FatalError(1, "Bad paragraph number.\n");
+  return 0;
+}
+#endif
+
+
+/*********************************************
+   initialisation stuff
+ *********************************************/
+
+/* cached ids for java stuff */
+jfieldID FID_mg_data = NULL; /* MGWrapperData */
+jfieldID FID_query_result = NULL; /* MGQueryResult */
+jmethodID MID_addDoc = NULL; /* MGQueryResult.addDoc() */
+jmethodID MID_addTerm = NULL; /* MGQueryResult.addTerm() */
+jmethodID MID_addEquivTerm = NULL; /* MGQueryResult.addEquivTerm() */
+jmethodID MID_setTotalDocs = NULL; /* MGQueryResult.setTotalDocs() */
+jmethodID MID_clearResult = NULL; /* MGQueryResult.clear() */
+
+
+/* to access objects and methods on java side, need their field/method ids - 
+ this initialises them at the start to avoid recalculating them each time they
+ are needed
+Note: the descriptors need to be exactly right, otherwise you get an error 
+saying "no such field" but no reference to the fact that it has the right 
+name but the wrong type.
+Note: apparently the jclass is a local ref and should only work 
+in the method that created it. It seems to work ok, but I'll make it
+global cos the book said I should, and it may avoid future hassles.
+*/
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGSearchWrapper_initIDs(JNIEnv *j_env, jclass j_cls)
+{
+  jclass JC_MGQueryResult;
+
+  /* a long-"J" */
+  FID_mg_data = (*j_env)->GetFieldID(j_env, j_cls, "mg_data_ptr_", "J");
+  assert(FID_mg_data != NULL);
+
+  /* an object -"L<class name>;" */
+  FID_query_result = (*j_env)->GetFieldID(j_env, j_cls, "mg_query_result_",
+					  "Lorg/greenstone/mg/MGQueryResult;");
+  assert(FID_query_result != NULL);
+
+  /* the methods we want to use */
+  JC_MGQueryResult = (*j_env)->FindClass(j_env, "org/greenstone/mg/MGQueryResult");
+
+  /* addDoc(long doc, float rank) */
+  MID_addDoc = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "addDoc", "(JF)V");
+  assert(MID_addDoc != NULL);
+
+  /* addTerm(String term, int stem) */
+  MID_addTerm = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "addTerm", "(Ljava/lang/String;I)V");
+  assert(MID_addTerm != NULL);
+
+  /* addEquivTerm(String term, String equivTerm, long match, long freq) */
+  MID_addEquivTerm = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "addEquivTerm", "(Ljava/lang/String;Ljava/lang/String;JJ)V");
+  assert(MID_addEquivTerm != NULL);
+
+  /* setTotalDocs(long) */
+  MID_setTotalDocs = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "setTotalDocs", "(J)V");
+  assert(MID_setTotalDocs != NULL);
+
+  /* clear(void) */
+  MID_clearResult = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "clear", "()V");
+  assert(MID_clearResult != NULL);
+}
+
+
+/* the java side MGSearchWrapper has a pointer to a C object - MGWrapperData
+   initialise this and set the pointer 
+*/
+JNIEXPORT jboolean JNICALL
+Java_org_greenstone_mg_MGSearchWrapper_initCSide(JNIEnv *j_env, jobject j_obj)
+{
+  /* Allocate a MGWrapperData object to store query parameters */
+  MGWrapperData* data = (MGWrapperData*) malloc(sizeof(MGWrapperData));
+  assert(data != NULL);
+
+  /* Set default values - no stemming, no case-folding, boolean OR queries */
+  data->defaultStemMethod = 0;
+  data->defaultBoolCombine = 0;
+
+  /* Allocate a QueryInfo object to store more query parameters */
+  data->queryInfo = (QueryInfo*) malloc(sizeof(QueryInfo));
+  assert(data->queryInfo != NULL);
+
+  /* Set default values - 50 documents max, return term freqs, sort by rank */
+  data->queryInfo->index = NULL;
+  data->queryInfo->maxDocs = 50;
+  data->queryInfo->needTermFreqs = 1;
+
+  /* Save the object on the Java side */
+  (*j_env)->SetIntField(j_env, j_obj, FID_mg_data, (long) data);
+
+  /* Initialise MG environment variables */
+  InitEnv();
+  SetEnv("expert", "true", NULL);
+  SetEnv("mode", "docnums", NULL);
+  
+  return 1;  /* true - no errors */
+}
+
+
+/*******************************************
+   Index caching
+ *******************************************/
+
+query_data* cached_indexes[MAX_INDEXES_CACHED] = { NULL };
+
+
+/* Get the index data necessary to perform a query or document retrieval */
+query_data*
+loadIndexData(char* base_dir, char* index_path, char* text_path)
+{
+  char* index_path_name;
+  char* text_path_name;
+  query_data* qd;
+  int i = 0;
+
+  /* Form the path name of the desired indexes */
+  index_path_name = (char*) malloc(strlen(base_dir) + strlen(index_path) + 1);
+  assert(index_path_name != NULL);
+  strcpy(index_path_name, base_dir);
+  strcat(index_path_name, index_path);
+  printf("Index pathname: %s\n", index_path_name);
+
+  text_path_name = (char*) malloc(strlen(base_dir) + strlen(text_path) + 1);
+  assert(text_path_name != NULL);
+  strcpy(text_path_name, base_dir);
+  strcat(text_path_name, text_path);
+  printf("Text pathname: %s\n", text_path_name);
+
+  /* Search through the cached indexes for the desired one */
+  while (i < MAX_INDEXES_CACHED && cached_indexes[i] != NULL) {
+    printf("(Cached) Pathname: %s\n", cached_indexes[i]->pathname);
+    printf("(Cached) Textpathname: %s\n", cached_indexes[i]->textpathname);
+
+    /* Check if the index has already been loaded */
+    if ((strcmp(index_path_name, cached_indexes[i]->pathname) == 0) &&
+	(strcmp(text_path_name, cached_indexes[i]->textpathname) == 0)) {
+      /* Index has already been loaded and cached, so return it */
+      printf("Found index!\n");
+      free(index_path_name);
+      free(text_path_name);
+      return cached_indexes[i];
+    }
+
+    i++;
+  }
+
+  /* Text strings no longer needed */
+  free(index_path_name);
+  free(text_path_name);
+
+  /* The index is not cached, so load it now */
+  qd = InitQuerySystem(base_dir, index_path, text_path, NULL);
+  if (!qd) {
+    printf("Error: Could not InitQuerySystem()...\n");
+    return NULL;
+  }
+
+  /* The index loaded OK, so cache it */
+  /* This could be a little more sophisticated, eg. replace least frequently used index */
+  if (i >= MAX_INDEXES_CACHED)
+    i = MAX_INDEXES_CACHED - 1;
+
+  /* Free the index being replaced */
+  if (cached_indexes[i] != NULL)
+    FinishQuerySystem(cached_indexes[i]);
+
+  /* Cache the loaded index, and return it */
+  cached_indexes[i] = qd;
+  return cached_indexes[i];
+}
+
+
+/* Clean up by unloading all cached indexes */
+JNIEXPORT jboolean JNICALL
+Java_org_greenstone_mg_MGSearchWrapper_unloadIndexData(JNIEnv* j_env, jobject j_obj)
+{
+  /* Free all the loaded indexes */
+  int i = 0;
+  while (i < MAX_INDEXES_CACHED && cached_indexes[i] != NULL) {
+    FinishQuerySystem(cached_indexes[i]);
+    cached_indexes[i] = NULL;
+    i++;
+  }
+
+  return 1;  /* true - no errors */
+}
+
+
+/*******************************************
+   do a query
+ *******************************************/
+
+/* do the actual query - the results are written to query_result held on the Java side */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGSearchWrapper_runQuery(JNIEnv *j_env, jobject j_obj,
+					  jstring j_base_dir, jstring j_text_path,
+					  jstring j_query)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+
+  char* index_path;
+  const char* base_dir;
+  const char* text_path;
+  query_data* qd;
+
+  jobject result_ptr;
+  char* query;
+  int i, j;
+
+  jthrowable exc;
+  /* First of all, clear the previous result */
+  /* The result to write to */
+  result_ptr = (*j_env)->GetObjectField(j_env, j_obj, FID_query_result);
+  assert(result_ptr != NULL);
+
+  /* Clear any previous query results */
+  (*j_env)->CallVoidMethod(j_env, result_ptr, MID_clearResult);
+  exc = (*j_env)->ExceptionOccurred(j_env);
+  if (exc) {
+    (*j_env)->ExceptionDescribe(j_env);
+    return;
+  }
+
+  /* Make sure an index has been specified */
+  index_path = data->queryInfo->index;
+  if (index_path == NULL) {
+    return;
+  }
+
+  /* Obtain C versions of the two string parameters */
+  base_dir = (*j_env)->GetStringUTFChars(j_env, j_base_dir, NULL);
+  if (base_dir == NULL) {
+    return;
+  }
+  text_path = (*j_env)->GetStringUTFChars(j_env, j_text_path, NULL);
+  if (text_path == NULL) {
+    (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
+    return;
+  }
+
+  /* Load the appropriate index for satisfying this request */
+  qd = loadIndexData((char*) base_dir, (char*) index_path, (char*) text_path);
+
+  /* The C text strings are no longer needed */
+  (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
+  (*j_env)->ReleaseStringUTFChars(j_env, j_text_path, text_path);
+
+  /* Check that the index was loaded successfully */
+  if (qd == NULL) {
+    return;
+  }
+  
+  /* Remove anything hanging around from last time */
+  FreeQueryDocs(qd);
+
+  /* Obtain a C version of the query string */
+  query = (char*) (*j_env)->GetStringUTFChars(j_env, j_query, NULL);
+  if (query == NULL) {
+    return;
+  }
+  printf("Searching for query \"%s\"...\n", query);
+
+  /* Make sure the query isn't empty */
+  if (strlen(query) == 0) {
+    printf("Warning: Empty query.\n");
+    return;
+  }
+
+  /* "Some" queries are done as ranked queries */
+  if (data->defaultBoolCombine == 0) {
+    RankedQueryInfo rqi;
+    rqi.QueryFreqs = 1;  /* Use the frequency of each query term in the query - OK? */
+    rqi.Exact = 1;  /* Perform exact ranking */
+    rqi.MaxDocsToRetrieve = data->queryInfo->maxDocs;  /* Get only the desired number */
+    rqi.MaxParasToRetrieve = rqi.MaxDocsToRetrieve;  /* OK? */
+    /* we may need to get more paragraphs to get enough documents. I copied the following from mgquery. it seems to work, not sure why - kjdon */
+    if (qd->id->ifh.InvfLevel == 3 && GetEnv ("maxparas")) {
+      rqi.MaxParasToRetrieve = atoi (GetEnv ("maxparas"));
+    }
+    
+    rqi.Sort = 1;  /* Sort the query terms by frequency before ranking */
+    rqi.AccumMethod = 'L';  /* Use a list when accumulating (has bugs though...) */
+    /* rqi.MaxAccums = -1; */ /* Use as many accumulators as necessary - CRASHES with list */
+    rqi.MaxAccums = 100000;
+    rqi.MaxTerms = -1;  /* Use all the query terms */
+    /* rqi.StopAtMaxAccum = 0;*/  /* Don't care (using as many accumulators as necessary) */
+    rqi.StopAtMaxAccum = 1;
+    rqi.HashTblSize = 1000;  /* Don't care (not using a hash table) */
+    rqi.skip_dump = NULL;  /* Don't dump skip information */
+
+    /* RankedQuery() reads 'casefold' and 'stem' parameters from the environment */
+    SetEnv("casefold", ((data->defaultStemMethod & 1) ? "on" : "off"), NULL);
+    SetEnv("stem", ((data->defaultStemMethod & 2) ? "on" : "off"), NULL);
+
+    RankedQuery(qd, query, &rqi);
+  }
+  /* "All" queries are done as boolean queries */
+  else {
+    BooleanQueryInfo bqi;
+    bqi.MaxDocsToRetrieve = data->queryInfo->maxDocs;
+
+    /* Had to add "words$o" to LIB_OBJS in mg/src/text/Makefile and recompile mg for this */
+    BooleanQuery(qd, query, &bqi, data->defaultStemMethod);
+  }
+
+  /* Finished with the C query string */
+  (*j_env)->ReleaseStringUTFChars(j_env, j_query, query);
+
+  /* Check the query was processed successfully */
+  if (qd->DL == NULL || qd->QTL == NULL || qd->TL == NULL) {
+    return;
+  }
+
+  /* Record the total number of matching documents */
+  (*j_env)->CallVoidMethod(j_env, result_ptr, MID_setTotalDocs, (jlong) qd->DL->num);
+  exc = (*j_env)->ExceptionOccurred(j_env);
+  if (exc) {
+    (*j_env)->ExceptionDescribe(j_env);
+    return;
+  }
+
+  /* Record the matching documents, but only the number requested */
+  printf("Number of matching documents: %d\n", qd->DL->num);
+  
+  for (i = 0; (i < qd->DL->num && i < data->queryInfo->maxDocs); i++) {
+    int doc_num = qd->DL->DE[i].DocNum;
+    float doc_weight = qd->DL->DE[i].Weight;
+
+#if defined(PARADOCNUM) || defined(NZDL)
+    if (qd->id->ifh.InvfLevel == 3) {
+      /* pararaph level, need to convert to doc level*/
+      doc_num = GetDocNumFromParaNum(qd, doc_num);
+    }
+#endif
+    
+    
+    /* Call the addDoc function (Java side) to record a matching document */
+    (*j_env)->CallVoidMethod(j_env, result_ptr, MID_addDoc,
+			     (jlong) doc_num, (jfloat) doc_weight);
+    exc = (*j_env)->ExceptionOccurred(j_env);
+    if (exc) {
+      (*j_env)->ExceptionDescribe(j_env);
+      return;
+    }
+  }
+
+  /* Record the term information, if desired */
+  if (data->queryInfo->needTermFreqs) {
+    /* The following code is a lot more complicated than it could be, but it is necessary
+       to compensate for an oddity in MG. */
+    unsigned char** stemmed_terms = malloc(sizeof(unsigned char*) * qd->TL->num);
+
+    printf("Number of terms: %d\n", qd->TL->num);
+    printf("Number of query terms: %d\n", qd->QTL->num);
+
+    /* Generate the stemmed form of each of the relevant terms */
+    for (i = 0; i < qd->TL->num; i++) {
+      u_char* raw_term = qd->TL->TE[i].Word;
+      unsigned int term_length = raw_term[0];
+
+      u_char* raw_stemmed_term = malloc(term_length + 1);
+      unsigned int stemmed_term_length;
+
+      /* Copy the term, and stem it */
+      for (j = 0; j <= term_length; j++)
+	raw_stemmed_term[j] = raw_term[j];
+      stemmer(data->defaultStemMethod, qd->sd->sdh.stemmer_num, raw_stemmed_term);
+
+      /* Allocate memory to store the stemmed term, and fill it */
+      stemmed_term_length = raw_stemmed_term[0];
+      stemmed_terms[i] = malloc(stemmed_term_length + 1);
+      assert(stemmed_terms[i] != NULL);
+      strncpy(stemmed_terms[i], &(raw_stemmed_term[1]), stemmed_term_length);
+      stemmed_terms[i][stemmed_term_length] = '\0';
+    }
+
+    /* Record every query term, along with their equivalent terms */
+    for (i = 0; i < qd->QTL->num; i++) {
+      u_char* raw_query_term = qd->QTL->QTE[i].Term;
+      unsigned int query_term_length = raw_query_term[0];
+      unsigned char* query_term;
+      jstring j_query_term;
+
+      u_char* raw_stemmed_query_term = malloc(query_term_length + 1);
+      unsigned int stemmed_query_term_length;
+      unsigned char* stemmed_query_term;
+
+      /* Allocate memory to store the query term, and fill it */
+      query_term = malloc(query_term_length + 1);
+      assert(query_term != NULL);
+      strncpy(query_term, &(raw_query_term[1]), query_term_length);
+      query_term[query_term_length] = '\0';
+
+      /* Allocate a new jstring for the query term */
+      j_query_term = (*j_env)->NewStringUTF(j_env, query_term);
+      assert(j_query_term != NULL);
+
+      /* Call the addTerm function (Java side) to record the query term */
+      (*j_env)->CallVoidMethod(j_env, result_ptr, MID_addTerm,
+			       j_query_term, (jint) data->defaultStemMethod);
+      exc = (*j_env)->ExceptionOccurred(j_env);
+      if (exc) {
+	(*j_env)->ExceptionDescribe(j_env);
+	return;
+      }
+
+      /* Copy the query term, and stem it */
+      for (j = 0; j <= query_term_length; j++)
+	raw_stemmed_query_term[j] = raw_query_term[j];
+      stemmer(data->defaultStemMethod, qd->sd->sdh.stemmer_num, raw_stemmed_query_term);
+
+      /* Allocate memory to store the stemmed query term, and fill it */
+      stemmed_query_term_length = raw_stemmed_query_term[0];
+      stemmed_query_term = malloc(stemmed_query_term_length + 1);
+      assert(stemmed_query_term != NULL);
+      strncpy(stemmed_query_term, &(raw_stemmed_query_term[1]), stemmed_query_term_length);
+      stemmed_query_term[stemmed_query_term_length] = '\0';
+
+      /* Find all the terms equivalent to the query term */
+      for (j = 0; j < qd->TL->num; j++) {
+	/* Check if the stemmed query term matches the stemmed term */
+	if (strcmp(stemmed_query_term, stemmed_terms[j]) == 0) {
+	  u_char* raw_term = qd->TL->TE[j].Word;
+	  unsigned int term_length = raw_term[0];
+	  unsigned char* term;
+	  jstring j_term;
+
+	  /* Allocate memory to store the query term, and fill it */
+	  term = malloc(term_length + 1);
+	  assert(term != NULL);
+	  strncpy(term, &(raw_term[1]), term_length);
+	  term[term_length] = '\0';
+
+	  /* Allocate a new jstring for the query term */
+	  j_term = (*j_env)->NewStringUTF(j_env, term);
+	  assert(j_term != NULL);
+
+	  /* Call the addEquivTerm function (Java side) to record the equivalent term */
+	  (*j_env)->CallVoidMethod(j_env, result_ptr, MID_addEquivTerm,
+				   j_query_term, j_term,
+				   (jlong) qd->TL->TE[j].WE.doc_count,
+				   (jlong) qd->TL->TE[j].WE.count);
+	  exc = (*j_env)->ExceptionOccurred(j_env);
+	  if (exc) {
+	    (*j_env)->ExceptionDescribe(j_env);
+	    return;
+	  }
+	}
+      }
+    }
+  }
+}
+
+
+/*******************************************
+   set query options
+ *******************************************/
+
+/* Turn casefolding on or off */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGSearchWrapper_setCase(JNIEnv *j_env, jobject j_obj, 
+					 jboolean j_on)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+
+  if (j_on) {
+    data->defaultStemMethod |= 1;
+  } else {
+    data->defaultStemMethod &= 0xe;
+  }
+}
+
+
+/* Turn stemming on or off */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGSearchWrapper_setStem(JNIEnv *j_env, jobject j_obj, 
+					 jboolean j_on)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+
+  if (j_on) {
+    data->defaultStemMethod |= 2;
+  } else {
+    data->defaultStemMethod &= 0xd;
+  }
+}
+
+
+/* Set the maximum number of documents to return from a query */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGSearchWrapper_setMaxDocs(JNIEnv *j_env, jobject j_obj, 
+					    jint j_max)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+  data->queryInfo->maxDocs = j_max;
+}
+
+/* set the maximum number of numeric to split*/
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mg_MGSearchWrapper_setMaxNumeric (JNIEnv *j_env, 
+						 jobject j_obj, 
+						 jint j_max) {
+
+  char text[20];
+  char* maxnumeric;
+  sprintf(text,"%d",j_max); 
+  maxnumeric = text;  
+  SetEnv("maxnumeric",maxnumeric, NULL);
+}
+
+
+/* Turn term frequency recording on or off */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGSearchWrapper_setReturnTerms(JNIEnv *j_env, jobject j_obj, 
+						jboolean j_on)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+  data->queryInfo->needTermFreqs = j_on;
+}
+
+
+/* Choose MG index to search */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGSearchWrapper_setIndex(JNIEnv *j_env, jobject j_obj,
+					  jstring j_index)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+
+  /* Get the index name as a C string */
+  const char* index = (*j_env)->GetStringUTFChars(j_env, j_index, NULL);
+  assert(index != NULL);
+  printf("Choosing index %s...\n", index);
+
+  /* Free the previous index name */
+  if (data->queryInfo->index)
+    free(data->queryInfo->index);
+
+  /* Allocate memory for the index name, and fill it */
+  data->queryInfo->index = (char*) malloc(strlen(index) + 1);
+  assert(data->queryInfo->index != NULL);
+  strcpy(data->queryInfo->index, index);
+
+  /* Release the index string */
+  (*j_env)->ReleaseStringUTFChars(j_env, j_index, index);
+}
+
+
+/* Choose boolean AND or boolean OR queries */
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mg_MGSearchWrapper_setMatchMode(JNIEnv *j_env, jobject j_obj,
+					      jint j_mode)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+  data->defaultBoolCombine = j_mode;
+}
+
+
+/* Get a text representation of the current parameter values */
+JNIEXPORT jstring JNICALL
+Java_org_greenstone_mg_MGSearchWrapper_getQueryParams(JNIEnv *j_env, jobject j_obj)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+  char result[512];  /* Assume this is big enough */
+
+  /* Print the data to a character array */
+  sprintf(result, "Query params:\nindex\t\t%s\ncasefold\t%d\nstem\t\t%d\nquery type\t%s\nmax docs\t%ld\n",
+	  (data->queryInfo->index == NULL ? "<none loaded>" : data->queryInfo->index),
+	  (data->defaultStemMethod & 1),
+	  (data->defaultStemMethod & 2),
+	  (data->defaultBoolCombine == 1 ? "all" : "some"),
+	  (data->queryInfo->maxDocs));
+
+  /* Convert to a jstring, and return */
+  return (*j_env)->NewStringUTF(j_env, result);
+}
+
Index: /indexers/branches/3.03a/mg/jni/MGWrapperImpl.c
===================================================================
--- /indexers/branches/3.03a/mg/jni/MGWrapperImpl.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/jni/MGWrapperImpl.c	(revision 14757)
@@ -0,0 +1,741 @@
+/*
+ *    MGWrapperImpl.c
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "MGWrapperImpl.h"
+#include <jni.h>
+#include "org_greenstone_mg_MGWrapper.h"
+
+#include "backend.h"
+#include "environment.h"
+#include "text_get.h"
+#include "stemmer.h"
+
+/*************************************************************************
+   NOTES
+
+ - Features supported by MGPP but not by MG (AFAIK)
+
+   - Sorting results by rank.
+     Done here as a post-processing operation. Could be more efficient in
+     some cases: the current solution is not very good when the number of
+     matching documents is large and the number of desired matches is
+     small. In this case it would be better to iterate through the array
+     picking out the best documents rather than sorting them all.
+
+   - Asking for query term frequencies to be returned.
+     This cannot be turned off in MG. If the term frequencies are not
+     required, they are simply not passed back to the Java side.
+
+   - Choosing the index for queries.
+     It is possible for MG to build Section and Document indexes (for
+     example), but these are two separate indexes, and must be loaded
+     separately. This module can load more than one index at a time, thus
+     processing queries to different indexes more quickly.
+     NOTE: This replaces TWO options in the MGPP version: returnLevel and
+           queryLevel.
+
+ *************************************************************************/
+
+
+#define MAX_INDEXES_CACHED 3
+
+/* copied from mgquery, needed to convert paragraph numbers to document numbers
+   for greenstone */
+#if defined(PARADOCNUM) ||  defined(NZDL)
+static int GetDocNumFromParaNum(query_data *qd, int paranum) {
+  int Documents = qd->td->cth.num_of_docs;
+  int *Paragraph = qd->paragraph;
+  int low = 1, high = Documents;
+  int mid = (low+high)/2;
+
+  while ((mid = (low+high)/2) >=1 && mid <= Documents)
+    {
+      if (paranum > Paragraph[mid])
+        low = mid+1;
+      else if (paranum <= Paragraph[mid-1])
+        high = mid-1;
+      else
+        return mid;
+    }
+  FatalError(1, "Bad paragraph number.\n");
+  return 0;
+}
+#endif
+
+
+/*********************************************
+   initialisation stuff
+ *********************************************/
+
+/* cached ids for java stuff */
+jfieldID FID_mg_data = NULL; /* MGWrapperData */
+jfieldID FID_query_result = NULL; /* MGQueryResult */
+jmethodID MID_addDoc = NULL; /* MGQueryResult.addDoc() */
+jmethodID MID_addTerm = NULL; /* MGQueryResult.addTerm() */
+jmethodID MID_addEquivTerm = NULL; /* MGQueryResult.addEquivTerm() */
+jmethodID MID_setTotalDocs = NULL; /* MGQueryResult.setTotalDocs() */
+jmethodID MID_clearResult = NULL; /* MGQueryResult.clear() */
+
+
+/* to access objects and methods on java side, need their field/method ids - 
+ this initialises them at the start to avoid recalculating them each time they
+ are needed
+Note: the descriptors need to be exactly right, otherwise you get an error 
+saying "no such field" but no reference to the fact that it has the right 
+name but the wrong type.
+Note: apparently the jclass is a local ref and should only work 
+in the method that created it. It seems to work ok, but I'll make it
+global cos the book said I should, and it may avoid future hassles.
+*/
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGWrapper_initIDs(JNIEnv *j_env, jclass j_cls)
+{
+  jclass JC_MGQueryResult;
+
+  /* a long-"J" */
+  FID_mg_data = (*j_env)->GetFieldID(j_env, j_cls, "mg_data_ptr_", "J");
+  assert(FID_mg_data != NULL);
+
+  /* an object -"L<class name>;" */
+  FID_query_result = (*j_env)->GetFieldID(j_env, j_cls, "mg_query_result_",
+					  "Lorg/greenstone/mg/MGQueryResult;");
+  assert(FID_query_result != NULL);
+
+  /* the methods we want to use */
+  JC_MGQueryResult = (*j_env)->FindClass(j_env, "org/greenstone/mg/MGQueryResult");
+
+  /* addDoc(long doc, float rank) */
+  MID_addDoc = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "addDoc", "(JF)V");
+  assert(MID_addDoc != NULL);
+
+  /* addTerm(String term, int stem) */
+  MID_addTerm = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "addTerm", "(Ljava/lang/String;I)V");
+  assert(MID_addTerm != NULL);
+
+  /* addEquivTerm(String term, String equivTerm, long match, long freq) */
+  MID_addEquivTerm = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "addEquivTerm", "(Ljava/lang/String;Ljava/lang/String;JJ)V");
+  assert(MID_addEquivTerm != NULL);
+
+  /* setTotalDocs(long) */
+  MID_setTotalDocs = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "setTotalDocs", "(J)V");
+  assert(MID_setTotalDocs != NULL);
+
+  /* clear(void) */
+  MID_clearResult = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "clear", "()V");
+  assert(MID_clearResult != NULL);
+}
+
+
+/* the java side MGWrapper has a pointer to a C object - MGWrapperData
+   initialise this and set the pointer 
+*/
+JNIEXPORT jboolean JNICALL
+Java_org_greenstone_mg_MGWrapper_initCSide(JNIEnv *j_env, jobject j_obj)
+{
+  /* Allocate a MGWrapperData object to store query parameters */
+  MGWrapperData* data = (MGWrapperData*) malloc(sizeof(MGWrapperData));
+  assert(data != NULL);
+
+  /* Set default values - no stemming, no case-folding, boolean OR queries */
+  data->defaultStemMethod = 0;
+  data->defaultBoolCombine = 0;
+
+  /* Allocate a QueryInfo object to store more query parameters */
+  data->queryInfo = (QueryInfo*) malloc(sizeof(QueryInfo));
+  assert(data->queryInfo != NULL);
+
+  /* Set default values - 50 documents max, return term freqs, sort by rank */
+  data->queryInfo->index = NULL;
+  data->queryInfo->maxDocs = 50;
+  data->queryInfo->needTermFreqs = 1;
+
+  /* Save the object on the Java side */
+  (*j_env)->SetIntField(j_env, j_obj, FID_mg_data, (long) data);
+
+  /* Initialise MG environment variables */
+  InitEnv();
+  SetEnv("expert", "true", NULL);
+  SetEnv("mode", "docnums", NULL);
+  
+  return 1;  /* true - no errors */
+}
+
+
+/*******************************************
+   Index caching
+ *******************************************/
+
+query_data* cached_indexes[MAX_INDEXES_CACHED] = { NULL };
+
+
+/* Get the index data necessary to perform a query or document retrieval */
+query_data*
+loadIndexData(char* base_dir, char* index_path, char* text_path)
+{
+  char* index_path_name;
+  char* text_path_name;
+  query_data* qd;
+  int i = 0;
+
+  /* Form the path name of the desired indexes */
+  index_path_name = (char*) malloc(strlen(base_dir) + strlen(index_path) + 1);
+  assert(index_path_name != NULL);
+  strcpy(index_path_name, base_dir);
+  strcat(index_path_name, index_path);
+  printf("Index pathname: %s\n", index_path_name);
+
+  text_path_name = (char*) malloc(strlen(base_dir) + strlen(text_path) + 1);
+  assert(text_path_name != NULL);
+  strcpy(text_path_name, base_dir);
+  strcat(text_path_name, text_path);
+  printf("Text pathname: %s\n", text_path_name);
+
+  /* Search through the cached indexes for the desired one */
+  while (i < MAX_INDEXES_CACHED && cached_indexes[i] != NULL) {
+    printf("(Cached) Pathname: %s\n", cached_indexes[i]->pathname);
+    printf("(Cached) Textpathname: %s\n", cached_indexes[i]->textpathname);
+
+    /* Check if the index has already been loaded */
+    if ((strcmp(index_path_name, cached_indexes[i]->pathname) == 0) &&
+	(strcmp(text_path_name, cached_indexes[i]->textpathname) == 0)) {
+      /* Index has already been loaded and cached, so return it */
+      printf("Found index!\n");
+      free(index_path_name);
+      free(text_path_name);
+      return cached_indexes[i];
+    }
+
+    i++;
+  }
+
+  /* Text strings no longer needed */
+  free(index_path_name);
+  free(text_path_name);
+
+  /* The index is not cached, so load it now */
+  qd = InitQuerySystem(base_dir, index_path, text_path, NULL);
+  if (!qd) {
+    printf("Error: Could not InitQuerySystem()...\n");
+    return NULL;
+  }
+
+  /* The index loaded OK, so cache it */
+  /* This could be a little more sophisticated, eg. replace least frequently used index */
+  if (i >= MAX_INDEXES_CACHED)
+    i = MAX_INDEXES_CACHED - 1;
+
+  /* Free the index being replaced */
+  if (cached_indexes[i] != NULL)
+    FinishQuerySystem(cached_indexes[i]);
+
+  /* Cache the loaded index, and return it */
+  cached_indexes[i] = qd;
+  return cached_indexes[i];
+}
+
+
+/* Clean up by unloading all cached indexes */
+JNIEXPORT jboolean JNICALL
+Java_org_greenstone_mg_MGWrapper_unloadIndexData(JNIEnv* j_env, jobject j_obj)
+{
+  /* Free all the loaded indexes */
+  int i = 0;
+  while (i < MAX_INDEXES_CACHED && cached_indexes[i] != NULL) {
+    FinishQuerySystem(cached_indexes[i]);
+    cached_indexes[i] = NULL;
+    i++;
+  }
+
+  return 1;  /* true - no errors */
+}
+
+
+/****************************************************
+   retrieve a document
+ ****************************************************/
+
+/* Returns a document from mg as a string */
+JNIEXPORT jstring JNICALL
+Java_org_greenstone_mg_MGWrapper_getDocument(JNIEnv *j_env, jobject j_obj,
+					     jstring j_base_dir, jstring j_text_path,
+					     jlong j_docnum)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+
+  char* index_path;
+  const char* base_dir;
+  const char* text_path;
+  query_data* qd;
+
+  u_long pos, len;
+  u_char* c_buffer = NULL;
+  u_char* uc_buffer = NULL;
+  int ULen;
+
+  jstring result;
+
+  /* Make sure an index has been specified */
+  index_path = data->queryInfo->index;
+  assert(index_path != NULL);
+
+  /* Obtain C versions of the two string parameters */
+  base_dir = (*j_env)->GetStringUTFChars(j_env, j_base_dir, NULL);
+  if (base_dir == NULL) {
+    return NULL;
+  }
+  text_path = (*j_env)->GetStringUTFChars(j_env, j_text_path, NULL);
+  if (text_path == NULL) {
+    (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
+    return NULL;
+  }
+
+  /* Load the appropriate index for satisfying this request */
+  printf("Document retrieval, index path: %s\n", index_path);
+  qd = loadIndexData((char*) base_dir, (char*) index_path, (char*) text_path);
+
+  /* The C text strings are no longer needed */
+  (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
+  (*j_env)->ReleaseStringUTFChars(j_env, j_text_path, text_path);
+
+  /* Check that the index was loaded successfully */
+  if (qd==NULL) {
+    return NULL;
+  }
+  /*assert(qd != NULL);*/
+
+  /* Get the document position and length in the text file */
+  printf("Fetching document number %ld...\n", (unsigned long) j_docnum);
+  FetchDocStart(qd, (unsigned long) j_docnum, &pos, &len);
+  printf("Fetched document start. Pos: %ld, Len: %ld\n", pos, len);
+
+  /* Allocate memory for the document text (from mg/src/text/mgquery.c:RawDocOutput()) */
+  c_buffer = (u_char*) malloc(len);
+  assert(c_buffer != NULL);
+  uc_buffer = (u_char*) malloc((int) (qd->td->cth.ratio * 1.01 * len) + 100);
+  assert(uc_buffer != NULL);
+
+  /* Seek to the correct position in the file and read the document text */
+  Fseek (qd->td->TextFile, pos, 0);
+  Fread (c_buffer, 1, len, qd->td->TextFile);
+
+  /* Decompress the document text into another buffer, and terminate it */
+  DecodeText (qd->cd, c_buffer, len, uc_buffer, &ULen);
+  uc_buffer[ULen] = '\0';
+
+  /* Load the document text into a Java string */
+  result = (*j_env)->NewStringUTF(j_env, uc_buffer);
+  assert(result != NULL);
+
+  /* Free C buffers */
+  free(c_buffer);
+  free(uc_buffer);
+
+  /* Return the document text */
+  return result;
+}
+
+
+/*******************************************
+   do a query
+ *******************************************/
+
+/* do the actual query - the results are written to query_result held on the Java side */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGWrapper_runQuery(JNIEnv *j_env, jobject j_obj,
+					  jstring j_base_dir, jstring j_text_path,
+					  jstring j_query)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+
+  char* index_path;
+  const char* base_dir;
+  const char* text_path;
+  query_data* qd;
+
+  jobject result_ptr;
+  char* query;
+  int i, j;
+
+  jthrowable exc;
+  /* First of all, clear the previous result */
+  /* The result to write to */
+  result_ptr = (*j_env)->GetObjectField(j_env, j_obj, FID_query_result);
+  assert(result_ptr != NULL);
+
+  /* Clear any previous query results */
+  (*j_env)->CallVoidMethod(j_env, result_ptr, MID_clearResult);
+  exc = (*j_env)->ExceptionOccurred(j_env);
+  if (exc) {
+    (*j_env)->ExceptionDescribe(j_env);
+    return;
+  }
+
+  /* Make sure an index has been specified */
+  index_path = data->queryInfo->index;
+  if (index_path == NULL) {
+    return;
+  }
+
+  /* Obtain C versions of the two string parameters */
+  base_dir = (*j_env)->GetStringUTFChars(j_env, j_base_dir, NULL);
+  if (base_dir == NULL) {
+    return;
+  }
+  text_path = (*j_env)->GetStringUTFChars(j_env, j_text_path, NULL);
+  if (text_path == NULL) {
+    (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
+    return;
+  }
+
+  /* Load the appropriate index for satisfying this request */
+  qd = loadIndexData((char*) base_dir, (char*) index_path, (char*) text_path);
+
+  /* The C text strings are no longer needed */
+  (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
+  (*j_env)->ReleaseStringUTFChars(j_env, j_text_path, text_path);
+
+  /* Check that the index was loaded successfully */
+  if (qd == NULL) {
+    return;
+  }
+  
+  /* Remove anything hanging around from last time */
+  FreeQueryDocs(qd);
+
+  /* Obtain a C version of the query string */
+  query = (char*) (*j_env)->GetStringUTFChars(j_env, j_query, NULL);
+  if (query == NULL) {
+    return;
+  }
+  printf("Searching for query \"%s\"...\n", query);
+
+  /* Make sure the query isn't empty */
+  if (strlen(query) == 0) {
+    printf("Warning: Empty query.\n");
+    return;
+  }
+
+  /* "Some" queries are done as ranked queries */
+  if (data->defaultBoolCombine == 0) {
+    RankedQueryInfo rqi;
+    rqi.QueryFreqs = 1;  /* Use the frequency of each query term in the query - OK? */
+    rqi.Exact = 1;  /* Perform exact ranking */
+    rqi.MaxDocsToRetrieve = data->queryInfo->maxDocs;  /* Get only the desired number */
+    rqi.MaxParasToRetrieve = rqi.MaxDocsToRetrieve;  /* OK? */
+    /* we may need to get more paragraphs to get enough documents. I copied the following from mgquery. it seems to work, not sure why - kjdon */
+    if (qd->id->ifh.InvfLevel == 3 && GetEnv ("maxparas")) {
+      rqi.MaxParasToRetrieve = atoi (GetEnv ("maxparas"));
+    }
+    
+    rqi.Sort = 1;  /* Sort the query terms by frequency before ranking */
+    rqi.AccumMethod = 'L';  /* Use a list when accumulating (has bugs though...) */
+    /* rqi.MaxAccums = -1; */ /* Use as many accumulators as necessary - CRASHES with list */
+    rqi.MaxAccums = 100000;
+    rqi.MaxTerms = -1;  /* Use all the query terms */
+    /* rqi.StopAtMaxAccum = 0;*/  /* Don't care (using as many accumulators as necessary) */
+    rqi.StopAtMaxAccum = 1;
+    rqi.HashTblSize = 1000;  /* Don't care (not using a hash table) */
+    rqi.skip_dump = NULL;  /* Don't dump skip information */
+
+    /* RankedQuery() reads 'casefold' and 'stem' parameters from the environment */
+    SetEnv("casefold", ((data->defaultStemMethod & 1) ? "on" : "off"), NULL);
+    SetEnv("stem", ((data->defaultStemMethod & 2) ? "on" : "off"), NULL);
+
+    RankedQuery(qd, query, &rqi);
+  }
+  /* "All" queries are done as boolean queries */
+  else {
+    BooleanQueryInfo bqi;
+    bqi.MaxDocsToRetrieve = data->queryInfo->maxDocs;
+
+    /* Had to add "words$o" to LIB_OBJS in mg/src/text/Makefile and recompile mg for this */
+    BooleanQuery(qd, query, &bqi, data->defaultStemMethod);
+  }
+
+  /* Finished with the C query string */
+  (*j_env)->ReleaseStringUTFChars(j_env, j_query, query);
+
+  /* Check the query was processed successfully */
+  if (qd->DL == NULL || qd->QTL == NULL || qd->TL == NULL) {
+    return;
+  }
+
+  /* Record the total number of matching documents */
+  (*j_env)->CallVoidMethod(j_env, result_ptr, MID_setTotalDocs, (jlong) qd->DL->num);
+  exc = (*j_env)->ExceptionOccurred(j_env);
+  if (exc) {
+    (*j_env)->ExceptionDescribe(j_env);
+    return;
+  }
+
+  /* Record the matching documents, but only the number requested */
+  printf("Number of matching documents: %d\n", qd->DL->num);
+  
+  for (i = 0; (i < qd->DL->num && i < data->queryInfo->maxDocs); i++) {
+    int doc_num = qd->DL->DE[i].DocNum;
+    float doc_weight = qd->DL->DE[i].Weight;
+
+#if defined(PARADOCNUM) || defined(NZDL)
+    if (qd->id->ifh.InvfLevel == 3) {
+      /* pararaph level, need to convert to doc level*/
+      doc_num = GetDocNumFromParaNum(qd, doc_num);
+    }
+#endif
+    
+    
+    /* Call the addDoc function (Java side) to record a matching document */
+    (*j_env)->CallVoidMethod(j_env, result_ptr, MID_addDoc,
+			     (jlong) doc_num, (jfloat) doc_weight);
+    exc = (*j_env)->ExceptionOccurred(j_env);
+    if (exc) {
+      (*j_env)->ExceptionDescribe(j_env);
+      return;
+    }
+  }
+
+  /* Record the term information, if desired */
+  if (data->queryInfo->needTermFreqs) {
+    /* The following code is a lot more complicated than it could be, but it is necessary
+       to compensate for an oddity in MG. */
+    unsigned char** stemmed_terms = malloc(sizeof(unsigned char*) * qd->TL->num);
+
+    printf("Number of terms: %d\n", qd->TL->num);
+    printf("Number of query terms: %d\n", qd->QTL->num);
+
+    /* Generate the stemmed form of each of the relevant terms */
+    for (i = 0; i < qd->TL->num; i++) {
+      u_char* raw_term = qd->TL->TE[i].Word;
+      unsigned int term_length = raw_term[0];
+
+      u_char* raw_stemmed_term = malloc(term_length + 1);
+      unsigned int stemmed_term_length;
+
+      /* Copy the term, and stem it */
+      for (j = 0; j <= term_length; j++)
+	raw_stemmed_term[j] = raw_term[j];
+      stemmer(data->defaultStemMethod, qd->sd->sdh.stemmer_num, raw_stemmed_term);
+
+      /* Allocate memory to store the stemmed term, and fill it */
+      stemmed_term_length = raw_stemmed_term[0];
+      stemmed_terms[i] = malloc(stemmed_term_length + 1);
+      assert(stemmed_terms[i] != NULL);
+      strncpy(stemmed_terms[i], &(raw_stemmed_term[1]), stemmed_term_length);
+      stemmed_terms[i][stemmed_term_length] = '\0';
+    }
+
+    /* Record every query term, along with their equivalent terms */
+    for (i = 0; i < qd->QTL->num; i++) {
+      u_char* raw_query_term = qd->QTL->QTE[i].Term;
+      unsigned int query_term_length = raw_query_term[0];
+      unsigned char* query_term;
+      jstring j_query_term;
+
+      u_char* raw_stemmed_query_term = malloc(query_term_length + 1);
+      unsigned int stemmed_query_term_length;
+      unsigned char* stemmed_query_term;
+
+      /* Allocate memory to store the query term, and fill it */
+      query_term = malloc(query_term_length + 1);
+      assert(query_term != NULL);
+      strncpy(query_term, &(raw_query_term[1]), query_term_length);
+      query_term[query_term_length] = '\0';
+
+      /* Allocate a new jstring for the query term */
+      j_query_term = (*j_env)->NewStringUTF(j_env, query_term);
+      assert(j_query_term != NULL);
+
+      /* Call the addTerm function (Java side) to record the query term */
+      (*j_env)->CallVoidMethod(j_env, result_ptr, MID_addTerm,
+			       j_query_term, (jint) data->defaultStemMethod);
+      exc = (*j_env)->ExceptionOccurred(j_env);
+      if (exc) {
+	(*j_env)->ExceptionDescribe(j_env);
+	return;
+      }
+
+      /* Copy the query term, and stem it */
+      for (j = 0; j <= query_term_length; j++)
+	raw_stemmed_query_term[j] = raw_query_term[j];
+      stemmer(data->defaultStemMethod, qd->sd->sdh.stemmer_num, raw_stemmed_query_term);
+
+      /* Allocate memory to store the stemmed query term, and fill it */
+      stemmed_query_term_length = raw_stemmed_query_term[0];
+      stemmed_query_term = malloc(stemmed_query_term_length + 1);
+      assert(stemmed_query_term != NULL);
+      strncpy(stemmed_query_term, &(raw_stemmed_query_term[1]), stemmed_query_term_length);
+      stemmed_query_term[stemmed_query_term_length] = '\0';
+
+      /* Find all the terms equivalent to the query term */
+      for (j = 0; j < qd->TL->num; j++) {
+	/* Check if the stemmed query term matches the stemmed term */
+	if (strcmp(stemmed_query_term, stemmed_terms[j]) == 0) {
+	  u_char* raw_term = qd->TL->TE[j].Word;
+	  unsigned int term_length = raw_term[0];
+	  unsigned char* term;
+	  jstring j_term;
+
+	  /* Allocate memory to store the query term, and fill it */
+	  term = malloc(term_length + 1);
+	  assert(term != NULL);
+	  strncpy(term, &(raw_term[1]), term_length);
+	  term[term_length] = '\0';
+
+	  /* Allocate a new jstring for the query term */
+	  j_term = (*j_env)->NewStringUTF(j_env, term);
+	  assert(j_term != NULL);
+
+	  /* Call the addEquivTerm function (Java side) to record the equivalent term */
+	  (*j_env)->CallVoidMethod(j_env, result_ptr, MID_addEquivTerm,
+				   j_query_term, j_term,
+				   (jlong) qd->TL->TE[j].WE.doc_count,
+				   (jlong) qd->TL->TE[j].WE.count);
+	  exc = (*j_env)->ExceptionOccurred(j_env);
+	  if (exc) {
+	    (*j_env)->ExceptionDescribe(j_env);
+	    return;
+	  }
+	}
+      }
+    }
+  }
+}
+
+
+/*******************************************
+   set query options
+ *******************************************/
+
+/* Turn casefolding on or off */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGWrapper_setCase(JNIEnv *j_env, jobject j_obj, 
+					 jboolean j_on)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+
+  if (j_on) {
+    data->defaultStemMethod |= 1;
+  } else {
+    data->defaultStemMethod &= 0xe;
+  }
+}
+
+
+/* Turn stemming on or off */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGWrapper_setStem(JNIEnv *j_env, jobject j_obj, 
+					 jboolean j_on)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+
+  if (j_on) {
+    data->defaultStemMethod |= 2;
+  } else {
+    data->defaultStemMethod &= 0xd;
+  }
+}
+
+
+/* Set the maximum number of documents to return from a query */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGWrapper_setMaxDocs(JNIEnv *j_env, jobject j_obj, 
+					    jint j_max)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+  data->queryInfo->maxDocs = j_max;
+}
+
+/* set the maximum number of numeric to split*/
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mg_MGWrapper_setMaxNumeric (JNIEnv *j_env, 
+						 jobject j_obj, 
+						 jint j_max) {
+
+  char text[20];
+  char* maxnumeric;
+  sprintf(text,"%d",j_max); 
+  maxnumeric = text;  
+  SetEnv("maxnumeric",maxnumeric, NULL);
+}
+
+
+/* Turn term frequency recording on or off */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGWrapper_setReturnTerms(JNIEnv *j_env, jobject j_obj, 
+						jboolean j_on)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+  data->queryInfo->needTermFreqs = j_on;
+}
+
+
+/* Choose MG index to search */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mg_MGWrapper_setIndex(JNIEnv *j_env, jobject j_obj,
+					  jstring j_index)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+
+  /* Get the index name as a C string */
+  const char* index = (*j_env)->GetStringUTFChars(j_env, j_index, NULL);
+  assert(index != NULL);
+  printf("Choosing index %s...\n", index);
+
+  /* Free the previous index name */
+  if (data->queryInfo->index)
+    free(data->queryInfo->index);
+
+  /* Allocate memory for the index name, and fill it */
+  data->queryInfo->index = (char*) malloc(strlen(index) + 1);
+  assert(data->queryInfo->index != NULL);
+  strcpy(data->queryInfo->index, index);
+
+  /* Release the index string */
+  (*j_env)->ReleaseStringUTFChars(j_env, j_index, index);
+}
+
+
+/* Choose boolean AND or boolean OR queries */
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mg_MGWrapper_setMatchMode(JNIEnv *j_env, jobject j_obj,
+					      jint j_mode)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+  data->defaultBoolCombine = j_mode;
+}
+
+
+/* Get a text representation of the current parameter values */
+JNIEXPORT jstring JNICALL
+Java_org_greenstone_mg_MGWrapper_getQueryParams(JNIEnv *j_env, jobject j_obj)
+{
+  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
+  char result[512];  /* Assume this is big enough */
+
+  /* Print the data to a character array */
+  sprintf(result, "Query params:\nindex\t\t%s\ncasefold\t%d\nstem\t\t%d\nquery type\t%s\nmax docs\t%ld\n",
+	  (data->queryInfo->index == NULL ? "<none loaded>" : data->queryInfo->index),
+	  (data->defaultStemMethod & 1),
+	  (data->defaultStemMethod & 2),
+	  (data->defaultBoolCombine == 1 ? "all" : "some"),
+	  (data->queryInfo->maxDocs));
+
+  /* Convert to a jstring, and return */
+  return (*j_env)->NewStringUTF(j_env, result);
+}
Index: /indexers/branches/3.03a/mg/jni/MGWrapperImpl.h
===================================================================
--- /indexers/branches/3.03a/mg/jni/MGWrapperImpl.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/jni/MGWrapperImpl.h	(revision 14757)
@@ -0,0 +1,52 @@
+/*
+ *    MGWrapperImpl.h
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "backend.h"
+
+
+/*************************************************************************
+   NOTES
+
+ - These data structures are based on the MGPP ones but are modified
+   to reflect the different capabilities of the MG system.
+
+ *************************************************************************/
+
+ 
+typedef struct QueryInfo
+{
+  /* Name of index to use */
+  char* index;
+  /* Maximum number of documents to retrieve */
+  unsigned long maxDocs;
+  /* Whether term frequency information is desired (boolean value) */
+  int needTermFreqs;
+} QueryInfo;
+
+
+typedef struct MGWrapperData
+{
+  /* Information about a query, see above */
+  QueryInfo* queryInfo;
+  /* Whether to perform stemming and case-folding */
+  int defaultStemMethod;
+  /* Whether to perform boolean AND (1) or boolean OR (0) queries */
+  int defaultBoolCombine;
+} MGWrapperData;
Index: /indexers/branches/3.03a/mg/jni/Makefile.in
===================================================================
--- /indexers/branches/3.03a/mg/jni/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/mg/jni/Makefile.in	(revision 14757)
@@ -0,0 +1,68 @@
+
+SHELL = /bin/sh
+VPATH = @srcdir@
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+bindir = @bindir@
+srcdir = @srcdir@
+libdir = @libdir@
+subdir = jni
+top_srcdir = @top_srcdir@
+transform = @program_transform_name@
+
+AR = ar
+CC = @CC@
+CFLAGS = @CFLAGS@ -ansi -fpic -DSILENT -DSHORT_SUFFIX -DNZDL -DQUIET -DPARADOCNUM
+DEFS = @DEFS@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LDFLAGS = @LDFLAGS@
+#NOTE: libmgtext.a needs to come before libmglib.a !!!
+QUERY_LIBS = ../src/text/libmgtext.a ../lib/libmglib.a @LIBS@
+PASSES_LIBS = ../src/text/libmgpass.a ../lib/libmglib.a @LIBS@
+TOUCH = echo timestamp >
+AWK = @AWK@
+
+JNIFLAGS=@JNIFLAGS@
+JNISUFFIX=@JNISUFFIX@
+JNIINC=@JNIINC@
+datadir = $(prefix)/share
+libexecdir = $(exec_prefix)/libexec
+localedir = $(datadir)/locale
+mandir = $(prefix)/man/man1
+
+CCOMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CFLAGS)
+
+.SUFFIXES:
+
+.SUFFIXES: .c .o
+.c.o:
+	$(CCOMPILE) $<
+
+# can we get rid of JAVA_HOME from here??
+INCLUDES = -I.. -I../lib -I../src/text -I$(JAVA_HOME)/include $(JNIINC)
+
+all: compile link
+
+compile:
+	$(CCOMPILE) MGSearchWrapperImpl.c MGRetrieveWrapperImpl.c MGPassesWrapperImpl.c
+
+link:
+	$(CC) $(LDFLAGS) $(JNIFLAGS) -o libmgretrievejni.$(JNISUFFIX) MGRetrieveWrapperImpl.o $(QUERY_LIBS)
+	$(CC) $(LDFLAGS) $(JNIFLAGS) -o libmgsearchjni.$(JNISUFFIX) MGSearchWrapperImpl.o $(QUERY_LIBS)
+	$(CC) $(LDFLAGS)  $(JNIFLAGS) -o libmgpassjni.$(JNISUFFIX)  MGPassesWrapperImpl.o  $(PASSES_LIBS)
+
+clean:
+	rm -rf *.o libmgretrievejni.$(JNISUFFIX) libmgsearchjni.$(JNISUFFIX) libmgpassjni.$(JNISUFFIX) 
+
+distclean: clean
+	rm -f Makefile
+
+install:
+#	../mkinstalldirs $(libdir); \
+#	cp libmgjni.$(JNISUFFIX) libmgpassjni.$(JNISUFFIX)  $(libdir)/;
+
+
+
Index: /indexers/branches/3.03a/mg/jni/org_greenstone_mg_MGPassesWrapper.h
===================================================================
--- /indexers/branches/3.03a/mg/jni/org_greenstone_mg_MGPassesWrapper.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/jni/org_greenstone_mg_MGPassesWrapper.h	(revision 14757)
@@ -0,0 +1,175 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_greenstone_mg_MGPassesWrapper */
+
+#ifndef _Included_org_greenstone_mg_MGPassesWrapper
+#define _Included_org_greenstone_mg_MGPassesWrapper
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef org_greenstone_mg_MGPassesWrapper_INVF_LEVEL_1
+#define org_greenstone_mg_MGPassesWrapper_INVF_LEVEL_1 49L
+#undef org_greenstone_mg_MGPassesWrapper_INVF_LEVEL_2
+#define org_greenstone_mg_MGPassesWrapper_INVF_LEVEL_2 50L
+#undef org_greenstone_mg_MGPassesWrapper_INVF_LEVEL_3
+#define org_greenstone_mg_MGPassesWrapper_INVF_LEVEL_3 51L
+#undef org_greenstone_mg_MGPassesWrapper_TEXT_PASS_1
+#define org_greenstone_mg_MGPassesWrapper_TEXT_PASS_1 0L
+#undef org_greenstone_mg_MGPassesWrapper_TEXT_PASS_2
+#define org_greenstone_mg_MGPassesWrapper_TEXT_PASS_2 1L
+#undef org_greenstone_mg_MGPassesWrapper_INDEX_PASS_1
+#define org_greenstone_mg_MGPassesWrapper_INDEX_PASS_1 2L
+#undef org_greenstone_mg_MGPassesWrapper_INDEX_PASS_2
+#define org_greenstone_mg_MGPassesWrapper_INDEX_PASS_2 3L
+#undef org_greenstone_mg_MGPassesWrapper_SPECIAL_PASS
+#define org_greenstone_mg_MGPassesWrapper_SPECIAL_PASS 4L
+#undef org_greenstone_mg_MGPassesWrapper_NO_STEM_OR_CASE
+#define org_greenstone_mg_MGPassesWrapper_NO_STEM_OR_CASE 0L
+#undef org_greenstone_mg_MGPassesWrapper_CASE_ONLY
+#define org_greenstone_mg_MGPassesWrapper_CASE_ONLY 1L
+#undef org_greenstone_mg_MGPassesWrapper_STEM_ONLY
+#define org_greenstone_mg_MGPassesWrapper_STEM_ONLY 2L
+#undef org_greenstone_mg_MGPassesWrapper_STEM_AND_CASE
+#define org_greenstone_mg_MGPassesWrapper_STEM_AND_CASE 3L
+#undef org_greenstone_mg_MGPassesWrapper_END_OF_DOCUMENT
+#define org_greenstone_mg_MGPassesWrapper_END_OF_DOCUMENT 2L
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    init
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mg_MGPassesWrapper_init
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    setBasePath
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGPassesWrapper_setBasePath
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    setFileName
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGPassesWrapper_setFileName
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    setStemOptions
+ * Signature: (Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGPassesWrapper_setStemOptions
+  (JNIEnv *, jobject, jstring, jint);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    setInvfLevel
+ * Signature: (C)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGPassesWrapper_setInvfLevel
+  (JNIEnv *, jobject, jchar);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    setBufferSize
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGPassesWrapper_setBufferSize
+  (JNIEnv *, jobject, jlong);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    setInversionMemLimit
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGPassesWrapper_setInversionMemLimit
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    ignoreSGMLTags
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGPassesWrapper_ignoreSGMLTags
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    dumpFailedDocument
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGPassesWrapper_dumpFailedDocument
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    outputCompStats
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGPassesWrapper_outputCompStats
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    enableTracing
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGPassesWrapper_enableTracing
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    finish
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mg_MGPassesWrapper_finish
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    exitValue
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_greenstone_mg_MGPassesWrapper_exitValue
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGPassesWrapper_initIDs
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    initCSide
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mg_MGPassesWrapper_initCSide
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    addPass
+ * Signature: (CC)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGPassesWrapper_addPass
+  (JNIEnv *, jobject, jchar, jchar);
+
+/*
+ * Class:     org_greenstone_mg_MGPassesWrapper
+ * Method:    processMGDocument
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mg_MGPassesWrapper_processMGDocument
+  (JNIEnv *, jobject, jbyteArray);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: /indexers/branches/3.03a/mg/jni/org_greenstone_mg_MGRetrieveWrapper.h
===================================================================
--- /indexers/branches/3.03a/mg/jni/org_greenstone_mg_MGRetrieveWrapper.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/jni/org_greenstone_mg_MGRetrieveWrapper.h	(revision 14757)
@@ -0,0 +1,53 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_greenstone_mg_MGRetrieveWrapper */
+
+#ifndef _Included_org_greenstone_mg_MGRetrieveWrapper
+#define _Included_org_greenstone_mg_MGRetrieveWrapper
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_greenstone_mg_MGRetrieveWrapper
+ * Method:    initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGRetrieveWrapper_initIDs
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     org_greenstone_mg_MGRetrieveWrapper
+ * Method:    initCSide
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mg_MGRetrieveWrapper_initCSide
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mg_MGRetrieveWrapper
+ * Method:    getDocument
+ * Signature: (Ljava/lang/String;Ljava/lang/String;J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_greenstone_mg_MGRetrieveWrapper_getDocument
+  (JNIEnv *, jobject, jstring, jstring, jlong);
+
+/*
+ * Class:     org_greenstone_mg_MGRetrieveWrapper
+ * Method:    unloadIndexData
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mg_MGRetrieveWrapper_unloadIndexData
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mg_MGRetrieveWrapper
+ * Method:    setIndex
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGRetrieveWrapper_setIndex
+  (JNIEnv *, jobject, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: /indexers/branches/3.03a/mg/jni/org_greenstone_mg_MGSearchWrapper.h
===================================================================
--- /indexers/branches/3.03a/mg/jni/org_greenstone_mg_MGSearchWrapper.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/jni/org_greenstone_mg_MGSearchWrapper.h	(revision 14757)
@@ -0,0 +1,109 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_greenstone_mg_MGSearchWrapper */
+
+#ifndef _Included_org_greenstone_mg_MGSearchWrapper
+#define _Included_org_greenstone_mg_MGSearchWrapper
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_greenstone_mg_MGSearchWrapper
+ * Method:    initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGSearchWrapper_initIDs
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     org_greenstone_mg_MGSearchWrapper
+ * Method:    initCSide
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mg_MGSearchWrapper_initCSide
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mg_MGSearchWrapper
+ * Method:    unloadIndexData
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mg_MGSearchWrapper_unloadIndexData
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mg_MGSearchWrapper
+ * Method:    setCase
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGSearchWrapper_setCase
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mg_MGSearchWrapper
+ * Method:    setStem
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGSearchWrapper_setStem
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mg_MGSearchWrapper
+ * Method:    setMaxDocs
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGSearchWrapper_setMaxDocs
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mg_MGSearchWrapper
+ * Method:    setReturnTerms
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGSearchWrapper_setReturnTerms
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mg_MGSearchWrapper
+ * Method:    setIndex
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGSearchWrapper_setIndex
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mg_MGSearchWrapper
+ * Method:    setMatchMode
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGSearchWrapper_setMatchMode
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mg_MGSearchWrapper
+ * Method:    getQueryParams
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_greenstone_mg_MGSearchWrapper_getQueryParams
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mg_MGSearchWrapper
+ * Method:    setMaxNumeric
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGSearchWrapper_setMaxNumeric
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mg_MGSearchWrapper
+ * Method:    runQuery
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGSearchWrapper_runQuery
+  (JNIEnv *, jobject, jstring, jstring, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: /indexers/branches/3.03a/mg/jni/org_greenstone_mg_MGWrapper.h
===================================================================
--- /indexers/branches/3.03a/mg/jni/org_greenstone_mg_MGWrapper.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/jni/org_greenstone_mg_MGWrapper.h	(revision 14757)
@@ -0,0 +1,117 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_greenstone_mg_MGWrapper */
+
+#ifndef _Included_org_greenstone_mg_MGWrapper
+#define _Included_org_greenstone_mg_MGWrapper
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGWrapper_initIDs
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    initCSide
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mg_MGWrapper_initCSide
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    getDocument
+ * Signature: (Ljava/lang/String;Ljava/lang/String;J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_greenstone_mg_MGWrapper_getDocument
+  (JNIEnv *, jobject, jstring, jstring, jlong);
+
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    unloadIndexData
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mg_MGWrapper_unloadIndexData
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    setCase
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGWrapper_setCase
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    setStem
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGWrapper_setStem
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    setMaxDocs
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGWrapper_setMaxDocs
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    setReturnTerms
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGWrapper_setReturnTerms
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    setIndex
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGWrapper_setIndex
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    setMatchMode
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGWrapper_setMatchMode
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    getQueryParams
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_greenstone_mg_MGWrapper_getQueryParams
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    setMaxNumeric
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGWrapper_setMaxNumeric
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mg_MGWrapper
+ * Method:    runQuery
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mg_MGWrapper_runQuery
+  (JNIEnv *, jobject, jstring, jstring, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: /indexers/branches/3.03a/mg/jni/win32.mak
===================================================================
--- /indexers/branches/3.03a/mg/jni/win32.mak	(revision 14757)
+++ /indexers/branches/3.03a/mg/jni/win32.mak	(revision 14757)
@@ -0,0 +1,88 @@
+###########################################################################
+#
+# win32 makefile -- mg\jni
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999  The New Zealand Digital Library Project
+#
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+ 
+MGHOME = ..
+
+AR = lib
+CC = cl
+CPPFLAGS = 
+
+DEFS = -DQUIET -DHAVE_CONFIG_H -D__WIN32__ -D_LITTLE_ENDIAN -DPARADOCNUM \
+       -DSHORT_SUFFIX
+INCLUDES = -I"$(MGHOME)" -I"$(MGHOME)\lib" -I"$(MGHOME)\src\text" \
+           -I"$(JAVA_HOME)\include" -I"$(JAVA_HOME)\include\win32"           
+
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES)
+ 
+.SUFFIXES:
+.SUFFIXES: .c .obj
+.c.obj:
+	$(COMPILE) $<
+
+ANSI2KNR = 
+o = .obj
+ 
+HEADERS = \
+    MGSearchWrapperImpl.h   org_greenstone_mg_MGSearchWrapper.h  \
+    MGRetrieveWrapperImpl.h   org_greenstone_mg_MGRetrieveWrapper.h  \
+    org_greenstone_mg_MGPassesWrapper.h
+
+
+SOURCES = \
+    MGSearchWrapperImpl.c MGRetrieveWrapperImpl.c MGPassesWrapperImpl.c
+
+SEARCHOBJECTS = \
+    MGSearchWrapperImpl$o $(MGHOME)\src\text\libmgtext.lib \
+    $(MGHOME)\lib\libmglib.lib
+
+RETRIEVEOBJECTS = \
+    MGRetrieveWrapperImpl$o  $(MGHOME)\src\text\libmgtext.lib \
+    $(MGHOME)\lib\libmglib.lib
+
+PASSES_OBJECTS = \
+    MGPassesWrapperImpl$o   $(MGHOME)\src\text\libmgpass.lib \
+    $(MGHOME)\lib\libmglib.lib
+
+DISTFILES = Makefile.in $(HEADERS) $(SOURCES)
+ 
+all : compile link
+
+compile:
+        $(COMPILE) MGSearchWrapperImpl.c MGRetrieveWrapperImpl.c MGPassesWrapperImpl.c
+
+link:
+        $(CC) -MD -LD $(SEARCHOBJECTS) -Femgsearchjni.dll
+	  $(CC) -MD -LD $(RETRIEVEOBJECTS) -Femgretrievejni.dll
+        $(CC) -MD -LD $(PASSES_OBJECTS) -Femgpassjni.dll
+
+
+install: 
+
+clean:
+        if exist *$o del *$o 
+	if exist mgsearchjni.dll del mgsearchjni.dll
+	if exist mgretrievejni.dll del mgretrievejni.dll
+	if exist mgpassjni.dll del mgpassjni.dll
Index: /indexers/branches/3.03a/mg/lib/GCC.mak
===================================================================
--- /indexers/branches/3.03a/mg/lib/GCC.mak	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/GCC.mak	(revision 14757)
@@ -0,0 +1,84 @@
+###########################################################################
+#
+# gcc win32 makefile -- mg\lib
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2000  The New Zealand Digital Library Project
+#
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+AR = ar
+RANLIB = ranlib
+CC = gcc
+DELETE = del
+
+CPPFLAGS = -g
+DEFS = -DQUIET -DHAVE_CONFIG_H -D__WIN32__ -D_LITTLE_ENDIAN
+INCLUDES = -I".." -I"."
+
+o = .o
+ 
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS)
+ 
+.SUFFIXES:
+.SUFFIXES: .c $o
+.c$o:
+	$(COMPILE) $<
+
+
+HEADERS = \
+    bitio_m_random.h filestats.h local_strings.h lovinstem.h \
+    bitio_m_stdio.h getopt.h memlib.h bitio_gen.h bitio_mem.h \
+    mgheap.h messages.h bitio_m.h bitio_mems.h huffman.h \
+    timing.h bitio_m_mem.h bitio_random.h huffman_mem.h \
+    perf_hash.h bitio_m_mems.h bitio_stdio.h huffman_stdio.h \
+    sptree.h rx.h pathmax.h getpagesize.h random.h \
+    win32in.h simplefrenchstem.h unitool.h
+
+SOURCES = \
+    bitio_random.c mgheap.c memlib.c bitio_stdio.c huffman.c \
+    messages.c bitio_gen.c filestats.c huffman_mem.c \
+    perf_hash.c bitio_mem.c getopt.c huffman_stdio.c \
+    sptree.c bitio_mems.c getopt1.c local_strings.c \
+    lovinstem.c timing.c rx.c alloca.c error.c xmalloc.c \
+    strstr.c ftruncate.c strcasecmp.c random.c win32in.c \
+    simplefrenchstem.c unitool.h
+
+OBJECTS = \
+    rx$o bitio_random$o mgheap$o memlib$o bitio_stdio$o \
+    huffman$o messages$o bitio_gen$o filestats$o huffman_mem$o \
+    perf_hash$o bitio_mem$o getopt$o huffman_stdio$o sptree$o \
+    bitio_mems$o getopt1$o local_strings$o lovinstem$o \
+    timing$o error$o xmalloc$o random$o win32in$o \
+    simplefrenchstem$o unitool$o
+ 
+all : libmg.a
+
+libmg.a : $(OBJECTS)
+	$(DELETE) libmg.a
+	$(AR) cru libmg.a $(OBJECTS)
+	$(RANLIB) libmg.a
+
+install: 
+ 
+clean: 
+	$(DELETE) *$o
+	$(DELETE) libmg.a
Index: /indexers/branches/3.03a/mg/lib/Makefile.in
===================================================================
--- /indexers/branches/3.03a/mg/lib/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/Makefile.in	(revision 14757)
@@ -0,0 +1,173 @@
+###########################################################################
+#
+# Makefile.in -- Makefile for the general purpose library
+# Copyright (C) 1994  Neil Sharman; (C) 1995 Tim Shimmin
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#       @(#)Makefile.in	1.3 16 Mar 1994
+#
+###########################################################################
+
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+ 
+SHELL = /bin/sh
+srcdir = @srcdir@
+subdir = lib
+VPATH = @srcdir@
+ 
+AR = ar
+CC = @CC@
+CFLAGS = @CFLAGS@ -fpic 
+DEFS = @DEFS@
+RANLIB = @RANLIB@
+
+##########################################
+# Uncomment for compiling for the nzdl project
+#
+CFLAGS = @CFLAGS@ -DQUIET -fpic
+##########################################
+
+ 
+prefix = @prefix@
+datadir = $(prefix)/share
+localedir = $(datadir)/locale
+ 
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CFLAGS)
+ 
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+	$(COMPILE) $<
+
+ANSI2KNR = @ANSI2KNR@
+o = .@U@o
+ 
+.SUFFIXES: ._c ._o
+.c._c:
+	./ansi2knr $< > $*.tmp && mv $*.tmp $@
+._c._o:
+	@echo $(COMPILE) $<
+	@rm -f _$*.c
+	@ln $< _$*.c && $(COMPILE) _$*.c && mv _$*.o $@ && rm _$*.c
+.c._o:
+	./ansi2knr $< > $*.tmp && mv $*.tmp $*._c
+	@echo $(COMPILE) $*._c
+	@rm -f _$*.c
+	@ln $*._c _$*.c && $(COMPILE) _$*.c && mv _$*.o $@ && rm _$*.c
+
+ 
+INCLUDES = -I../../.. -I.. -I$(srcdir)
+ 
+HEADERS = \
+    bitio_m_random.h   filestats.h        local_strings.h    lovinstem.h \
+    bitio_m_stdio.h    getopt.h           memlib.h \
+    bitio_gen.h        bitio_mem.h        mgheap.h             messages.h \
+    bitio_m.h          bitio_mems.h       huffman.h          timing.h \
+    bitio_m_mem.h      bitio_random.h     huffman_mem.h      perf_hash.h \
+    bitio_m_mems.h     bitio_stdio.h      huffman_stdio.h    sptree.h \
+    pathmax.h          getpagesize.h \
+    random.h           simplefrenchstem.h unitool.h  longlong.h
+# regex.h            rx.h               
+
+
+SOURCES = \
+    bitio_random.c    mgheap.c            memlib.c \
+    bitio_stdio.c     huffman.c         messages.c \
+    bitio_gen.c       filestats.c       huffman_mem.c     perf_hash.c \
+    bitio_mem.c       getopt.c          huffman_stdio.c   sptree.c \
+    bitio_mems.c      getopt1.c         local_strings.c   lovinstem.c \
+    timing.c  \
+    alloca.c          error.c           xmalloc.c         strstr.c \
+    gmalloc.c         ftruncate.c       strcasecmp.c      random.c \
+    simplefrenchstem.c                  unitool.c
+# regex.c           rx.c              
+
+OBJECTS = @ALLOCA@ @LIBOBJS@ \
+    bitio_random$o    mgheap$o            memlib$o \
+    bitio_stdio$o     huffman$o         messages$o \
+    bitio_gen$o       filestats$o       huffman_mem$o     perf_hash$o \
+    bitio_mem$o       getopt$o          huffman_stdio$o   sptree$o \
+    bitio_mems$o      getopt1$o         local_strings$o   lovinstem$o \
+    timing$o \
+    error$o           xmalloc$o \
+    random$o          simplefrenchstem$o \
+    unitool$o
+#   gmalloc$o regex$o		rx$o 
+
+LIB_OBJECTS =   \
+    bitio_random$o    mgheap$o            memlib$o \
+    bitio_stdio$o     huffman$o          \
+    bitio_gen$o       filestats$o       huffman_mem$o     perf_hash$o \
+    bitio_mem$o       getopt$o          huffman_stdio$o   sptree$o \
+    bitio_mems$o      getopt1$o         local_strings$o   lovinstem$o \
+    timing$o \
+    error$o           xmalloc$o \
+    random$o          simplefrenchstem$o \
+    unitool$o
+
+
+DISTFILES = Makefile.in $(HEADERS) $(SOURCES)
+ 
+all : libmglib.a gsdllibmg.a
+
+libmglib.a : $(OBJECTS)
+	rm -f libmglib.a
+	$(AR) cru libmglib.a $(OBJECTS)
+	$(RANLIB) libmglib.a
+
+$(OBJECTS): ../config.h
+
+gsdllibmg.a: $(LIB_OBJECTS)
+	rm -f gsdllibmg.a
+	$(AR) cru gsdllibmg.a $(LIB_OBJECTS)
+	$(RANLIB) gsdllibmg.a
+ 
+
+install: 
+installdirs:
+uninstall:
+execinstall:
+execuninstall:
+maninstall:
+manuninstall:
+ 
+dist: $(DISTFILES)
+	for file in $(DISTFILES); do \
+	  ln $$file $(distdir) 2> /dev/null \
+	  || cp -p $$file $(distdir); \
+	done
+
+mostlyclean:
+	rm -f *.o *_.o
+ 
+clean: mostlyclean
+	rm -f libmglib.a gsdllibmg.a
+ 
+distclean: clean
+	rm -f Makefile
+ 
+maintainer-clean: distclean
+	@echo "This command is intended only for maintainers to use;"
+	@echo "rebuilding the deleted files may require special tools."
+
+#Makefile: Makefile.in ../../../config.status
+#	cd ../../.. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
+ 
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /indexers/branches/3.03a/mg/lib/WIN32.MAK
===================================================================
--- /indexers/branches/3.03a/mg/lib/WIN32.MAK	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/WIN32.MAK	(revision 14757)
@@ -0,0 +1,91 @@
+###########################################################################
+#
+# win32 makefile -- mg\lib
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999  The New Zealand Digital Library Project
+#
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+ 
+MGHOME = ..
+
+AR = lib
+CC = cl
+CPPFLAGS = 
+
+DEFS = -DQUIET -DHAVE_CONFIG_H -D__WIN32__ -D_LITTLE_ENDIAN -DPARADOCNUM \
+       -DSHORT_SUFFIX
+
+INCLUDES = -I"." -I"$(MGHOME)"
+
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES)
+ 
+.SUFFIXES: .c .obj
+.c.obj:
+	$(COMPILE) $<
+
+o = .obj
+ 
+HEADERS = \
+    bitio_m_random.h   filestats.h        local_strings.h    lovinstem.h \
+    bitio_m_stdio.h    getopt.h           memlib.h \
+    bitio_gen.h        bitio_mem.h        mgheap.h             messages.h \
+    bitio_m.h          bitio_mems.h       huffman.h          timing.h \
+    bitio_m_mem.h      bitio_random.h     huffman_mem.h      perf_hash.h \
+    bitio_m_mems.h     bitio_stdio.h      huffman_stdio.h    sptree.h \
+                       rx.h               pathmax.h          getpagesize.h \
+    random.h           win32in.h          simplefrenchstem.h unitool.h \
+    longlong.h	
+
+SOURCES = \
+    bitio_random.c    mgheap.c          memlib.c \
+    bitio_stdio.c     huffman.c         messages.c \
+    bitio_gen.c       filestats.c       huffman_mem.c     perf_hash.c \
+    bitio_mem.c       getopt.c          huffman_stdio.c   sptree.c \
+    bitio_mems.c      getopt1.c         local_strings.c   lovinstem.c \
+    timing.c                            rx.c              \
+    alloca.c          error.c           xmalloc.c         strstr.c \
+    ftruncate.c       strcasecmp.c      random.c          win32in.c \
+    simplefrenchstem.c                  unitool.h
+
+OBJECTS =   rx$o \
+    bitio_random$o    mgheap$o            memlib$o \
+    bitio_stdio$o     huffman$o         messages$o \
+    bitio_gen$o       filestats$o       huffman_mem$o     perf_hash$o \
+    bitio_mem$o       getopt$o          huffman_stdio$o   sptree$o \
+    bitio_mems$o      getopt1$o         local_strings$o   lovinstem$o \
+    timing$o           \
+    error$o           xmalloc$o \
+    random$o          win32in$o         simplefrenchstem$o \
+    unitool$o
+ 
+DISTFILES = Makefile.in $(HEADERS) $(SOURCES)
+ 
+all : libmglib.lib
+
+libmglib.lib : $(OBJECTS)
+        if exist libmglib.lib del libmglib.lib
+	$(AR) /out:libmglib.lib $(OBJECTS)
+
+install: 
+
+clean:
+        if exist *$o del *$o 
+        if exist libmglib.lib del libmglib.lib
Index: /indexers/branches/3.03a/mg/lib/alloca.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/alloca.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/alloca.c	(revision 14757)
@@ -0,0 +1,496 @@
+/* alloca.c -- allocate automatically reclaimed memory
+   (Mostly) portable public-domain implementation -- D A Gwyn
+
+   This implementation of the PWB library alloca function,
+   which is used to allocate space off the run-time stack so
+   that it is automatically reclaimed upon procedure exit,
+   was inspired by discussions with J. Q. Johnson of Cornell.
+   J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+   There are some preprocessor constants that can
+   be defined when compiling for your specific system, for
+   improved efficiency; however, the defaults should be okay.
+
+   The general concept of this implementation is to keep
+   track of all alloca-allocated blocks, and reclaim any
+   that are found to be deeper in the stack than the current
+   invocation.  This heuristic does not reclaim storage as
+   soon as it becomes invalid, but it will do so eventually.
+
+   As a special case, alloca(0) reclaims storage without
+   allocating any.  It is a good idea to use alloca(0) in
+   your main control loop, etc. to force garbage collection.  */
+
+#ifdef HAVE_CONFIG_H
+# ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+#  include <win32cfg.h>
+# else
+#  include <sysfuncs.h>
+# endif
+#endif
+
+#ifdef emacs
+#include "blockinput.h"
+#endif
+
+/* If compiling with GCC 2, this file's not needed.  */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If someone has defined alloca as a macro,
+   there must be some other way alloca is supposed to work.  */
+#ifndef alloca
+
+#ifdef emacs
+#ifdef static
+/* actually, only want this if static is defined as ""
+   -- this is for usg, in which emacs must undefine static
+   in order to make unexec workable
+   */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+   provide an "address metric" ADDRESS_FUNCTION macro.  */
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+#else
+#define ADDRESS_FUNCTION(arg) &(arg)
+#endif
+
+#if __STDC__
+typedef void *pointer;
+#else
+typedef char *pointer;
+#endif
+
+#define	NULL	0
+
+/* Different portions of Emacs need to call different versions of
+   malloc.  The Emacs executable needs alloca to call xmalloc, because
+   ordinary malloc isn't protected from input signals.  On the other
+   hand, the utilities in lib-src need alloca to call malloc; some of
+   them are very simple, and don't have an xmalloc routine.
+
+   Non-Emacs programs expect this to call use xmalloc.
+
+   Callers below should use malloc.  */
+
+#ifndef emacs
+#define malloc xmalloc
+#endif
+extern pointer malloc ();
+
+/* Define STACK_DIRECTION if you know the direction of stack
+   growth for your system; otherwise it will be automatically
+   deduced at run-time.
+
+   STACK_DIRECTION > 0 => grows toward higher addresses
+   STACK_DIRECTION < 0 => grows toward lower addresses
+   STACK_DIRECTION = 0 => direction of growth unknown  */
+
+#ifndef STACK_DIRECTION
+#define	STACK_DIRECTION	0	/* Direction unknown.  */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define	STACK_DIR	STACK_DIRECTION	/* Known at compile-time.  */
+
+#else /* STACK_DIRECTION == 0; need run-time code.  */
+
+static int stack_dir;		/* 1 or -1 once known.  */
+#define	STACK_DIR	stack_dir
+
+static void
+find_stack_direction ()
+{
+  static char *addr = NULL;	/* Address of first `dummy', once known.  */
+  auto char dummy;		/* To get stack address.  */
+
+  if (addr == NULL)
+    {				/* Initial entry.  */
+      addr = ADDRESS_FUNCTION (dummy);
+
+      find_stack_direction ();	/* Recurse once.  */
+    }
+  else
+    {
+      /* Second entry.  */
+      if (ADDRESS_FUNCTION (dummy) > addr)
+	stack_dir = 1;		/* Stack grew upward.  */
+      else
+	stack_dir = -1;		/* Stack grew downward.  */
+    }
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+   (a) chain together all alloca'ed blocks;
+   (b) keep track of stack depth.
+
+   It is very important that sizeof(header) agree with malloc
+   alignment chunk size.  The following default should work okay.  */
+
+#ifndef	ALIGN_SIZE
+#define	ALIGN_SIZE	sizeof(double)
+#endif
+
+typedef union hdr
+{
+  char align[ALIGN_SIZE];	/* To force sizeof(header).  */
+  struct
+    {
+      union hdr *next;		/* For chaining headers.  */
+      char *deep;		/* For stack depth measure.  */
+    } h;
+} header;
+
+static header *last_alloca_header = NULL;	/* -> last alloca header.  */
+
+/* Return a pointer to at least SIZE bytes of storage,
+   which will be automatically reclaimed upon exit from
+   the procedure that called alloca.  Originally, this space
+   was supposed to be taken from the current stack frame of the
+   caller, but that method cannot be made to work for some
+   implementations of C, for example under Gould's UTX/32.  */
+
+pointer
+alloca (size)
+     unsigned size;
+{
+  auto char probe;		/* Probes stack depth: */
+  register char *depth = ADDRESS_FUNCTION (probe);
+
+#if STACK_DIRECTION == 0
+  if (STACK_DIR == 0)		/* Unknown growth direction.  */
+    find_stack_direction ();
+#endif
+
+  /* Reclaim garbage, defined as all alloca'd storage that
+     was allocated from deeper in the stack than currently. */
+
+  {
+    register header *hp;	/* Traverses linked list.  */
+
+#ifdef emacs
+    BLOCK_INPUT;
+#endif
+
+    for (hp = last_alloca_header; hp != NULL;)
+      if ((STACK_DIR > 0 && hp->h.deep > depth)
+	  || (STACK_DIR < 0 && hp->h.deep < depth))
+	{
+	  register header *np = hp->h.next;
+
+	  free ((pointer) hp);	/* Collect garbage.  */
+
+	  hp = np;		/* -> next header.  */
+	}
+      else
+	break;			/* Rest are not deeper.  */
+
+    last_alloca_header = hp;	/* -> last valid storage.  */
+
+#ifdef emacs
+    UNBLOCK_INPUT;
+#endif
+  }
+
+  if (size == 0)
+    return NULL;		/* No allocation required.  */
+
+  /* Allocate combined header + user data storage.  */
+
+  {
+    register pointer new = malloc (sizeof (header) + size);
+    /* Address of header.  */
+
+    ((header *) new)->h.next = last_alloca_header;
+    ((header *) new)->h.deep = depth;
+
+    last_alloca_header = (header *) new;
+
+    /* User storage begins just after header.  */
+
+    return (pointer) ((char *) new + sizeof (header));
+  }
+}
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+#ifdef DEBUG_I00AFUNC
+#include <stdio.h>
+#endif
+
+#ifndef CRAY_STACK
+#define CRAY_STACK
+#ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+  {
+    long shgrow:32;		/* Number of times stack has grown.  */
+    long shaseg:32;		/* Size of increments to stack.  */
+    long shhwm:32;		/* High water mark of stack.  */
+    long shsize:32;		/* Current size of stack (all segments).  */
+  };
+
+/* The stack segment linkage control information occurs at
+   the high-address end of a stack segment.  (The stack
+   grows from low addresses to high addresses.)  The initial
+   part of the stack segment linkage control information is
+   0200 (octal) words.  This provides for register storage
+   for the routine which overflows the stack.  */
+
+struct stack_segment_linkage
+  {
+    long ss[0200];		/* 0200 overflow words.  */
+    long sssize:32;		/* Number of words in this segment.  */
+    long ssbase:32;		/* Offset to stack base.  */
+    long:32;
+    long sspseg:32;		/* Offset to linkage control of previous
+				   segment of stack.  */
+    long:32;
+    long sstcpt:32;		/* Pointer to task common address block.  */
+    long sscsnm;		/* Private control structure number for
+				   microtasking.  */
+    long ssusr1;		/* Reserved for user.  */
+    long ssusr2;		/* Reserved for user.  */
+    long sstpid;		/* Process ID for pid based multi-tasking.  */
+    long ssgvup;		/* Pointer to multitasking thread giveup.  */
+    long sscray[7];		/* Reserved for Cray Research.  */
+    long ssa0;
+    long ssa1;
+    long ssa2;
+    long ssa3;
+    long ssa4;
+    long ssa5;
+    long ssa6;
+    long ssa7;
+    long sss0;
+    long sss1;
+    long sss2;
+    long sss3;
+    long sss4;
+    long sss5;
+    long sss6;
+    long sss7;
+  };
+
+#else /* CRAY2 */
+/* The following structure defines the vector of words
+   returned by the STKSTAT library routine.  */
+struct stk_stat
+  {
+    long now;			/* Current total stack size.  */
+    long maxc;			/* Amount of contiguous space which would
+				   be required to satisfy the maximum
+				   stack demand to date.  */
+    long high_water;		/* Stack high-water mark.  */
+    long overflows;		/* Number of stack overflow ($STKOFEN) calls.  */
+    long hits;			/* Number of internal buffer hits.  */
+    long extends;		/* Number of block extensions.  */
+    long stko_mallocs;		/* Block allocations by $STKOFEN.  */
+    long underflows;		/* Number of stack underflow calls ($STKRETN).  */
+    long stko_free;		/* Number of deallocations by $STKRETN.  */
+    long stkm_free;		/* Number of deallocations by $STKMRET.  */
+    long segments;		/* Current number of stack segments.  */
+    long maxs;			/* Maximum number of stack segments so far.  */
+    long pad_size;		/* Stack pad size.  */
+    long current_address;	/* Current stack segment address.  */
+    long current_size;		/* Current stack segment size.  This
+				   number is actually corrupted by STKSTAT to
+				   include the fifteen word trailer area.  */
+    long initial_address;	/* Address of initial segment.  */
+    long initial_size;		/* Size of initial segment.  */
+  };
+
+/* The following structure describes the data structure which trails
+   any stack segment.  I think that the description in 'asdef' is
+   out of date.  I only describe the parts that I am sure about.  */
+
+struct stk_trailer
+  {
+    long this_address;		/* Address of this block.  */
+    long this_size;		/* Size of this block (does not include
+				   this trailer).  */
+    long unknown2;
+    long unknown3;
+    long link;			/* Address of trailer block of previous
+				   segment.  */
+    long unknown5;
+    long unknown6;
+    long unknown7;
+    long unknown8;
+    long unknown9;
+    long unknown10;
+    long unknown11;
+    long unknown12;
+    long unknown13;
+    long unknown14;
+  };
+
+#endif /* CRAY2 */
+#endif /* not CRAY_STACK */
+
+#ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+   I doubt that "lint" will like this much. */
+
+static long
+i00afunc (long *address)
+{
+  struct stk_stat status;
+  struct stk_trailer *trailer;
+  long *block, size;
+  long result = 0;
+
+  /* We want to iterate through all of the segments.  The first
+     step is to get the stack status structure.  We could do this
+     more quickly and more directly, perhaps, by referencing the
+     $LM00 common block, but I know that this works.  */
+
+  STKSTAT (&status);
+
+  /* Set up the iteration.  */
+
+  trailer = (struct stk_trailer *) (status.current_address
+				    + status.current_size
+				    - 15);
+
+  /* There must be at least one stack segment.  Therefore it is
+     a fatal error if "trailer" is null.  */
+
+  if (trailer == 0)
+    abort ();
+
+  /* Discard segments that do not contain our argument address.  */
+
+  while (trailer != 0)
+    {
+      block = (long *) trailer->this_address;
+      size = trailer->this_size;
+      if (block == 0 || size == 0)
+	abort ();
+      trailer = (struct stk_trailer *) trailer->link;
+      if ((block <= address) && (address < (block + size)))
+	break;
+    }
+
+  /* Set the result to the offset in this segment and add the sizes
+     of all predecessor segments.  */
+
+  result = address - block;
+
+  if (trailer == 0)
+    {
+      return result;
+    }
+
+  do
+    {
+      if (trailer->this_size <= 0)
+	abort ();
+      result += trailer->this_size;
+      trailer = (struct stk_trailer *) trailer->link;
+    }
+  while (trailer != 0);
+
+  /* We are done.  Note that if you present a bogus address (one
+     not in any segment), you will get a different number back, formed
+     from subtracting the address of the first block.  This is probably
+     not what you want.  */
+
+  return (result);
+}
+
+#else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+   Determine the number of the cell within the stack,
+   given the address of the cell.  The purpose of this
+   routine is to linearize, in some sense, stack addresses
+   for alloca.  */
+
+static long
+i00afunc (long address)
+{
+  long stkl = 0;
+
+  long size, pseg, this_segment, stack;
+  long result = 0;
+
+  struct stack_segment_linkage *ssptr;
+
+  /* Register B67 contains the address of the end of the
+     current stack segment.  If you (as a subprogram) store
+     your registers on the stack and find that you are past
+     the contents of B67, you have overflowed the segment.
+
+     B67 also points to the stack segment linkage control
+     area, which is what we are really interested in.  */
+
+  stkl = CRAY_STACKSEG_END ();
+  ssptr = (struct stack_segment_linkage *) stkl;
+
+  /* If one subtracts 'size' from the end of the segment,
+     one has the address of the first word of the segment.
+
+     If this is not the first segment, 'pseg' will be
+     nonzero.  */
+
+  pseg = ssptr->sspseg;
+  size = ssptr->sssize;
+
+  this_segment = stkl - size;
+
+  /* It is possible that calling this routine itself caused
+     a stack overflow.  Discard stack segments which do not
+     contain the target address.  */
+
+  while (!(this_segment <= address && address <= stkl))
+    {
+#ifdef DEBUG_I00AFUNC
+      fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+#endif
+      if (pseg == 0)
+	break;
+      stkl = stkl - pseg;
+      ssptr = (struct stack_segment_linkage *) stkl;
+      size = ssptr->sssize;
+      pseg = ssptr->sspseg;
+      this_segment = stkl - size;
+    }
+
+  result = address - this_segment;
+
+  /* If you subtract pseg from the current end of the stack,
+     you get the address of the previous stack segment's end.
+     This seems a little convoluted to me, but I'll bet you save
+     a cycle somewhere.  */
+
+  while (pseg != 0)
+    {
+#ifdef DEBUG_I00AFUNC
+      fprintf (stderr, "%011o %011o\n", pseg, size);
+#endif
+      stkl = stkl - pseg;
+      ssptr = (struct stack_segment_linkage *) stkl;
+      size = ssptr->sssize;
+      pseg = ssptr->sspseg;
+      result += size;
+    }
+  return (result);
+}
+
+#endif /* not CRAY2 */
+#endif /* CRAY */
+
+#endif /* no alloca */
+#endif /* not GCC version 2 */
Index: /indexers/branches/3.03a/mg/lib/bitio_gen.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_gen.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_gen.c	(revision 14757)
@@ -0,0 +1,141 @@
+/**************************************************************************
+ *
+ * bitio_gen.c -- General supoport routines for bitio
+ * Copyright (C) 1994  Neil Sharman and Alistair Moffat
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "bitio_m.h"
+
+
+
+
+int fprintf (FILE *, const char *,...);
+
+unsigned long 
+BIO_Unary_Length (unsigned long val)
+{
+  register unsigned long num;
+  UNARY_LENGTH (val, num);
+  return (num);
+}
+
+
+unsigned long 
+BIO_Binary_Length (unsigned long val, unsigned long b)
+{
+  register unsigned long num;
+  BINARY_LENGTH (val, b, num);
+  return (num);
+}
+
+
+unsigned long 
+BIO_Gamma_Length (unsigned long val)
+{
+  register unsigned long num;
+  GAMMA_LENGTH (val, num);
+  return (num);
+}
+
+
+unsigned long 
+BIO_Delta_Length (unsigned long val)
+{
+  register unsigned long num;
+  DELTA_LENGTH (val, num);
+  return (num);
+}
+
+
+unsigned long 
+BIO_Elias_Length (unsigned long val, unsigned long b, double s)
+{
+  register unsigned long num;
+  ELIAS_LENGTH (val, b, s, num);
+  return (num);
+}
+
+unsigned long 
+BIO_Bblock_Length (unsigned long val, unsigned long b)
+{
+  register unsigned long num;
+  BBLOCK_LENGTH (val, b, num);
+  return (num);
+}
+
+
+int 
+BIO_Bblock_Init (int N, int p)
+{
+  int b;
+  b = (int) (0.5 + 0.6931471 * N / p);
+  return (b ? b : 1);
+}
+
+
+int 
+BIO_Bblock_Init_W (int N, int p)
+{
+  int logb;
+  FLOORLOG_2 ((N - p) / p, logb);
+  return (logb < 0 ? 1 : (1 << logb));
+}
+
+int 
+BIO_Bblock_Bound_b (int N, int p, int b)
+{
+  int clogb;
+  CEILLOG_2 (b, clogb);
+  return (p * (1 + clogb) + (N - p * ((1 << clogb) - b + 1)) / b);
+}
+
+int 
+BIO_Bblock_Bound (int N, int p)
+{
+  int b;
+  b = BIO_Bblock_Init_W (N, p);
+  return (BIO_Bblock_Bound_b (N, p, b));
+}
+
+
+/* adjustment is a hack to overcome inaccuracies in floating point,
+   where (int)(ln4/ln2) can equal 1, not 2. */
+/* copied from mg-1.3f, 17-09-01 kjm18 */
+int 
+BIO_Gamma_Bound (int N, int p)
+{
+  /* return ((int) (p * (2 * log2 ((double) N / p) + 1))); */
+  return ((int) (p * (2 * log2 (((double) N * 1.0001) / p) + 1)));
+}
+
+int 
+floorlog_2 (int b)
+{
+  int logb;
+  FLOORLOG_2 (b, logb);
+  return logb;
+}
+
+int 
+ceillog_2 (int b)
+{
+  int logb;
+  CEILLOG_2 (b, logb);
+  return logb;
+}
Index: /indexers/branches/3.03a/mg/lib/bitio_gen.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_gen.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_gen.h	(revision 14757)
@@ -0,0 +1,61 @@
+/**************************************************************************
+ *
+ * bitio_gen.h -- General supoport routines for bitio
+ * Copyright (C) 1994  Neil Sharman and Alistair Moffat
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains function definitions for doing general bitio operations.
+ *
+ *  This file defines functions for calculation the length in bits of a number
+ *  coded unary, binary, delta, gamma, elias, and  bblock coding. It defines 
+ *  routines for calculating the parameter and bounds for bblock coding. 
+ *  Routines for calculating ceil and floor lg are also defined.
+ *
+ *
+ **************************************************************************/
+
+#ifndef H_BITIO_GEN
+#define H_BITIO_GEN
+
+unsigned long BIO_Unary_Length (unsigned long val);
+
+unsigned long BIO_Binary_Length (unsigned long val, unsigned long b);
+
+unsigned long BIO_Gamma_Length (unsigned long val);
+
+unsigned long BIO_Delta_Length (unsigned long val);
+
+unsigned long BIO_Elias_Length (unsigned long val, unsigned long b, double s);
+
+unsigned long BIO_Bblock_Length (unsigned long val, unsigned long b);
+
+int BIO_Bblock_Init (int N, int p);
+
+int BIO_Bblock_Init_W (int N, int p);
+
+int BIO_Bblock_Bound_b (int N, int p, int b);
+
+int BIO_Bblock_Bound (int N, int p);
+
+int BIO_Gamma_Bound (int N, int p);
+
+int floorlog_2 (int b);
+
+int ceillog_2 (int b);
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/bitio_m.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_m.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_m.h	(revision 14757)
@@ -0,0 +1,541 @@
+/**************************************************************************
+ *
+ * bitio_m.h -- Macros for bitio
+ * Copyright (C) 1994  Neil Sharman and Alistair Moffat
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+
+#ifndef H_BITIO_M
+#define H_BITIO_M
+
+/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
+
+#ifndef BIO_ENCODE_PROLOGUE
+#define BIO_ENCODE_PROLOGUE
+#endif
+
+#ifndef BIO_DECODE_PROLOGUE
+#define BIO_DECODE_PROLOGUE
+#endif
+
+#ifndef BIO_ENCODE_EPILOGUE
+#define BIO_ENCODE_EPILOGUE
+#endif
+
+#ifndef BIO_DECODE_EPILOGUE
+#define BIO_DECODE_EPILOGUE
+#endif
+
+#ifndef DECODE_ADD
+#define DECODE_ADD(b) (b) += (b) + DECODE_BIT
+#endif
+
+/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
+
+#define POSITIVE(f, x)							\
+  if ((x)<=0) 								\
+    fprintf(stderr,"Error: Cannot "#f" encode %lu\n",(unsigned long)x),exit(1);
+
+
+#define CEILLOG_2(x,v)							\
+do {									\
+  register int _B_x  = (x) - 1;						\
+  (v) = 0;								\
+  for (; _B_x ; _B_x>>=1, ++(v));					\
+} while(0)
+
+
+#define FLOORLOG_2(x,v)							\
+do {									\
+  register int _B_x  = (x);						\
+  (v) = -1;								\
+  for (; _B_x ; _B_x>>=1, ++(v));					\
+} while(0)
+
+
+/****************************************************************************/
+
+
+
+#define UNARY_ENCODE(x)							\
+do {									\
+  register unsigned long _B_x = (x);					\
+  BIO_ENCODE_PROLOGUE;							\
+  POSITIVE(unary, _B_x);						\
+  while(--_B_x) ENCODE_BIT(0);						\
+  ENCODE_BIT(1);							\
+  BIO_ENCODE_EPILOGUE;							\
+} while(0)
+
+#define UNARY_ENCODE_L(x, count)					\
+do {									\
+  register unsigned long _B_x = (x);					\
+  BIO_ENCODE_PROLOGUE;							\
+  POSITIVE(unary, _B_x);						\
+  (count) += _B_x;							\
+  while(--_B_x) ENCODE_BIT(0);						\
+  ENCODE_BIT(1);							\
+  BIO_ENCODE_EPILOGUE;							\
+} while(0)
+
+#define UNARY_DECODE(x)							\
+do {									\
+  BIO_DECODE_PROLOGUE;							\
+  (x) = 1;								\
+  while (!DECODE_BIT) ++(x);						\
+  BIO_DECODE_EPILOGUE;							\
+} while(0)
+
+#define UNARY_DECODE_L(x, count)					\
+do {									\
+  BIO_DECODE_PROLOGUE;							\
+  (x) = 1;								\
+  while (!DECODE_BIT) ++(x);						\
+  (count) += (x);							\
+  BIO_DECODE_EPILOGUE;							\
+} while(0)
+
+
+#define UNARY_LENGTH(x, count)						\
+do {									\
+  POSITIVE(unary, x);							\
+  (count) = (x);							\
+} while(0)
+
+
+/****************************************************************************/
+
+
+#define BINARY_ENCODE(x, b)						\
+do {									\
+  register unsigned long _B_x = (x);					\
+  register unsigned long _B_b = (b);					\
+  register int _B_nbits, _B_logofb, _B_thresh;				\
+  BIO_ENCODE_PROLOGUE;							\
+  POSITIVE(binary, _B_x);						\
+  CEILLOG_2(_B_b, _B_logofb);						\
+  _B_thresh = (1<<_B_logofb) - _B_b;					\
+  if (--_B_x < _B_thresh)						\
+    _B_nbits = _B_logofb-1;						\
+  else									\
+    {									\
+      _B_nbits = _B_logofb;						\
+      _B_x += _B_thresh;						\
+    }									\
+  while (--_B_nbits>=0)							\
+    ENCODE_BIT((_B_x>>_B_nbits) & 0x1);					\
+  BIO_ENCODE_EPILOGUE;							\
+} while(0)
+
+#define BINARY_ENCODE_L(x, b, count)					\
+do {									\
+  register unsigned long _B_x = (x);					\
+  register unsigned long _B_b = (b);					\
+  register int _B_nbits, _B_logofb, _B_thresh;				\
+  BIO_ENCODE_PROLOGUE;							\
+  POSITIVE(binary, _B_x);						\
+  CEILLOG_2(_B_b, _B_logofb);						\
+  _B_thresh = (1<<_B_logofb) - _B_b;					\
+  if (--_B_x < _B_thresh)						\
+    _B_nbits = _B_logofb-1;						\
+  else									\
+    {									\
+      _B_nbits = _B_logofb;						\
+      _B_x += _B_thresh;						\
+    }									\
+  (count) += _B_nbits;							\
+  while (--_B_nbits>=0)							\
+    ENCODE_BIT((_B_x>>_B_nbits) & 0x1);					\
+  BIO_ENCODE_EPILOGUE;							\
+} while(0)
+
+
+#define BINARY_DECODE(x, b)						\
+do {									\
+  register unsigned long _B_x = 0;					\
+  register unsigned long _B_b = (b);					\
+  register int _B_i, _B_logofb, _B_thresh;				\
+  BIO_DECODE_PROLOGUE;							\
+  if (_B_b != 1)							\
+    {									\
+      CEILLOG_2(_B_b, _B_logofb);					\
+      _B_thresh = (1<<_B_logofb) - _B_b;				\
+      --_B_logofb;							\
+      for (_B_i=0; _B_i < _B_logofb; ++_B_i)			 	\
+        DECODE_ADD(_B_x);						\
+      if (_B_x >= _B_thresh)						\
+        {								\
+          DECODE_ADD(_B_x);						\
+          _B_x -= _B_thresh;						\
+	}								\
+      (x) = _B_x+1;							\
+    }									\
+  else									\
+    (x) = 1;								\
+  BIO_DECODE_EPILOGUE;							\
+} while(0)
+
+#define BINARY_DECODE_L(x, b, count)					\
+do {									\
+  register unsigned long _B_x = 0;					\
+  register unsigned long _B_b = (b);					\
+  register int _B_i, _B_logofb, _B_thresh;				\
+  BIO_DECODE_PROLOGUE;							\
+  if (_B_b != 1)							\
+    {									\
+      CEILLOG_2(_B_b, _B_logofb);					\
+      _B_thresh = (1<<_B_logofb) - _B_b;				\
+      --_B_logofb;							\
+      (count) += _B_logofb;					       	\
+      for (_B_i=0; _B_i < _B_logofb; ++_B_i)			 	\
+        DECODE_ADD(_B_x);						\
+      if (_B_x >= _B_thresh)						\
+        {								\
+          DECODE_ADD(_B_x);						\
+          _B_x -= _B_thresh;						\
+          ++(count);							\
+	}								\
+      (x) = _B_x+1;							\
+    }									\
+  else									\
+    (x) = 1;								\
+  BIO_DECODE_EPILOGUE;							\
+} while(0)
+
+#define BINARY_LENGTH(x, b, count)					\
+do {									\
+  register unsigned long _B_x = (x);					\
+  register unsigned long _B_b = (b);					\
+  register int _B_nbits, _B_logofb, _B_thresh;				\
+  POSITIVE(binary, _B_x);						\
+  CEILLOG_2(_B_b, _B_logofb);						\
+  _B_thresh = (1<<_B_logofb) - _B_b;					\
+  if (--_B_x < _B_thresh)						\
+    _B_nbits = _B_logofb-1;						\
+  else									\
+    _B_nbits = _B_logofb;						\
+  (count) = _B_nbits;							\
+} while(0)
+
+/****************************************************************************/
+
+
+
+
+#define GAMMA_ENCODE(x)							\
+do {									\
+  register unsigned long _B_xx = (x);					\
+  register int _B_logofb;						\
+  register int _B_nbits;						\
+  BIO_ENCODE_PROLOGUE;							\
+  POSITIVE(gamma, _B_xx);						\
+  FLOORLOG_2(_B_xx, _B_logofb);						\
+  _B_nbits = _B_logofb+1;						\
+  while(_B_logofb--) ENCODE_BIT(0);					\
+  while (--_B_nbits>=0)							\
+    ENCODE_BIT((_B_xx>>_B_nbits) & 0x1);				\
+  BIO_ENCODE_EPILOGUE;							\
+} while (0)
+
+#define GAMMA_ENCODE_L(x, count)					\
+do {									\
+  register unsigned long _B_xx = (x);					\
+  register int _B_logofb;						\
+  register int _B_nbits;						\
+  BIO_ENCODE_PROLOGUE;							\
+  POSITIVE(gamma, _B_xx);						\
+  FLOORLOG_2(_B_xx, _B_logofb);						\
+  _B_nbits = _B_logofb+1;						\
+  (count) += _B_logofb*2+1;						\
+  while(_B_logofb--) ENCODE_BIT(0);					\
+  while (--_B_nbits>=0)							\
+    ENCODE_BIT((_B_xx>>_B_nbits) & 0x1);				\
+  BIO_ENCODE_EPILOGUE;							\
+} while (0)
+
+#define GAMMA_DECODE(x)							\
+do {									\
+  register unsigned long _B_xx = 1;					\
+  register int _B_nbits = 0;						\
+  BIO_DECODE_PROLOGUE;							\
+  while(!DECODE_BIT) ++_B_nbits;					\
+  while (_B_nbits-- > 0)						\
+    DECODE_ADD(_B_xx);							\
+  (x) = _B_xx;								\
+  BIO_DECODE_EPILOGUE;							\
+} while (0)
+
+#define GAMMA_DECODE_L(x, count)					\
+do {									\
+  register unsigned long _B_xx = 1;					\
+  register int _B_nbits = 0;						\
+  BIO_DECODE_PROLOGUE;							\
+  while(!DECODE_BIT) ++_B_nbits;					\
+  (count) += _B_nbits*2+1;						\
+  while (_B_nbits-- > 0)						\
+    DECODE_ADD(_B_xx);							\
+  (x) = _B_xx;								\
+  BIO_DECODE_EPILOGUE;							\
+} while (0)
+
+#define GAMMA_LENGTH(x, count)						\
+do {									\
+  register unsigned long _B_xx = (x);					\
+  register int _B_logofb;						\
+  POSITIVE(gamma, _B_xx);						\
+  FLOORLOG_2(_B_xx, _B_logofb);						\
+  (count) = _B_logofb*2+1;						\
+} while (0)
+
+
+
+/****************************************************************************/
+
+
+#define DELTA_ENCODE(x)							\
+do {									\
+  register unsigned long _B_xxx = (x);					\
+  register int _B_logx;							\
+  FLOORLOG_2(_B_xxx, _B_logx);						\
+  GAMMA_ENCODE(_B_logx+1);						\
+  BINARY_ENCODE(_B_xxx+1, 1<<_B_logx);					\
+} while (0)
+
+#define DELTA_ENCODE_L(x, count)					\
+do {									\
+  register unsigned long _B_xxx = (x);					\
+  register int _B_logx;							\
+  FLOORLOG_2(_B_xxx, _B_logx);						\
+  GAMMA_ENCODE_L(_B_logx+1, count);					\
+  BINARY_ENCODE_L(_B_xxx+1, 1<<_B_logx, count);				\
+} while (0)
+
+
+#define DELTA_DECODE(x)							\
+do {									\
+  register unsigned long _B_xxx;					\
+  register int _B_logx;							\
+  GAMMA_DECODE(_B_logx); --_B_logx;					\
+  BINARY_DECODE(_B_xxx, 1<<_B_logx); --_B_xxx;				\
+  (x) = _B_xxx + (1<<_B_logx);						\
+} while (0)
+
+#define DELTA_DECODE_L(x, count)					\
+do {									\
+  register unsigned long _B_xxx;					\
+  register int _B_logx;							\
+  GAMMA_DECODE_L(_B_logx, count); --_B_logx;				\
+  BINARY_DECODE_L(_B_xxx, 1<<_B_logx, count); --_B_xxx;			\
+  (x) = _B_xxx + (1<<_B_logx);						\
+} while (0)
+
+#define DELTA_LENGTH(x, count)						\
+do {									\
+  register unsigned long _B_xxx = (x);					\
+  register int _B_logx, _B_dcount;					\
+  FLOORLOG_2(_B_xxx, _B_logx);						\
+  GAMMA_LENGTH(_B_logx+1, count);					\
+  BINARY_LENGTH(_B_xxx+1, 1<<_B_logx, _B_dcount);			\
+  (count) += _B_dcount;							\
+} while (0)
+
+
+/****************************************************************************/
+
+
+
+
+#define ELIAS_ENCODE(x, b, s)						\
+do {									\
+  register unsigned long _B_xx = (x);					\
+  register unsigned long _B_b = (b);					\
+  register double _B_s = (s);						\
+  register int _B_lower=1, _B_upper=1;					\
+  register int _B_k=0;							\
+  register double _B_pow=1.0;						\
+  POSITIVE(elias, _B_xx);						\
+  while (_B_xx>_B_upper) 						\
+    {									\
+      ++_B_k;								\
+      _B_lower = _B_upper+1;						\
+      _B_pow *= _B_s;							\
+      _B_upper += _B_b*_B_pow;						\
+    }									\
+  UNARY_ENCODE(_B_k+1);							\
+  BINARY_ENCODE(_B_xx-_B_lower+1, _B_upper-_B_lower+1);			\
+} while (0)
+
+#define ELIAS_ENCODE_L(x, b, s, count)					\
+do {									\
+  register unsigned long _B_xx = (x);					\
+  register unsigned long _B_b = (b);					\
+  register double _B_s = (s);						\
+  register int _B_lower=1, _B_upper=1;					\
+  register int _B_k=0;							\
+  register double _B_pow=1.0;						\
+  POSITIVE(elias, _B_xx);						\
+  while (_B_xx>_B_upper) 						\
+    {									\
+      ++_B_k;								\
+      _B_lower = _B_upper+1;						\
+      _B_pow *= _B_s;							\
+      _B_upper += _B_b*_B_pow;						\
+    }									\
+  UNARY_ENCODE_L(_B_k+1, count);					\
+  BINARY_ENCODE_L(_B_xx-_B_lower+1, _B_upper-_B_lower+1, count);	\
+} while (0)
+
+#define ELIAS_DECODE(x, b, s)						\
+do {									\
+  register unsigned long _B_xx;						\
+  register unsigned long _B_b = (b);					\
+  register double _B_s = (s);						\
+  register int _B_lower=1, _B_upper=1;					\
+  register int _B_k;							\
+  register double _B_pow=1.0;						\
+  UNARY_DECODE(_B_k); --_B_k;						\
+  while (_B_k--)							\
+    {									\
+      _B_lower = _B_upper+1;						\
+      _B_pow *= _B_s;							\
+      _B_upper += _B_b*_B_pow;						\
+    }									\
+  BINARY_DECODE(_B_xx, _B_upper-_B_lower+1); --_B_xx;			\
+  POSITIVE(gamma, _B_xx+_B_lower);				  	\
+  (x) = _B_xx+_B_lower;							\
+} while (0)
+
+#define ELIAS_DECODE_L(x, b, s, count)					\
+do {									\
+  register unsigned long _B_xx;						\
+  register unsigned long _B_b = (b);					\
+  register double _B_s = (s);						\
+  register int _B_lower=1, _B_upper=1;					\
+  register int _B_k;							\
+  register double _B_pow=1.0;						\
+  UNARY_DECODE_L(_B_k, count); --_B_k;					\
+  while (_B_k--)							\
+    {									\
+      _B_lower = _B_upper+1;						\
+      _B_pow *= _B_s;							\
+      _B_upper += _B_b*_B_pow;						\
+    }									\
+  BINARY_DECODE_L(_B_xx, _B_upper-_B_lower+1, count); --_B_xx;		\
+  POSITIVE(gamma, _B_xx+_B_lower);				  	\
+  (x) = _B_xx+_B_lower;							\
+} while (0)
+
+#define ELIAS_LENGTH(x, b, s, count)					\
+do {									\
+  register unsigned long _B_xx = (x);					\
+  register unsigned long _B_b = (b);					\
+  register double _B_s = (s);						\
+  register int _B_lower=1, _B_upper=1;					\
+  register int _B_k=0, _B_ecount;					\
+  register double _B_pow=1.0;						\
+  POSITIVE(gamma, _B_xx);						\
+  while (_B_xx>_B_upper) 						\
+    {									\
+      ++_B_k;								\
+      _B_lower = _B_upper+1;						\
+      _B_pow *= _B_s;							\
+      _B_upper += _B_b*_B_pow;						\
+    }									\
+  UNARY_LENGTH(_B_k+1, count);						\
+  BINARY_LENGTH(_B_xx-_B_lower+1, _B_upper-_B_lower+1, _B_ecount);	\
+  (count) += _B_ecount;							\
+} while (0)
+
+
+/****************************************************************************/
+
+
+#define BBLOCK_ENCODE(x, b)						\
+do {									\
+  register unsigned long _B_xx = (x);					\
+  register unsigned long _B_bb = (b);					\
+  register int _B_xdivb = 0;						\
+  POSITIVE(bblock, _B_xx);						\
+  --_B_xx;								\
+  while (_B_xx >= _B_bb) 						\
+    {									\
+      ++_B_xdivb;							\
+      _B_xx -= _B_bb;							\
+    }									\
+  UNARY_ENCODE(_B_xdivb+1);						\
+  BINARY_ENCODE(_B_xx+1, _B_bb);					\
+} while (0)
+
+#define BBLOCK_ENCODE_L(x, b, count)					\
+do {									\
+  register unsigned long _B_xx = (x);					\
+  register unsigned long _B_bb = (b);					\
+  register int _B_xdivb = 0;						\
+  POSITIVE(bblock, _B_xx);						\
+  --_B_xx;								\
+  while (_B_xx >= _B_bb) 						\
+    {									\
+      ++_B_xdivb;							\
+      _B_xx -= _B_bb;							\
+    }									\
+  UNARY_ENCODE_L(_B_xdivb+1, count);					\
+  BINARY_ENCODE_L(_B_xx+1, _B_bb, count);				\
+} while (0)
+
+#define BBLOCK_DECODE(x, b)						\
+do {									\
+  register unsigned long _B_x1, _B_xx = 0;				\
+  register unsigned long _B_bb = (b);					\
+  register int _B_xdivb;						\
+  UNARY_DECODE(_B_xdivb); --_B_xdivb;					\
+  while (_B_xdivb--)							\
+    _B_xx += _B_bb;							\
+  BINARY_DECODE(_B_x1, _B_bb);						\
+  (x) = _B_xx+_B_x1;							\
+} while (0)
+
+#define BBLOCK_DECODE_L(x, b, count)					\
+do {									\
+  register unsigned long _B_x1, _B_xx = 0;				\
+  register unsigned long _B_bb = (b);					\
+  register int _B_xdivb;						\
+  UNARY_DECODE_L(_B_xdivb, count); --_B_xdivb;				\
+  while (_B_xdivb--)							\
+    _B_xx += _B_bb;							\
+  BINARY_DECODE_L(_B_x1, _B_bb, count);					\
+  (x) = _B_xx+_B_x1;							\
+} while (0)
+
+#define BBLOCK_LENGTH(x, b, count)					\
+do {									\
+  register unsigned long _B_bcount, _B_xx = (x);			\
+  register unsigned long _B_bb = (b);					\
+  register int _B_xdivb = 0;						\
+  POSITIVE(bblock, _B_xx);						\
+  --_B_xx;								\
+  while (_B_xx >= _B_bb) 						\
+    {									\
+      ++_B_xdivb;							\
+      _B_xx -= _B_bb;							\
+    }									\
+  UNARY_LENGTH(_B_xdivb+1, count);					\
+  BINARY_LENGTH(_B_xx+1, _B_bb, _B_bcount);				\
+  (count) += _B_bcount;  						\
+} while (0)
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/bitio_m_mem.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_m_mem.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_m_mem.h	(revision 14757)
@@ -0,0 +1,189 @@
+/**************************************************************************
+ *
+ * bitio_m_mem.h -- Macros for bitio to memory
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains macros for doing bitwise input and output on an array 
+ *  of chars. These routines are faster than the ones in "mems" files. But 
+ *  with these routines you cannot mix reads and writes on the array of chars,
+ *  or multiple write, at the same time and guarantee them to work, also you 
+ *  cannot seek to a point and do a write. The decode routine can detect when
+ *  you run off the end of the array and will produce an approate error 
+ *  message, and the encode routine will stop when it gets to the end of the 
+ *  character array. 
+ *
+ **************************************************************************/
+
+#ifndef H_BITIO_M_MEM
+#define H_BITIO_M_MEM
+
+typedef struct mem_bitio_state
+  {
+    unsigned char *Base;
+    unsigned char *Pos;
+    int Remaining;
+    unsigned char Buff;
+    unsigned char Btg;
+  }
+mem_bitio_state;
+
+
+
+
+#ifndef DECODE_ERROR
+#define DECODE_ERROR (fprintf(stderr,"Unexpected EOF in \"%s\" on line %d\n",\
+				__FILE__, __LINE__), exit(1))
+#endif
+
+
+
+#define ENCODE_START(p,r)						\
+  {									\
+    register unsigned char *__pos = p;					\
+    register unsigned char *__base = p;					\
+    register int __remaining = r;					\
+    register unsigned char __buff = 0;					\
+    register unsigned char __btg = sizeof(__buff)*8;
+
+#define ENCODE_CONTINUE(b)						\
+  {									\
+    register unsigned char *__pos = (b).Pos;				\
+    register unsigned char *__base = (b).Base;				\
+    register int __remaining = (b).Remaining;				\
+    register unsigned char __buff = (b).Buff;				\
+    register unsigned char __btg = (b).Btg;
+
+#define ENCODE_BIT(b)							\
+  do {									\
+    --__btg;								\
+    if (b) __buff |= (1 << __btg);					\
+    if (!__btg)								\
+      {									\
+	if (__remaining)						\
+	  {								\
+	    *__pos++ = __buff;						\
+	    --__remaining;						\
+	  }  								\
+	__buff = 0;							\
+	__btg = sizeof(__buff)*8;					\
+      }									\
+  } while(0)
+
+#define ENCODE_PAUSE(b)							\
+    (b).Pos = __pos;							\
+    (b).Base = __base;							\
+    (b).Remaining = __remaining;					\
+    (b).Buff = __buff;							\
+    (b).Btg =  __btg;							\
+  }
+
+#define ENCODE_FLUSH							\
+  do {									\
+    if (__btg != sizeof(__buff)*8)					\
+      if (__remaining)							\
+	{								\
+          *__pos++ = __buff;						\
+          --__remaining;						\
+	}  								\
+    __btg = sizeof(__buff)*8;						\
+  } while (0)
+
+#define ENCODE_DONE							\
+    ENCODE_FLUSH;							\
+  }
+
+
+#define DECODE_START(p,r)						\
+  {									\
+    register unsigned char *__pos = p;					\
+    register unsigned char *__base = p;					\
+    register int __remaining = r;					\
+    register unsigned char __buff = 0;					\
+    register unsigned char __btg = 0;
+
+#define DECODE_CONTINUE(b)						\
+  {									\
+    register unsigned char *__pos = (b).Pos;				\
+    register unsigned char *__base = (b).Base;				\
+    register int __remaining = (b).Remaining;				\
+    register unsigned char __buff = (b).Buff;				\
+    register unsigned char __btg = (b).Btg;
+
+#define DECODE_ADD_FF(b)						\
+  do {									\
+    if (!__btg)								\
+      {									\
+	if (__remaining)						\
+	  {								\
+  	    __buff = *__pos++;						\
+	    --__remaining;						\
+	  }								\
+        else								\
+          __buff = 0xff;						\
+	__btg = sizeof(__buff)*8;					\
+      }									\
+    (b) += (b) + ((__buff >> --__btg) & 1);				\
+  } while(0)
+
+#define DECODE_ADD_00(b)						\
+  do {									\
+    if (!__btg)								\
+      {									\
+	if (__remaining)						\
+	  {								\
+  	    __buff = *__pos++;						\
+	    --__remaining;						\
+	  }								\
+        else								\
+          __buff = 0x00;						\
+	__btg = sizeof(__buff)*8;					\
+      }									\
+    (b) += (b) + ((__buff >> --__btg) & 1);				\
+  } while(0)
+
+#define DECODE_BIT (__btg ? (__buff >> --__btg) & 1 :			\
+   (!__remaining ? 							\
+    (DECODE_ERROR, 0) :							\
+    (__buff = *__pos++, __remaining--, __btg = sizeof(__buff)*8, 	\
+     (__buff >> --__btg) & 1)))
+
+#define DECODE_DONE	;						\
+  }
+
+#define DECODE_PAUSE(b)							\
+    (b).Pos = __pos;							\
+    (b).Base = __base;							\
+    (b).Remaining = __remaining;					\
+    (b).Buff = __buff;							\
+    (b).Btg =  __btg;							\
+  }
+
+#define DECODE_SEEK(pos)						\
+  do {									\
+    register long __new_pos = (pos);					\
+    __pos = __base + (__new_pos >> 3);					\
+    __buff = *__pos++;							\
+    __btg = 8 - (__new_pos&7);						\
+    }									\
+  while(0)
+
+
+
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/bitio_m_mems.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_m_mems.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_m_mems.h	(revision 14757)
@@ -0,0 +1,112 @@
+/**************************************************************************
+ *
+ * bitio_m_mems.h -- Macros for bitio to memory (random access)
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains macros for doing bitwise input and output on an array 
+ *  of chars. These routines are slower than the ones in "mem" files. but 
+ *  with these routines you can mix reads and writes, or multiple writes,  on
+ *  the array of chars at the same time and guarantee them to work, also you 
+ *  can seek to a point and do a write. The decode and encode macros cannot 
+ *  detect when the end off the character is reached and just continue 
+ *  processing.
+ *
+ **************************************************************************/
+
+#ifndef H_BITIO_M_MEMS
+#define H_BITIO_M_MEMS
+
+typedef struct mems_bitio_state
+  {
+    unsigned char *Base;
+    unsigned long pos;
+  }
+mems_bitio_state;
+
+
+#define ENCODE_START(b,p)						\
+  {									\
+    register unsigned char *__base = b;					\
+    register unsigned long __pos = p;
+
+#define ENCODE_CONTINUE(b)						\
+  {									\
+    register unsigned char *__base = (b).Base;				\
+    register unsigned long __pos = (b).pos;
+
+#define ENCODE_BIT(b)							\
+  do {									\
+    if (b)								\
+      __base[__pos>>3] |= 0x80 >> (__pos&7);				\
+    else								\
+      __base[__pos>>3] &= 0xff7f >> (__pos&7);				\
+    ++__pos;								\
+  } while(0)
+
+#define ENCODE_PAUSE(b)							\
+    (b).Base = __base;							\
+    (b).pos = __pos;							\
+  }
+
+#define ENCODE_FLUSH
+
+
+#define ENCODE_DONE							\
+    ENCODE_FLUSH;							\
+  }
+
+
+#define DECODE_START(b,p)						\
+  {									\
+    register unsigned char *__base = b;					\
+    register unsigned long __pos = p;
+
+#define DECODE_CONTINUE(b)						\
+  {									\
+    register unsigned char *__base = (b).Base;				\
+    register unsigned long __pos = (b).pos;
+
+#define DECODE_ADD_FF(b)						\
+  do {									\
+    (b) += (b) + (__base[__pos>>3] & (0x80 >> (__pos&7)) != 0);		\
+    ++__pos;								\
+  } while(0)
+
+#define DECODE_ADD_00(b) DECODE_ADD_FF(b)
+
+#define DECODE_BIT 							\
+    (__pos++, ((__base[(__pos-1)>>3] & (0x80 >> ((__pos-1)&7))) != 0))
+
+#define DECODE_DONE	;						\
+  }
+
+#define DECODE_PAUSE(b)							\
+    (b).Base = __base;							\
+    (b).pos = __pos;							\
+  }
+
+#define DECODE_SEEK(pos) __pos = (pos)
+
+#define ENCODE_SEEK(pos) __pos = (pos)
+
+
+
+
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/bitio_m_random.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_m_random.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_m_random.h	(revision 14757)
@@ -0,0 +1,166 @@
+/**************************************************************************
+ *
+ * bitio_m_random.h -- Macros for bitio to a file (random access)
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains macros for doing bitwise input and output on an array 
+ *  of chars. These routines are slower than the ones in "mem" files. but 
+ *  with these routines you can mix reads and writes, or multiple writes,  on
+ *  the array of chars at the same time and guarantee them to work, also you 
+ *  can seek to a point and do a write. The decode and encode macros cannot 
+ *  detect when the end off the character is reached and just continue 
+ *  processing.
+ *
+ *
+ **************************************************************************/
+
+#ifndef H_BITIO_M_RANDOM
+#define H_BITIO_M_RANDOM
+
+typedef struct random_bitio_state
+  {
+    FILE *File;
+    unsigned char *Buf;
+    unsigned long Base;
+    unsigned long Used;
+    unsigned long pos;
+    unsigned long len;
+    unsigned long sft;
+  }
+random_bitio_state;
+
+
+#define ENCODE_START(f,l)						\
+  {									\
+    register FILE *__file = f;						\
+    register unsigned char *__buf;					\
+    register unsigned long __pos = 0;					\
+    register unsigned long __base = 0;					\
+    register unsigned long __is_used = 0;					\
+    register unsigned long __len = (l)-1;				\
+    register unsigned long __sft = 0;					\
+    while (__len) { ++__sft; __len >>=1; }				\
+    __len = 1<<__sft;							\
+    __buf = Xmalloc(__len);						\
+    fseek(__file, 0, 0);						\
+    fread(__buf, 1, __len, __file);
+
+#define ENCODE_CONTINUE(b)						\
+  {									\
+    register FILE *__file = (b).File;					\
+    register unsigned char *__buf = (b).Buf;				\
+    register unsigned long __pos = (b).pos;				\
+    register unsigned long __base = (b).Base;				\
+    register unsigned long __is_used = (b).Used;				\
+    register unsigned long __len = (b).len;				\
+    register unsigned long __sft = (b).sft;
+
+#define SEEK fprintf(stderr, "Seek to %d\n",__base)
+#define READ fprintf(stderr, "Read of %d\n",__len)
+#define WRITE fprintf(stderr, "Write of %d\n",__is_used)
+
+#define WRITE_READ 							\
+	(__is_used ? (fseek(__file, __base, 0),				\
+                   fwrite(__buf, 1, __len, __file)) : 0,		\
+        __base += __len,						\
+	fseek(__file, __base, 0),					\
+        fread(__buf, 1, __len, __file),					\
+	__pos = 0, __is_used = 0)
+
+#define ENCODE_BIT(b)							\
+  do {									\
+    if (b)								\
+      __buf[__pos>>3] |= 0x80 >> (__pos&7);				\
+    else								\
+      __buf[__pos>>3] &= 0xff7f >> (__pos&7);				\
+    __is_used = 1;								\
+    ++__pos;								\
+    if ((__pos>>3) >= __len)						\
+      (void)WRITE_READ;							\
+  } while(0)
+
+#define ENCODE_PAUSE(b)							\
+    (b).File = __file;							\
+    (b).Buf = __buf;							\
+    (b).pos = __pos;							\
+    (b).Base = __base;							\
+    (b).Used = __is_used;							\
+    (b).len = __len;							\
+    (b).sft = __sft;							\
+  }
+
+#define ENCODE_FLUSH							\
+  if (__is_used)								\
+    {									\
+      fseek(__file, __base, 0);						\
+      fwrite(__buf, 1, __len, __file);					\
+      __is_used = 0;							\
+    }
+
+
+
+#define ENCODE_DONE							\
+    ENCODE_FLUSH;							\
+    free(__buf);							\
+  }
+
+
+#define DECODE_START(f,l) ENCODE_START(f,l)
+
+#define DECODE_CONTINUE(b) ENCODE_CONTINUE(b)
+
+#define DECODE_BIT 							\
+    (__pos++, (((__pos-1)>>3) >= __len ? WRITE_READ, __pos=1 : 0),	\
+     ((__buf[(__pos-1)>>3] & (0x80 >> ((__pos-1)&7))) != 0))
+
+#define DECODE_ADD_FF(b) ((b) += (b) + DECODE_BIT)
+
+#define DECODE_ADD_00(b) DECODE_ADD_FF(b)
+
+#define DECODE_DONE ENCODE_DONE
+
+#define DECODE_PAUSE(b)	ENCODE_PAUSE(b)
+
+#define ENCODE_SEEK(pos) 						\
+  do {									\
+    if ((((pos)>>3) >= __base) && ((((pos)+7)>>3) < (__base+__len)))   	\
+      __pos = (pos)-(__base << 3); 					\
+    else								\
+      {									\
+        ENCODE_FLUSH;							\
+        __base = (pos) >> 3;						\
+        __base = ((pos)  >> (__sft+3)) << __sft;			\
+        fseek(__file, __base, 0);					\
+        fread(__buf, 1, __len, __file);					\
+        __pos = (pos)&7; 						\
+        __pos = (pos)&((8 << __sft)-1);					\
+      }									\
+  } while(0)
+
+
+#define DECODE_SEEK(pos) ENCODE_SEEK(pos)
+
+#define ENCODE_TELL ((__base << 3) + __pos)
+
+#define DECODE_TELL ENCODE_TELL
+
+
+
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/bitio_m_stdio.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_m_stdio.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_m_stdio.h	(revision 14757)
@@ -0,0 +1,145 @@
+/**************************************************************************
+ *
+ * bitio_m_stdio.h -- Macros for bitio to a file
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains macros for doing bitwise input and output on a FILE*.
+ *  With these routines you cannot mix reads and writes on the FILE,
+ *  or multiple writes, at the same time and guarantee them to work, also you 
+ *  cannot seek to a point and do a write. The decode routine can detect when
+ *  you run off the end of the file and will produce an approate error message.
+ *
+ *
+ **************************************************************************/
+
+#ifndef H_BITIO_M_STDIO
+#define H_BITIO_M_STDIO
+
+typedef struct stdio_bitio_state
+  {
+    FILE *File;
+    unsigned char Buff;
+    unsigned char Btg;
+  }
+stdio_bitio_state;
+
+
+
+#ifndef DECODE_ERROR
+#define DECODE_ERROR (fprintf(stderr,"Unexpected EOF in \"%s\" on line %d\n",\
+				__FILE__, __LINE__), exit(1))
+#endif
+
+
+
+#define ENCODE_START(f)							\
+  {									\
+    FILE *__outfile = f;						\
+    register unsigned char __buff = 0;					\
+    register unsigned char __btg = sizeof(__buff)*8;
+
+#define ENCODE_CONTINUE(b)						\
+  {									\
+    FILE *__outfile = (b).File;						\
+    register unsigned char __buff = (b).Buff;				\
+    register unsigned char __btg = (b).Btg;
+
+#define ENCODE_BIT(b)							\
+  do {									\
+    --__btg;								\
+    if (b) __buff |= (1 << __btg);					\
+    if (!__btg)								\
+      {									\
+	putc(__buff, __outfile);					\
+	__buff = 0;							\
+	__btg = sizeof(__buff)*8;					\
+      }									\
+  } while(0)
+
+#define ENCODE_PAUSE(b)							\
+    (b).File = __outfile;						\
+    (b).Buff = __buff;							\
+    (b).Btg =  __btg;							\
+  }
+
+#define ENCODE_DONE							\
+    if (__btg != sizeof(__buff)*8)					\
+      putc(__buff,__outfile);						\
+  }
+
+
+#define DECODE_START(f)							\
+  {									\
+    FILE *__infile = f;							\
+    register unsigned char __buff = 0;					\
+    register unsigned char __btg = 0;
+
+#define DECODE_CONTINUE(b)						\
+  {									\
+    FILE *__infile = (b).File;						\
+    register unsigned char __buff = (b).Buff;				\
+    register unsigned char __btg = (b).Btg;
+
+#define DECODE_ADD_FF(b)						\
+  do {									\
+    if (!__btg)								\
+      {									\
+	register int val = getc(__infile);				\
+	__buff = val == EOF ? 0xff : val;				\
+	__btg = sizeof(__buff)*8;					\
+      }									\
+    (b) += (b) + ((__buff >> --__btg) & 1);				\
+  } while(0)
+
+#define DECODE_ADD_00(b)						\
+  do {									\
+    if (!__btg)								\
+      {									\
+	register int val = getc(__infile);				\
+	__buff = val == EOF ? 0xff : val;				\
+	__btg = sizeof(__buff)*8;					\
+      }									\
+    (b) += (b) + ((__buff >> --__btg) & 1);				\
+  } while(0)
+
+#define DECODE_BIT (__btg ? (__buff >> --__btg) & 1 :			\
+   (__buff = getc(__infile), (feof(__infile) ?				\
+    (DECODE_ERROR, 0) :							\
+    (__btg = sizeof(__buff)*8, (__buff >> --__btg) & 1))))
+
+#define DECODE_DONE	;						\
+  }
+
+#define DECODE_PAUSE(b)							\
+    (b).File = __infile;						\
+    (b).Buff = __buff;							\
+    (b).Btg =  __btg;							\
+  }
+
+
+#define DECODE_SEEK(pos)						\
+  do {									\
+    register long __new_pos = (pos);					\
+    fseek(__infile, __new_pos >> 3, 0);					\
+    __buff = getc(__infile);						\
+    __btg = 8 - (__new_pos&7);						\
+    }									\
+  while(0)
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/bitio_mem.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_mem.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_mem.c	(revision 14757)
@@ -0,0 +1,237 @@
+/**************************************************************************
+ *
+ * bitio_mem.c -- Functions for bitio to memory
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "bitio_m_mem.h"
+#include "bitio_m.h"
+
+int fprintf (FILE *, const char *,...);
+
+
+
+void 
+BIO_Mem_Encode_Start (void *buf, int rem, mem_bitio_state * bs)
+{
+  ENCODE_START (buf, rem)
+    ENCODE_PAUSE (*bs)
+}
+
+void 
+BIO_Mem_Encode_Done (mem_bitio_state * bs)
+{
+  ENCODE_CONTINUE (*bs)
+    ENCODE_DONE
+}
+
+
+void 
+BIO_Mem_Decode_Start (void *buf, int rem, mem_bitio_state * bs)
+{
+  DECODE_START (buf, rem)
+    DECODE_PAUSE (*bs)
+}
+
+
+
+
+void 
+BIO_Mem_Unary_Encode (unsigned long val, mem_bitio_state * bs,
+		      unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    UNARY_ENCODE_L (val, *bits);
+  else
+    UNARY_ENCODE (val);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Mem_Unary_Decode (mem_bitio_state * bs,
+		      unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    UNARY_DECODE_L (val, *bits);
+  else
+    UNARY_DECODE (val);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+
+
+
+void 
+BIO_Mem_Binary_Encode (unsigned long val, unsigned long b,
+		       mem_bitio_state * bs, unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    BINARY_ENCODE_L (val, b, *bits);
+  else
+    BINARY_ENCODE (val, b);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Mem_Binary_Decode (unsigned long b, mem_bitio_state * bs,
+		       unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    BINARY_DECODE_L (val, b, *bits);
+  else
+    BINARY_DECODE (val, b);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+
+
+
+void 
+BIO_Mem_Gamma_Encode (unsigned long val, mem_bitio_state * bs,
+		      unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    GAMMA_ENCODE_L (val, *bits);
+  else
+    GAMMA_ENCODE (val);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Mem_Gamma_Decode (mem_bitio_state * bs, unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    GAMMA_DECODE_L (val, *bits);
+  else
+    GAMMA_DECODE (val);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+void 
+BIO_Mem_Delta_Encode (unsigned long val, mem_bitio_state * bs,
+		      unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    DELTA_ENCODE_L (val, *bits);
+  else
+    DELTA_ENCODE (val);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Mem_Delta_Decode (mem_bitio_state * bs, unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    DELTA_DECODE_L (val, *bits);
+  else
+    DELTA_DECODE (val);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+void 
+BIO_Mem_Elias_Encode (unsigned long val, unsigned long b, double s,
+		      mem_bitio_state * bs, unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    ELIAS_ENCODE_L (val, b, s, *bits);
+  else
+    ELIAS_ENCODE (val, b, s);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Mem_Elias_Decode (unsigned long b, double s,
+		      mem_bitio_state * bs, unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    ELIAS_DECODE_L (val, b, s, *bits);
+  else
+    ELIAS_DECODE (val, b, s);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+void 
+BIO_Mem_Bblock_Encode (unsigned long val, unsigned long b,
+		       mem_bitio_state * bs, unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    BBLOCK_ENCODE_L (val, b, *bits);
+  else
+    BBLOCK_ENCODE (val, b);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Mem_Bblock_Decode (unsigned long b, mem_bitio_state * bs,
+		       unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    BBLOCK_DECODE_L (val, b, *bits);
+  else
+    BBLOCK_DECODE (val, b);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+void 
+BIO_Mem_Decode_Seek (unsigned long pos, mem_bitio_state * bs)
+{
+  DECODE_CONTINUE (*bs)
+    DECODE_SEEK (pos);
+  DECODE_PAUSE (*bs)
+}
Index: /indexers/branches/3.03a/mg/lib/bitio_mem.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_mem.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_mem.h	(revision 14757)
@@ -0,0 +1,103 @@
+/**************************************************************************
+ *
+ * bitio_mem.h -- Functions for bitio to memory
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains function definitions for doing bitwise input and output
+ *  of numbers on an array of chars. These routines are faster than the ones 
+ *  in "mems" files. But with these routines you cannot mix reads and writes 
+ *  on the array of chars, or multiple write, at the same time and guarantee
+ *  them to work, also you cannot seek to a point and do a write. The decode
+ *  routine can detect when you run off the end of the array and will produce
+ *  an approate error message, and the encode routine will stop when it gets
+ *  to the end of the character array. 
+ *
+ *
+ **************************************************************************/
+
+
+#ifndef H_BITIO_MEM
+#define H_BITIO_MEM
+
+
+
+typedef struct mem_bitio_state
+  {
+    unsigned char *Base;
+    unsigned char *Pos;
+    int Remaining;
+    unsigned char Buff;
+    unsigned char Btg;
+  }
+mem_bitio_state;
+
+
+/* NOTE : All bytes are filled high bit first */
+
+
+void BIO_Mem_Encode_Start (void *buf, int rem, mem_bitio_state * bs);
+void BIO_Mem_Encode_Done (mem_bitio_state * bs);
+
+
+
+void BIO_Mem_Decode_Start (void *buf, int rem, mem_bitio_state * bs);
+
+
+
+void BIO_Mem_Unary_Encode (unsigned long val, mem_bitio_state * bs,
+			   unsigned long *bits);
+unsigned long BIO_Mem_Unary_Decode (mem_bitio_state * bs,
+				    unsigned long *bits);
+
+
+
+void BIO_Mem_Binary_Encode (unsigned long val, unsigned long b,
+			    mem_bitio_state * bs, unsigned long *bits);
+unsigned long BIO_Mem_Binary_Decode (unsigned long b, mem_bitio_state * bs,
+				     unsigned long *bits);
+
+
+
+void BIO_Mem_Gamma_Encode (unsigned long val, mem_bitio_state * bs,
+			   unsigned long *bits);
+unsigned long BIO_Mem_Gamma_Decode (mem_bitio_state * bs, unsigned long *bits);
+
+
+
+void BIO_Mem_Delta_Encode (unsigned long val, mem_bitio_state * bs,
+			   unsigned long *bits);
+unsigned long BIO_Mem_Delta_Decode (mem_bitio_state * bs, unsigned long *bits);
+
+
+void BIO_Mem_Elias_Encode (unsigned long val, unsigned long b, double s,
+			   mem_bitio_state * bs, unsigned long *bits);
+unsigned long BIO_Mem_Elias_Decode (unsigned long b, double s,
+				 mem_bitio_state * bs, unsigned long *bits);
+
+
+void BIO_Mem_Bblock_Encode (unsigned long val, unsigned long b,
+			    mem_bitio_state * bs, unsigned long *bits);
+unsigned long BIO_Mem_Bblock_Decode (unsigned long b, mem_bitio_state * bs,
+				     unsigned long *bits);
+
+
+void BIO_Mem_Decode_Seek (unsigned long pos, mem_bitio_state * bs);
+
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/bitio_mems.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_mems.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_mems.c	(revision 14757)
@@ -0,0 +1,247 @@
+/**************************************************************************
+ *
+ * bitio_mems.c -- Functions for bitio to memory (random access)
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "bitio_m_mems.h"
+#include "bitio_m.h"
+
+int fprintf (FILE *, const char *,...);
+
+
+
+void 
+BIO_Mems_Encode_Start (unsigned char *buf, unsigned long pos,
+		       mems_bitio_state * bs)
+{
+  ENCODE_START (buf, pos)
+    ENCODE_PAUSE (*bs)
+}
+
+void 
+BIO_Mems_Encode_Done (mems_bitio_state * bs)
+{
+  ENCODE_CONTINUE (*bs)
+    ENCODE_DONE
+}
+
+
+void 
+BIO_Mems_Decode_Start (unsigned char *buf, unsigned long pos,
+		       mems_bitio_state * bs)
+{
+  DECODE_START (buf, pos)
+    DECODE_PAUSE (*bs)
+}
+
+
+
+
+void 
+BIO_Mems_Unary_Encode (unsigned long val, mems_bitio_state * bs,
+		       unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    UNARY_ENCODE_L (val, *bits);
+  else
+    UNARY_ENCODE (val);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Mems_Unary_Decode (mems_bitio_state * bs,
+		       unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    UNARY_DECODE_L (val, *bits);
+  else
+    UNARY_DECODE (val);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+
+
+
+void 
+BIO_Mems_Binary_Encode (unsigned long val, unsigned long b,
+			mems_bitio_state * bs, unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    BINARY_ENCODE_L (val, b, *bits);
+  else
+    BINARY_ENCODE (val, b);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Mems_Binary_Decode (unsigned long b, mems_bitio_state * bs,
+			unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    BINARY_DECODE_L (val, b, *bits);
+  else
+    BINARY_DECODE (val, b);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+
+
+
+void 
+BIO_Mems_Gamma_Encode (unsigned long val, mems_bitio_state * bs,
+		       unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    GAMMA_ENCODE_L (val, *bits);
+  else
+    GAMMA_ENCODE (val);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Mems_Gamma_Decode (mems_bitio_state * bs, unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    GAMMA_DECODE_L (val, *bits);
+  else
+    GAMMA_DECODE (val);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+void 
+BIO_Mems_Delta_Encode (unsigned long val, mems_bitio_state * bs,
+		       unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    DELTA_ENCODE_L (val, *bits);
+  else
+    DELTA_ENCODE (val);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Mems_Delta_Decode (mems_bitio_state * bs, unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    DELTA_DECODE_L (val, *bits);
+  else
+    DELTA_DECODE (val);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+void 
+BIO_Mems_Elias_Encode (unsigned long val, unsigned long b, double s,
+		       mems_bitio_state * bs, unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    ELIAS_ENCODE_L (val, b, s, *bits);
+  else
+    ELIAS_ENCODE (val, b, s);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Mems_Elias_Decode (unsigned long b, double s,
+		       mems_bitio_state * bs, unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    ELIAS_DECODE_L (val, b, s, *bits);
+  else
+    ELIAS_DECODE (val, b, s);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+void 
+BIO_Mems_Bblock_Encode (unsigned long val, unsigned long b,
+			mems_bitio_state * bs, unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    BBLOCK_ENCODE_L (val, b, *bits);
+  else
+    BBLOCK_ENCODE (val, b);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Mems_Bblock_Decode (unsigned long b, mems_bitio_state * bs,
+			unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    BBLOCK_DECODE_L (val, b, *bits);
+  else
+    BBLOCK_DECODE (val, b);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+void 
+BIO_Mems_Decode_Seek (unsigned long pos, mems_bitio_state * bs)
+{
+  DECODE_CONTINUE (*bs)
+    DECODE_SEEK (pos);
+  DECODE_PAUSE (*bs)
+}
+
+void 
+BIO_Mems_Encode_Seek (unsigned long pos, mems_bitio_state * bs)
+{
+  ENCODE_CONTINUE (*bs)
+    ENCODE_SEEK (pos);
+  ENCODE_PAUSE (*bs)
+}
Index: /indexers/branches/3.03a/mg/lib/bitio_mems.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_mems.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_mems.h	(revision 14757)
@@ -0,0 +1,97 @@
+/**************************************************************************
+ *
+ * bitio_mems.h -- Functions for bitio to memory (random access)
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains function definitions for doing bitwise input and output
+ *  of numbers on an array of chars. These routines are slower than the ones 
+ *  in "mem" files. but with these routines you can mix reads and writes, or 
+ *  multiple writes,  on the array of chars at the same time and guarantee
+ *  them to work, also you can seek to a point and do a write. The decode and 
+ *  encode functions cannot detect when the end off the character is reached
+ *  and just continue processing.
+ *
+ **************************************************************************/
+
+#ifndef H_BITIO_MEMS
+#define H_BITIO_MEMS
+
+
+
+typedef struct mems_bitio_state
+  {
+    unsigned char *Base;
+    unsigned long pos;
+  }
+mems_bitio_state;
+
+
+/* NOTE : All bytes are filled high bit first */
+
+
+void BIO_Mems_Encode_Start (char *buf, unsigned long pos, mems_bitio_state * bs);
+void BIO_Mems_Encode_Done (mems_bitio_state * bs);
+
+
+
+void BIO_Mems_Decode_Start (void *buf, unsigned long pos, mems_bitio_state * bs);
+
+
+
+void BIO_Mems_Unary_Encode (unsigned long val, mems_bitio_state * bs,
+			    unsigned long *bits);
+unsigned long BIO_Mems_Unary_Decode (mems_bitio_state * bs,
+				     unsigned long *bits);
+
+
+
+void BIO_Mems_Binary_Encode (unsigned long val, unsigned long b,
+			     mems_bitio_state * bs, unsigned long *bits);
+unsigned long BIO_Mems_Binary_Decode (unsigned long b, mems_bitio_state * bs,
+				      unsigned long *bits);
+
+
+
+void BIO_Mems_Gamma_Encode (unsigned long val, mems_bitio_state * bs,
+			    unsigned long *bits);
+unsigned long BIO_Mems_Gamma_Decode (mems_bitio_state * bs, unsigned long *bits);
+
+
+
+void BIO_Mems_Delta_Encode (unsigned long val, mems_bitio_state * bs,
+			    unsigned long *bits);
+unsigned long BIO_Mems_Delta_Decode (mems_bitio_state * bs, unsigned long *bits);
+
+
+void BIO_Mems_Elias_Encode (unsigned long val, unsigned long b, double s,
+			    mems_bitio_state * bs, unsigned long *bits);
+unsigned long BIO_Mems_Elias_Decode (unsigned long b, double s,
+				mems_bitio_state * bs, unsigned long *bits);
+
+
+void BIO_Mems_Bblock_Encode (unsigned long val, unsigned long b,
+			     mems_bitio_state * bs, unsigned long *bits);
+unsigned long BIO_Mems_Bblock_Decode (unsigned long b, mems_bitio_state * bs,
+				      unsigned long *bits);
+
+
+void BIO_Mems_Decode_Seek (unsigned long pos, mems_bitio_state * bs);
+
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/bitio_random.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_random.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_random.c	(revision 14757)
@@ -0,0 +1,305 @@
+/*************************************************************************
+ *
+ * bitio_random.c -- Functions for bitio to a file (random access)
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "memlib.h"
+
+#include "longlong.h"
+
+#include "bitio_m_random.h"
+#include "bitio_m.h"
+
+
+void 
+BIO_Random_Start (FILE * f, unsigned long len,
+		  random_bitio_state * bs)
+{
+  ENCODE_START (f, len)
+    ENCODE_PAUSE (*bs)
+}
+
+void 
+BIO_Random_Done (random_bitio_state * bs)
+{
+  ENCODE_CONTINUE (*bs)
+    ENCODE_DONE
+}
+
+void 
+BIO_Random_Encode_Bit (int bit, random_bitio_state * bs)
+{
+  ENCODE_CONTINUE (*bs)
+    ENCODE_BIT (bit);
+  ENCODE_PAUSE (*bs)
+}
+
+int 
+BIO_Random_Decode_Bit (random_bitio_state * bs)
+{
+  register int val;
+  DECODE_CONTINUE (*bs)
+    val = DECODE_BIT;
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+void 
+BIO_Random_Unary_Encode (unsigned long val, random_bitio_state * bs,
+			 unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    UNARY_ENCODE_L (val, *bits);
+  else
+    UNARY_ENCODE (val);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Random_Unary_Decode (random_bitio_state * bs,
+			 unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    UNARY_DECODE_L (val, *bits);
+  else
+    UNARY_DECODE (val);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+
+
+
+void 
+BIO_Random_Binary_Encode (unsigned long val, unsigned long b,
+			  random_bitio_state * bs, unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    BINARY_ENCODE_L (val, b, *bits);
+  else
+    BINARY_ENCODE (val, b);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Random_Binary_Decode (unsigned long b,
+			  random_bitio_state * bs,
+			  unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    BINARY_DECODE_L (val, b, *bits);
+  else
+    BINARY_DECODE (val, b);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+
+
+
+void 
+BIO_Random_Gamma_Encode (unsigned long val, random_bitio_state * bs,
+			 unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    GAMMA_ENCODE_L (val, *bits);
+  else
+    GAMMA_ENCODE (val);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Random_Gamma_Decode (random_bitio_state * bs,
+			 unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    GAMMA_DECODE_L (val, *bits);
+  else
+    GAMMA_DECODE (val);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+void 
+BIO_Random_Delta_Encode (unsigned long val, random_bitio_state * bs,
+			 unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    DELTA_ENCODE_L (val, *bits);
+  else
+    DELTA_ENCODE (val);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Random_Delta_Decode (random_bitio_state * bs,
+			 unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    DELTA_DECODE_L (val, *bits);
+  else
+    DELTA_DECODE (val);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+void 
+BIO_Random_Elias_Encode (unsigned long val, unsigned long b, double s,
+			 random_bitio_state * bs, unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    ELIAS_ENCODE_L (val, b, s, *bits);
+  else
+    ELIAS_ENCODE (val, b, s);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Random_Elias_Decode (unsigned long b, double s,
+			 random_bitio_state * bs,
+			 unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    ELIAS_DECODE_L (val, b, s, *bits);
+  else
+    ELIAS_DECODE (val, b, s);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+void 
+BIO_Random_Bblock_Encode (unsigned long val, unsigned long b,
+			  random_bitio_state * bs, unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    BBLOCK_ENCODE_L (val, b, *bits);
+  else
+    BBLOCK_ENCODE (val, b);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Random_Bblock_Decode (unsigned long b,
+			  random_bitio_state * bs,
+			  unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    BBLOCK_DECODE_L (val, b, *bits);
+  else
+    BBLOCK_DECODE (val, b);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+void 
+BIO_Random_Seek (unsigned long pos, random_bitio_state * bs)
+{
+  ENCODE_CONTINUE (*bs)
+    ENCODE_SEEK (pos);
+  ENCODE_PAUSE (*bs)
+}
+void 
+BIO_Random_Flush (random_bitio_state * bs)
+{
+  ENCODE_CONTINUE (*bs)
+    ENCODE_FLUSH;
+  ENCODE_PAUSE (*bs)
+}
+
+unsigned long 
+BIO_Random_Tell (random_bitio_state * bs)
+{
+  register unsigned long t;
+  ENCODE_CONTINUE (*bs)
+    t = ENCODE_TELL;
+  ENCODE_PAUSE (*bs)
+    return (t);
+}
+
+#ifdef USE_LONG_LONG
+
+void 
+BIO_Random_Seek_LL (mg_ullong pos, random_bitio_state * bs)
+{
+  ENCODE_CONTINUE(*bs)
+
+    if ((((pos) >> 3) >= (mg_ullong)__base) &&
+	((((pos)+7) >> 3) < (mg_ullong)(__base + __len)))
+      {
+	__pos = (long)((pos) - (mg_ullong)(__base << 3));
+      }
+    else
+      {
+        ENCODE_FLUSH;
+	__base = (long)(((pos) >> (__sft+3)) << __sft);
+	
+	fseek(__file,__base,0);
+	fread(__buf,1,__len,__file);
+	__pos = (long)((pos) & ((8 << __sft)-1));
+      }
+  
+  ENCODE_PAUSE(*bs)
+}
+
+mg_ullong 
+BIO_Random_Tell_LL (random_bitio_state * bs)
+{
+  mg_ullong t;
+  ENCODE_CONTINUE(*bs)
+    t = (((mg_ullong)__base) << 3ull) + __pos;
+  ENCODE_PAUSE(*bs)
+  return(t);  
+}
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/bitio_random.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_random.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_random.h	(revision 14757)
@@ -0,0 +1,125 @@
+/**************************************************************************
+ *
+ * bitio_random.h -- Functions for bitio to a file (random access)
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains function definitions for doing bitwise input and output
+ *  of numbers on an array of chars. These routines are slower than the ones 
+ *  in "mem" files. but with these routines you can mix reads and writes, or 
+ *  multiple writes,  on the array of chars at the same time and guarantee
+ *  them to work, also you can seek to a point and do a write. The decode and 
+ *  encode functions cannot detect when the end off the character is reached
+ *  and just continue processing.
+ *
+ *  Modified:
+ *   - long long seek and tell ops
+ *     (1999-08-03 Tim Bell <bhat@cs.mu.oz.au>)
+ **************************************************************************/
+
+#ifndef H_BITIO_RANDOM
+#define H_BITIO_RANDOM
+
+#include "longlong.h"
+
+
+typedef struct random_bitio_state
+  {
+    FILE *File;
+    unsigned char *Buf;
+    unsigned long Base;
+    unsigned long Used;
+    unsigned long pos;
+    unsigned long len;
+    unsigned long sft;
+  }
+random_bitio_state;
+
+
+/* NOTE : All bytes are filled high bit first */
+
+
+void BIO_Random_Start (FILE * f, unsigned long len,
+		       random_bitio_state * bs);
+void BIO_Random_Done (random_bitio_state * bs);
+
+
+
+void BIO_Random_Decode_Start (void *buf, unsigned long pos,
+			      random_bitio_state * bs);
+
+void BIO_Random_Encode_Bit (int bit, random_bitio_state * bs);
+
+int BIO_Random_Decode_Bit (random_bitio_state * bs);
+
+
+void BIO_Random_Unary_Encode (unsigned long val, random_bitio_state * bs,
+			      unsigned long *bits);
+unsigned long BIO_Random_Unary_Decode (random_bitio_state * bs,
+				       unsigned long *bits);
+
+
+
+void BIO_Random_Binary_Encode (unsigned long val, unsigned long b,
+			       random_bitio_state * bs, unsigned long *bits);
+unsigned long BIO_Random_Binary_Decode (unsigned long b, random_bitio_state * bs,
+					unsigned long *bits);
+
+
+
+void BIO_Random_Gamma_Encode (unsigned long val, random_bitio_state * bs,
+			      unsigned long *bits);
+unsigned long BIO_Random_Gamma_Decode (random_bitio_state * bs,
+				       unsigned long *bits);
+
+
+
+void BIO_Random_Delta_Encode (unsigned long val, random_bitio_state * bs,
+			      unsigned long *bits);
+unsigned long BIO_Random_Delta_Decode (random_bitio_state * bs,
+				       unsigned long *bits);
+
+
+void BIO_Random_Elias_Encode (unsigned long val, unsigned long b, double s,
+			      random_bitio_state * bs, unsigned long *bits);
+unsigned long BIO_Random_Elias_Decode (unsigned long b, double s,
+				       random_bitio_state * bs,
+				       unsigned long *bits);
+
+
+void BIO_Random_Bblock_Encode (unsigned long val, unsigned long b,
+			       random_bitio_state * bs, unsigned long *bits);
+unsigned long BIO_Random_Bblock_Decode (unsigned long b,
+					random_bitio_state * bs,
+					unsigned long *bits);
+
+
+void BIO_Random_Seek (unsigned long pos, random_bitio_state * bs);
+
+void BIO_Random_Flush (random_bitio_state * bs);
+
+unsigned long BIO_Random_Tell (random_bitio_state * bs);
+
+#ifdef USE_LONG_LONG
+
+void BIO_Random_Seek_LL (mg_ullong pos, random_bitio_state * bs);
+mg_ullong BIO_Random_Tell_LL (random_bitio_state * bs);
+
+#endif /* USE_LONG_LONG */
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/bitio_stdio.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_stdio.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_stdio.c	(revision 14757)
@@ -0,0 +1,262 @@
+/**************************************************************************
+ *
+ * bitio_stdio.c -- Functions for bitio to a file
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "bitio_m_stdio.h"
+#include "bitio_m.h"
+
+
+
+void 
+BIO_Stdio_Encode_Start (FILE * f, stdio_bitio_state * bs)
+{
+  ENCODE_START (f)
+    ENCODE_PAUSE (*bs)
+}
+
+void 
+BIO_Stdio_Encode_Done (stdio_bitio_state * bs)
+{
+  ENCODE_CONTINUE (*bs)
+    ENCODE_DONE
+}
+
+
+void 
+BIO_Stdio_Decode_Start (FILE * f, stdio_bitio_state * bs)
+{
+  DECODE_START (f)
+    DECODE_PAUSE (*bs)
+}
+
+void 
+BIO_Stdio_Encode_Bit (int bit, stdio_bitio_state * bs)
+{
+  ENCODE_CONTINUE (*bs)
+    ENCODE_BIT (bit);
+  ENCODE_PAUSE (*bs)
+}
+
+
+int 
+BIO_Stdio_Decode_Bit (stdio_bitio_state * bs)
+{
+  register int val;
+  DECODE_CONTINUE (*bs)
+    val = DECODE_BIT;
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+void 
+BIO_Stdio_Unary_Encode (unsigned long val, stdio_bitio_state * bs,
+			unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    UNARY_ENCODE_L (val, *bits);
+  else
+    UNARY_ENCODE (val);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Stdio_Unary_Decode (stdio_bitio_state * bs,
+			unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    UNARY_DECODE_L (val, *bits);
+  else
+    UNARY_DECODE (val);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+
+
+
+void 
+BIO_Stdio_Binary_Encode (unsigned long val, unsigned long b,
+			 stdio_bitio_state * bs, unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    BINARY_ENCODE_L (val, b, *bits);
+  else
+    BINARY_ENCODE (val, b);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Stdio_Binary_Decode (unsigned long b, stdio_bitio_state * bs,
+			 unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    BINARY_DECODE_L (val, b, *bits);
+  else
+    BINARY_DECODE (val, b);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+
+
+
+void 
+BIO_Stdio_Gamma_Encode (unsigned long val, stdio_bitio_state * bs,
+			unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    GAMMA_ENCODE_L (val, *bits);
+  else
+    GAMMA_ENCODE (val);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Stdio_Gamma_Decode (stdio_bitio_state * bs,
+			unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    GAMMA_DECODE_L (val, *bits);
+  else
+    GAMMA_DECODE (val);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+void 
+BIO_Stdio_Delta_Encode (unsigned long val, stdio_bitio_state * bs,
+			unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    DELTA_ENCODE_L (val, *bits);
+  else
+    DELTA_ENCODE (val);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Stdio_Delta_Decode (stdio_bitio_state * bs,
+			unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    DELTA_DECODE_L (val, *bits);
+  else
+    DELTA_DECODE (val);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+
+void 
+BIO_Stdio_Elias_Encode (unsigned long val, unsigned long b, double s,
+			stdio_bitio_state * bs, unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    ELIAS_ENCODE_L (val, b, s, *bits);
+  else
+    ELIAS_ENCODE (val, b, s);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Stdio_Elias_Decode (unsigned long b, double s,
+			stdio_bitio_state * bs,
+			unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    ELIAS_DECODE_L (val, b, s, *bits);
+  else
+    ELIAS_DECODE (val, b, s);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+
+
+void 
+BIO_Stdio_Bblock_Encode (unsigned long val, unsigned long b,
+			 stdio_bitio_state * bs, unsigned long *bits)
+{
+  ENCODE_CONTINUE (*bs)
+    if (bits)
+    BBLOCK_ENCODE_L (val, b, *bits);
+  else
+    BBLOCK_ENCODE (val, b);
+  ENCODE_PAUSE (*bs)
+}
+
+
+unsigned long 
+BIO_Stdio_Bblock_Decode (unsigned long b, stdio_bitio_state * bs,
+			 unsigned long *bits)
+{
+  register unsigned long val;
+  DECODE_CONTINUE (*bs)
+    if (bits)
+    BBLOCK_DECODE_L (val, b, *bits);
+  else
+    BBLOCK_DECODE (val, b);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
+
+void 
+BIO_Stdio_Decode_Seek (unsigned long pos, stdio_bitio_state * bs)
+{
+  DECODE_CONTINUE (*bs)
+    DECODE_SEEK (pos);
+  DECODE_PAUSE (*bs)
+}
Index: /indexers/branches/3.03a/mg/lib/bitio_stdio.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/bitio_stdio.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/bitio_stdio.h	(revision 14757)
@@ -0,0 +1,104 @@
+/**************************************************************************
+ *
+ * bitio_stdio.h -- Functions for bitio to a file
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains function definitions for doing bitwise input and output
+ *  of number on a FILE*. With these function you cannot mix reads and writes
+ *  on the FILE, or multiple writes, at the same time and guarantee them to 
+ *  work, also you  cannot seek to a point and do a write. The decode function
+ *  can detect when you run off the end of the file and will produce an 
+ *  approate error message.
+ *
+ *
+ **************************************************************************/
+
+#ifndef H_BITIO_STDIO
+#define H_BITIO_STDIO
+
+
+typedef struct stdio_bitio_state
+  {
+    FILE *File;
+    unsigned char Buff;
+    unsigned char Btg;
+  }
+stdio_bitio_state;
+
+
+/* NOTE : All bytes are filled high bit first */
+
+
+void BIO_Stdio_Encode_Start (FILE * f, stdio_bitio_state * bs);
+void BIO_Stdio_Encode_Done (stdio_bitio_state * bs);
+
+
+
+void BIO_Stdio_Decode_Start (FILE * f, stdio_bitio_state * bs);
+
+
+
+void BIO_Stdio_Encode_Bit (int bit, stdio_bitio_state * bs);
+int BIO_Stdio_Decode_Bit (stdio_bitio_state * bs);
+
+
+void BIO_Stdio_Unary_Encode (unsigned long val, stdio_bitio_state * bs,
+			     unsigned long *bits);
+unsigned long BIO_Stdio_Unary_Decode (stdio_bitio_state * bs,
+				      unsigned long *bits);
+
+
+
+void BIO_Stdio_Binary_Encode (unsigned long val, unsigned long b,
+			      stdio_bitio_state * bs, unsigned long *bits);
+unsigned long BIO_Stdio_Binary_Decode (unsigned long b, stdio_bitio_state * bs,
+				       unsigned long *bits);
+
+
+
+void BIO_Stdio_Gamma_Encode (unsigned long val, stdio_bitio_state * bs,
+			     unsigned long *bits);
+unsigned long BIO_Stdio_Gamma_Decode (stdio_bitio_state * bs,
+				      unsigned long *bits);
+
+
+
+void BIO_Stdio_Delta_Encode (unsigned long val, stdio_bitio_state * bs,
+			     unsigned long *bits);
+unsigned long BIO_Stdio_Delta_Decode (stdio_bitio_state * bs,
+				      unsigned long *bits);
+
+
+
+void BIO_Stdio_Elias_Encode (unsigned long val, unsigned long b, double s,
+			     stdio_bitio_state * bs, unsigned long *bits);
+unsigned long BIO_Stdio_Elias_Decode (unsigned long b, double s,
+				      stdio_bitio_state * bs,
+				      unsigned long *bits);
+
+
+void BIO_Stdio_Bblock_Encode (unsigned long val, unsigned long b,
+			      stdio_bitio_state * bs, unsigned long *bits);
+unsigned long BIO_Stdio_Bblock_Decode (unsigned long b, stdio_bitio_state * bs,
+				       unsigned long *bits);
+
+
+void BIO_Stdio_Decode_Seek (unsigned long pos, stdio_bitio_state * bs);
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/error.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/error.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/error.c	(revision 14757)
@@ -0,0 +1,127 @@
+/* error.c -- error handler for noninteractive utilities
+   Copyright (C) 1990, 91, 92, 93, 94 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 program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>.  */
+
+#ifdef HAVE_CONFIG_H
+# ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+#  include <win32cfg.h>
+# else
+#  include <sysfuncs.h>
+# endif
+#endif
+
+#include <stdio.h>
+
+#if HAVE_VPRINTF || HAVE_DOPRNT
+# if __STDC__
+#  include <stdarg.h>
+#  define VA_START(args, lastarg) va_start(args, lastarg)
+# else
+#  include <varargs.h>
+#  define VA_START(args, lastarg) va_start(args)
+# endif
+#else
+# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
+# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
+#endif
+
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+#else
+void exit ();
+#endif
+
+/* If NULL, error will flush stdout, then print on stderr the program
+   name, a colon and a space.  Otherwise, error will call this
+   function without parameters instead.  */
+void (*error_print_progname) () = NULL;
+
+/* The calling program should define program_name and set it to the
+   name of the executing program.  */
+#if 0 /* [RB/TS:10/95] do not use program_name */
+extern char *program_name;
+#endif
+
+#if HAVE_STRERROR
+char *strerror (int errnum);
+#else
+static char *
+private_strerror (errnum)
+     int errnum;
+{
+  extern char *sys_errlist[];
+  extern int sys_nerr;
+
+  if (errnum > 0 && errnum <= sys_nerr)
+    return sys_errlist[errnum];
+  return "Unknown system error";
+}
+#define strerror private_strerror
+#endif
+
+/* Print the program name and error message MESSAGE, which is a printf-style
+   format string with optional args.
+   If ERRNUM is nonzero, print its corresponding system error message.
+   Exit with status STATUS if it is nonzero.  */
+/* VARARGS */
+
+void
+#if defined(VA_START) && __STDC__
+error (int status, int errnum, const char *message, ...)
+#else
+error (status, errnum, message, va_alist)
+     int status;
+     int errnum;
+     char *message;
+     va_dcl
+#endif
+{
+#ifdef VA_START
+  va_list args;
+#endif
+
+  if (error_print_progname)
+    (*error_print_progname) ();
+  else
+    {
+      fflush (stdout);
+#if 0 /* [RB/TS:10/95] do not use program_name */
+      fprintf (stderr, "%s: ", program_name);
+#endif
+    }
+
+#ifdef VA_START
+  VA_START (args, message);
+# if HAVE_VPRINTF
+  vfprintf (stderr, message, args);
+# else
+  _doprnt (message, args, stderr);
+# endif
+  va_end (args);
+#else
+  fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
+#endif
+
+  if (errnum)
+    fprintf (stderr, ": %s", strerror (errnum));
+  putc ('\n', stderr);
+  fflush (stderr);
+  if (status)
+    exit (status);
+}
Index: /indexers/branches/3.03a/mg/lib/filestats.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/filestats.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/filestats.c	(revision 14757)
@@ -0,0 +1,115 @@
+/**************************************************************************
+ *
+ * filestats.c -- Functions for keeping stats on file accesses
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "filestats.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+
+File *
+Fopen (char *name, char *mode, unsigned long magic)
+{
+  FILE *f;
+  File *F;
+  unsigned long m;
+  if (!(f = fopen (name, mode)))
+    return (NULL);
+  if (magic)
+    switch (*mode)
+      {
+      case 'r':
+	fread ((char *) &m, sizeof (m), 1, f);
+	NTOHUL(m);  /* [RPAP - Jan 97: Endian Ordering] */
+	if (m != magic)
+	  {
+	    fclose (f);
+	    return (NULL);
+	  }
+	break;
+      case 'w':
+	HTONUL(magic);  /* [RPAP - Jan 97: Endian Ordering] */
+	fwrite ((char *) &magic, sizeof (magic), 1, f);
+      }
+  if (!(F = Xmalloc (sizeof (File))))
+    {
+      fclose (f);
+      return (NULL);
+    }
+  F->pathname = Xstrdup (name);
+  F->name = strrchr (F->pathname, '/');
+  F->name = F->name ? F->name + 1 : F->pathname;
+  F->f = f;
+  F->Current.NumSeeks = F->Current.NumReads = F->Current.NumBytes = 0;
+  F->Cumulative = F->Current;
+  return (F);
+}
+
+
+int 
+Fclose (File * F)
+{
+  int num;
+  if (!F)
+    return (0);
+  num = fclose (F->f);
+  if (F->pathname)
+    Xfree (F->pathname);
+  Xfree (F);
+  return (num);
+}
+
+size_t 
+Fread (void *ptr, size_t size, size_t nitems, File * F)
+{
+  int num;
+  num = fread ((char *) ptr, size, nitems, F->f);
+  F->Current.NumReads++;
+  F->Current.NumBytes += num * size;
+  return (num);
+}
+
+int 
+Fseek (File * F, long offset, int ptrname)
+{
+  int num;
+  num = fseek (F->f, offset, ptrname);
+  F->Current.NumSeeks++;
+  return (num);
+}
+
+void 
+Rewind (File * F)
+{
+  rewind (F->f);
+  F->Current.NumSeeks++;
+}
+
+
+void 
+ZeroFileStats (File * F)
+{
+  F->Cumulative.NumSeeks += F->Current.NumSeeks;
+  F->Cumulative.NumReads += F->Current.NumReads;
+  F->Cumulative.NumBytes += F->Current.NumBytes;
+  F->Current.NumSeeks = F->Current.NumReads = F->Current.NumBytes = 0;
+}
Index: /indexers/branches/3.03a/mg/lib/filestats.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/filestats.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/filestats.h	(revision 14757)
@@ -0,0 +1,65 @@
+/**************************************************************************
+ *
+ * filestats.h -- Functions for keeping stats on file accesses
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_FILESTATS
+#define H_FILESTATS
+
+#include "sysfuncs.h"
+
+typedef struct FileStats
+  {
+    unsigned long NumSeeks;
+    unsigned long NumReads;
+    unsigned long NumBytes;
+  }
+FileStats;
+
+
+
+typedef struct
+  {
+    FILE *f;
+    char *pathname;
+    char *name;
+    FileStats Current;
+    FileStats Cumulative;
+  }
+File;
+
+/* if magic is 0 no magic number is read or written */
+File *Fopen (char *name, char *mode, unsigned long magic);
+
+size_t Fread (void *ptr, size_t size, size_t nitems, File * F);
+
+int Fseek (File * F, long offset, int ptrname);
+
+void Rewind (File * F);
+
+int Fclose (File * F);
+
+#define Getc(F) (F->Current.NumReads++, F->Current.NumBytes++, getc(F->f))
+
+/* This adds the Current file stats to the Cumulative stats and then zeros
+   the Current stats */
+void ZeroFileStats (File * F);
+
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/ftruncate.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/ftruncate.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/ftruncate.c	(revision 14757)
@@ -0,0 +1,107 @@
+/* ftruncate emulations that work on some System V's.
+   This file is in the public domain.  */
+
+#ifdef HAVE_CONFIG_H
+# ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+#  include <win32cfg.h>
+# else
+#  include <sysfuncs.h>
+# endif
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+
+#ifdef F_CHSIZE
+
+int
+ftruncate (fd, length)
+     int fd;
+     off_t length;
+{
+  return fcntl (fd, F_CHSIZE, length);
+}
+
+#else /* not F_CHSIZE */
+#ifdef F_FREESP
+
+/* By William Kucharski <kucharsk@netcom.com>.  */
+
+#include <sys/stat.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+int
+ftruncate (fd, length)
+     int fd;
+     off_t length;
+{
+  struct flock fl;
+  struct stat filebuf;
+
+  if (fstat (fd, &filebuf) < 0)
+    return -1;
+
+  if (filebuf.st_size < length)
+    {
+      /* Extend file length. */
+      if (lseek (fd, (length - 1), SEEK_SET) < 0)
+	return -1;
+
+      /* Write a "0" byte. */
+      if (write (fd, "", 1) != 1)
+	return -1;
+    }
+  else
+    {
+
+      /* Truncate length. */
+
+      fl.l_whence = 0;
+      fl.l_len = 0;
+      fl.l_start = length;
+      fl.l_type = F_WRLCK;	/* write lock on file space */
+
+      /* This relies on the *undocumented* F_FREESP argument to fcntl,
+	 which truncates the file so that it ends at the position
+	 indicated by fl.l_start.  Will minor miracles never cease?  */
+
+      if (fcntl (fd, F_FREESP, &fl) < 0)
+	return -1;
+    }
+
+  return 0;
+}
+
+#else /* not F_CHSIZE nor F_FREESP */
+#ifdef HAVE_CHSIZE
+
+int
+ftruncate (fd, length)
+     int fd;
+     off_t length;
+{
+  return chsize (fd, length);
+}
+
+#else /* not F_CHSIZE nor F_FREESP nor HAVE_CHSIZE */
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+int
+ftruncate (fd, length)
+     int fd;
+     off_t length;
+{
+  errno = EIO;
+  return -1;
+}
+
+#endif /* not HAVE_CHSIZE */
+#endif /* not F_FREESP */
+#endif /* not F_CHSIZE */
Index: /indexers/branches/3.03a/mg/lib/getopt.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/getopt.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/getopt.c	(revision 14757)
@@ -0,0 +1,750 @@
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+   before changing it!
+
+   Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+   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 program; if not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+#ifdef HAVE_CONFIG_H
+#include "sysfuncs.h"
+#endif
+
+#if !__STDC__ && !defined(const) && IN_GCC
+#define const
+#endif
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.  */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef	__GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+   contain conflicting prototypes for getopt.  */
+#include <stdlib.h>
+#endif /* GNU C library.  */
+
+/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
+   long-named option.  Because this is not POSIX.2 compliant, it is
+   being phased out.  */
+/* #define GETOPT_COMPAT */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable POSIXLY_CORRECT disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg = 0;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* XXX 1003.2 says this must be 1 before any call.  */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   If the caller did not specify anything,
+   the default is REQUIRE_ORDER if the environment variable
+   POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+   REQUIRE_ORDER means don't recognize them as options;
+   stop option processing when the first non-option is seen.
+   This is what Unix does.
+   This mode of operation is selected by either setting the environment
+   variable POSIXLY_CORRECT, or using `+' as the first character
+   of the list of option characters.
+
+   PERMUTE is the default.  We permute the contents of ARGV as we scan,
+   so that eventually all the non-options are at the end.  This allows options
+   to be given in any order, even with programs that were not written to
+   expect this.
+
+   RETURN_IN_ORDER is an option available to programs that were written
+   to expect options and other ARGV-elements in any order and that care about
+   the ordering of the two.  We describe each non-option ARGV-element
+   as if it were the argument of an option with character code 1.
+   Using `-' as the first character of the list of option characters
+   selects this mode of operation.
+
+   The special argument `--' forces an end of option-scanning regardless
+   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
+
+static enum
+  {
+    REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+  }
+ordering;
+
+
+#ifdef	__GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+   because there are many ways it can cause trouble.
+   On some systems, it contains special magic macros that don't work
+   in GCC.  */
+#include <string.h>
+#define	my_index	strchr
+#else
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+     const char *str;
+     int chr;
+{
+  while (*str)
+    {
+      if (*str == chr)
+	return (char *) str;
+      str++;
+    }
+  return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+   If not using GCC, it is ok not to declare it.  */
+#ifdef __GNUC__
+#ifdef IN_GCC
+#include "gstddef.h"
+#else
+#include <stddef.h>
+#endif
+extern size_t strlen (const char *);
+#endif
+
+#endif /* GNU C library.  */
+
+
+/* Handle permutation of arguments.  */
+
+/* Describe the part of ARGV that contains non-options that have
+   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+   `last_nonopt' is the index after the last of them.  */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+static void
+exchange (argv)
+     char **argv;
+{
+  int bottom = first_nonopt;
+  int middle = last_nonopt;
+  int top = optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+	{
+	  /* Bottom segment is the short one.  */
+	  int len = middle - bottom;
+	  register int i;
+
+	  /* Swap it with the top part of the top segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[top - (middle - bottom) + i];
+	      argv[top - (middle - bottom) + i] = tem;
+	    }
+	  /* Exclude the moved bottom segment from further swapping.  */
+	  top -= len;
+	}
+      else
+	{
+	  /* Top segment is the short one.  */
+	  int len = top - middle;
+	  register int i;
+
+	  /* Swap it with the bottom part of the bottom segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[middle + i];
+	      argv[middle + i] = tem;
+	    }
+	  /* Exclude the moved top segment from further swapping.  */
+	  bottom += len;
+	}
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  first_nonopt += (optind - last_nonopt);
+  last_nonopt = optind;
+}
+
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns `EOF'.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.  */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+     const struct option *longopts;
+     int *longind;
+     int long_only;
+{
+  int option_index;
+
+  optarg = 0;
+
+  /* Initialize the internal data when the first call is made.
+     Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  if (optind == 0)
+    {
+      first_nonopt = last_nonopt = optind = 1;
+
+      nextchar = NULL;
+
+      /* Determine how to handle the ordering of options and nonoptions.  */
+
+      if (optstring[0] == '-')
+	{
+	  ordering = RETURN_IN_ORDER;
+	  ++optstring;
+	}
+      else if (optstring[0] == '+')
+	{
+	  ordering = REQUIRE_ORDER;
+	  ++optstring;
+	}
+      else if (getenv ("POSIXLY_CORRECT") != NULL)
+	ordering = REQUIRE_ORDER;
+      else
+	ordering = PERMUTE;
+    }
+
+  if (nextchar == NULL || *nextchar == '\0')
+    {
+      if (ordering == PERMUTE)
+	{
+	  /* If we have just processed some options following some non-options,
+	     exchange them so that the options come first.  */
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (last_nonopt != optind)
+	    first_nonopt = optind;
+
+	  /* Now skip any additional non-options
+	     and extend the range of non-options previously skipped.  */
+
+	  while (optind < argc
+		 && (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+		 && (longopts == NULL
+		     || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+	    )
+	    optind++;
+	  last_nonopt = optind;
+	}
+
+      /* Special ARGV-element `--' means premature end of options.
+         Skip it like a null option,
+         then exchange with previous non-options as if it were an option,
+         then skip everything else like a non-option.  */
+
+      if (optind != argc && !strcmp (argv[optind], "--"))
+	{
+	  optind++;
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (first_nonopt == last_nonopt)
+	    first_nonopt = optind;
+	  last_nonopt = argc;
+
+	  optind = argc;
+	}
+
+      /* If we have done all the ARGV-elements, stop the scan
+         and back over any non-options that we skipped and permuted.  */
+
+      if (optind == argc)
+	{
+	  /* Set the next-arg-index to point at the non-options
+	     that we previously skipped, so the caller will digest them.  */
+	  if (first_nonopt != last_nonopt)
+	    optind = first_nonopt;
+	  return EOF;
+	}
+
+      /* If we have come to a non-option and did not permute it,
+         either stop the scan or describe it to the caller and pass it by.  */
+
+      if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+	  && (longopts == NULL
+	      || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+	)
+	{
+	  if (ordering == REQUIRE_ORDER)
+	    return EOF;
+	  optarg = argv[optind++];
+	  return 1;
+	}
+
+      /* We have found another option-ARGV-element.
+         Start decoding its characters.  */
+
+      nextchar = (argv[optind] + 1
+		  + (longopts != NULL && argv[optind][1] == '-'));
+    }
+
+  if (longopts != NULL
+      && ((argv[optind][0] == '-'
+	   && (argv[optind][1] == '-' || long_only))
+#ifdef GETOPT_COMPAT
+	  || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+      ))
+    {
+      const struct option *p;
+      char *s = nextchar;
+      int exact = 0;
+      int ambig = 0;
+      const struct option *pfound = NULL;
+      int indfound;
+
+      while (*s && *s != '=')
+	s++;
+
+      /* Test all options for either exact match or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name;
+	   p++, option_index++)
+	if (!strncmp (p->name, nextchar, s - nextchar))
+	  {
+	    if (s - nextchar == strlen (p->name))
+	      {
+		/* Exact match found.  */
+		pfound = p;
+		indfound = option_index;
+		exact = 1;
+		break;
+	      }
+	    else if (pfound == NULL)
+	      {
+		/* First nonexact match found.  */
+		pfound = p;
+		indfound = option_index;
+	      }
+	    else
+	      /* Second nonexact match found.  */
+	      ambig = 1;
+	  }
+
+      if (ambig && !exact)
+	{
+	  if (opterr)
+	    fprintf (stderr, "%s: option `%s' is ambiguous\n",
+		     argv[0], argv[optind]);
+	  nextchar += strlen (nextchar);
+	  optind++;
+	  return '?';
+	}
+
+      if (pfound != NULL)
+	{
+	  option_index = indfound;
+	  optind++;
+	  if (*s)
+	    {
+	      /* Don't test has_arg with >, because some C compilers don't
+	         allow it to be used on enums.  */
+	      if (pfound->has_arg)
+		optarg = s + 1;
+	      else
+		{
+		  if (opterr)
+		    {
+		      if (argv[optind - 1][1] == '-')
+			/* --option */
+			fprintf (stderr,
+			    "%s: option `--%s' doesn't allow an argument\n",
+				 argv[0], pfound->name);
+		      else
+			/* +option or -option */
+			fprintf (stderr,
+			    "%s: option `%c%s' doesn't allow an argument\n",
+				 argv[0], argv[optind - 1][0], pfound->name);
+		    }
+		  nextchar += strlen (nextchar);
+		  return '?';
+		}
+	    }
+	  else if (pfound->has_arg == 1)
+	    {
+	      if (optind < argc)
+		optarg = argv[optind++];
+	      else
+		{
+		  if (opterr)
+		    fprintf (stderr, "%s: option `%s' requires an argument\n",
+			     argv[0], argv[optind - 1]);
+		  nextchar += strlen (nextchar);
+		  return optstring[0] == ':' ? ':' : '?';
+		}
+	    }
+	  nextchar += strlen (nextchar);
+	  if (longind != NULL)
+	    *longind = option_index;
+	  if (pfound->flag)
+	    {
+	      *(pfound->flag) = pfound->val;
+	      return 0;
+	    }
+	  return pfound->val;
+	}
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+         or the option starts with '--' or is not a valid short
+         option, then it's an error.
+         Otherwise interpret it as a short option.  */
+      if (!long_only || argv[optind][1] == '-'
+#ifdef GETOPT_COMPAT
+	  || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+	  || my_index (optstring, *nextchar) == NULL)
+	{
+	  if (opterr)
+	    {
+	      if (argv[optind][1] == '-')
+		/* --option */
+		fprintf (stderr, "%s: unrecognized option `--%s'\n",
+			 argv[0], nextchar);
+	      else
+		/* +option or -option */
+		fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+			 argv[0], argv[optind][0], nextchar);
+	    }
+	  nextchar = (char *) "";
+	  optind++;
+	  return '?';
+	}
+    }
+
+  /* Look at and handle the next option-character.  */
+
+  {
+    char c = *nextchar++;
+    char *temp = my_index (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*nextchar == '\0')
+      ++optind;
+
+    if (temp == NULL || c == ':')
+      {
+	if (opterr)
+	  {
+#if 0
+	    if (c < 040 || c >= 0177)
+	      fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
+		       argv[0], c);
+	    else
+	      fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
+#else
+	    /* 1003.2 specifies the format of this message.  */
+	    fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+#endif
+	  }
+	optopt = c;
+	return '?';
+      }
+    if (temp[1] == ':')
+      {
+	if (temp[2] == ':')
+	  {
+	    /* This is an option that accepts an argument optionally.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		optind++;
+	      }
+	    else
+	      optarg = 0;
+	    nextchar = NULL;
+	  }
+	else
+	  {
+	    /* This is an option that requires an argument.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		/* If we end this ARGV-element by taking the rest as an arg,
+		   we must advance to the next element now.  */
+		optind++;
+	      }
+	    else if (optind == argc)
+	      {
+		if (opterr)
+		  {
+#if 0
+		    fprintf (stderr, "%s: option `-%c' requires an argument\n",
+			     argv[0], c);
+#else
+		    /* 1003.2 specifies the format of this message.  */
+		    fprintf (stderr, "%s: option requires an argument -- %c\n",
+			     argv[0], c);
+#endif
+		  }
+		optopt = c;
+		if (optstring[0] == ':')
+		  c = ':';
+		else
+		  c = '?';
+	      }
+	    else
+	      /* We already incremented `optind' once;
+	         increment it again when taking next ARGV-elt as argument.  */
+	      optarg = argv[optind++];
+	    nextchar = NULL;
+	  }
+      }
+    return c;
+  }
+}
+
+int
+getopt (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  return _getopt_internal (argc, argv, optstring,
+			   (const struct option *) 0,
+			   (int *) 0,
+			   0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__.  */
+
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == EOF)
+	break;
+
+      switch (c)
+	{
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
Index: /indexers/branches/3.03a/mg/lib/getopt.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/getopt.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/getopt.h	(revision 14757)
@@ -0,0 +1,130 @@
+/* Declarations for getopt.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993 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 program; if not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef	__cplusplus
+extern "C"
+{
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+  extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+  extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+  extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+  extern int optopt;
+
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument          (or 0) if the option does not take an argument,
+   required_argument    (or 1) if the option requires an argument,
+   optional_argument    (or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+  struct option
+    {
+#if	__STDC__
+      const char *name;
+#else
+      char *name;
+#endif
+      /* has_arg can't be an enum because some compilers complain about
+         type mismatches in all the code that assumes it is an int.  */
+      int has_arg;
+      int *flag;
+      int val;
+    };
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+#define	no_argument		0
+#define required_argument	1
+#define optional_argument	2
+
+#if __STDC__
+#if defined(__GNU_LIBRARY__)
+/* Many other libraries have conflicting prototypes for getopt, with
+   differences in the consts, in stdlib.h.  To avoid compilation
+   errors, only prototype getopt for the GNU C library.  */
+  extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else				/* not __GNU_LIBRARY__ */
+  extern int getopt ();
+#endif				/* not __GNU_LIBRARY__ */
+  extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+			  const struct option *longopts, int *longind);
+  extern int getopt_long_only (int argc, char *const *argv,
+			       const char *shortopts,
+			       const struct option *longopts, int *longind);
+
+/* Internal only.  Users should not call this directly.  */
+  extern int _getopt_internal (int argc, char *const *argv,
+			       const char *shortopts,
+			       const struct option *longopts, int *longind,
+			       int long_only);
+#else				/* not __STDC__ */
+  extern int getopt ();
+  extern int getopt_long ();
+  extern int getopt_long_only ();
+
+  extern int _getopt_internal ();
+#endif				/* not __STDC__ */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif				/* _GETOPT_H */
Index: /indexers/branches/3.03a/mg/lib/getopt1.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/getopt1.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/getopt1.c	(revision 14757)
@@ -0,0 +1,178 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+   Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+   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 program; if not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+#ifdef HAVE_CONFIG_H
+#include "sysfuncs.h"
+#endif
+
+#include "getopt.h"
+
+#if !__STDC__ && !defined(const) && IN_GCC
+#define const
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#else
+char *getenv ();
+#endif
+
+#ifndef	NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+     int argc;
+     char *const *argv;
+     const char *options;
+     const struct option *long_options;
+     int *opt_index;
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+   If an option that starts with '-' (not '--') doesn't match a long option,
+   but does match a short option, it is parsed as a short option
+   instead.  */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+     int argc;
+     char *const *argv;
+     const char *options;
+     const struct option *long_options;
+     int *opt_index;
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif /* _LIBC or not __GNU_LIBRARY__.  */
+
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+      int option_index = 0;
+      static struct option long_options[] =
+      {
+	{"add", 1, 0, 0},
+	{"append", 0, 0, 0},
+	{"delete", 1, 0, 0},
+	{"verbose", 0, 0, 0},
+	{"create", 0, 0, 0},
+	{"file", 1, 0, 0},
+	{0, 0, 0, 0}
+      };
+
+      c = getopt_long (argc, argv, "abc:d:0123456789",
+		       long_options, &option_index);
+      if (c == EOF)
+	break;
+
+      switch (c)
+	{
+	case 0:
+	  printf ("option %s", long_options[option_index].name);
+	  if (optarg)
+	    printf (" with arg %s", optarg);
+	  printf ("\n");
+	  break;
+
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case 'd':
+	  printf ("option d with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
Index: /indexers/branches/3.03a/mg/lib/getpagesize.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/getpagesize.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/getpagesize.h	(revision 14757)
@@ -0,0 +1,38 @@
+/* Emulate getpagesize on systems that lack it.  */
+
+#ifndef HAVE_GETPAGESIZE
+
+#ifdef VMS
+#define getpagesize() 512
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef _SC_PAGESIZE
+#define getpagesize() sysconf(_SC_PAGESIZE)
+#else
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifndef __WIN32__
+#include <sys/param.h>
+#endif
+
+#ifdef EXEC_PAGESIZE
+#define getpagesize() EXEC_PAGESIZE
+#else
+#ifdef NBPG
+#define getpagesize() NBPG * CLSIZE
+#ifndef CLSIZE
+#define CLSIZE 1
+#endif /* no CLSIZE */
+#else /* no NBPG */
+#ifdef NBPC
+#define getpagesize() NBPC
+#endif /* NBPC */
+#endif /* no NBPG */
+#endif /* no EXEC_PAGESIZE */
+#endif /* no _SC_PAGESIZE */
+
+#endif /* not HAVE_GETPAGESIZE */
Index: /indexers/branches/3.03a/mg/lib/gmalloc.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/gmalloc.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/gmalloc.c	(revision 14757)
@@ -0,0 +1,1318 @@
+/* DO NOT EDIT THIS FILE -- it is automagically generated.  -*- C -*- */
+
+#define _MALLOC_INTERNAL
+
+/* The malloc headers and source files from the C library follow here.  */
+
+/* Declarations for `malloc' and friends.
+   Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+		  Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef _MALLOC_H
+
+#define _MALLOC_H	1
+
+#ifdef _MALLOC_INTERNAL
+
+#ifdef	HAVE_CONFIG_H
+#include <sysfuncs.h>
+#endif
+
+#if	defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
+#include <string.h>
+#else
+#ifndef memset
+#define	memset(s, zero, n)	bzero ((s), (n))
+#endif
+#ifndef memcpy
+#define	memcpy(d, s, n)		bcopy ((s), (d), (n))
+#endif
+#endif
+
+#if	defined(__GNU_LIBRARY__) || __STDC__
+#include <limits.h>
+#else
+#define	CHAR_BIT	8
+#endif
+
+#ifdef	HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#endif	/* _MALLOC_INTERNAL.  */
+
+
+#ifdef	__cplusplus
+extern "C"
+{
+#endif
+
+#if defined (__cplusplus) || __STDC__
+#undef	__P
+#define	__P(args)	args
+#undef	__ptr_t
+#define	__ptr_t		void *
+#else /* Not C++ or ANSI C.  */
+#undef	__P
+#define	__P(args)	()
+#undef	const
+#define	const
+#undef	__ptr_t
+#define	__ptr_t		char *
+#endif /* C++ or ANSI C.  */
+
+#if	__STDC__
+#include <stddef.h>
+#else
+#undef	size_t
+#define	size_t		unsigned int
+#undef	ptrdiff_t
+#define	ptrdiff_t	int
+#endif
+
+#ifndef	NULL
+#define	NULL	0
+#endif
+
+
+/* Allocate SIZE bytes of memory.  */
+extern __ptr_t malloc __P ((size_t __size));
+/* Re-allocate the previously allocated block
+   in __ptr_t, making the new block SIZE bytes long.  */
+extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size));
+/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0.  */
+extern __ptr_t calloc __P ((size_t __nmemb, size_t __size));
+/* Free a block allocated by `malloc', `realloc' or `calloc'.  */
+extern void free __P ((__ptr_t __ptr));
+
+/* Allocate SIZE bytes allocated to ALIGNMENT bytes.  */
+extern __ptr_t memalign __P ((size_t __alignment, size_t __size));
+
+/* Allocate SIZE bytes on a page boundary.  */
+extern __ptr_t valloc __P ((size_t __size));
+
+
+#ifdef _MALLOC_INTERNAL
+
+/* The allocator divides the heap into blocks of fixed size; large
+   requests receive one or more whole blocks, and small requests
+   receive a fragment of a block.  Fragment sizes are powers of two,
+   and all fragments of a block are the same size.  When all the
+   fragments in a block have been freed, the block itself is freed.  */
+#define INT_BIT		(CHAR_BIT * sizeof(int))
+#define BLOCKLOG	(INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE	(1 << BLOCKLOG)
+#define BLOCKIFY(SIZE)	(((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* Determine the amount of memory spanned by the initial heap table
+   (not an absolute limit).  */
+#define HEAP		(INT_BIT > 16 ? 4194304 : 65536)
+
+/* Number of contiguous free blocks allowed to build up at the end of
+   memory before they will be returned to the system.  */
+#define FINAL_FREE_BLOCKS	8
+
+/* Data structure giving per-block information.  */
+typedef union
+  {
+    /* Heap information for a busy block.  */
+    struct
+      {
+	/* Zero for a large block, or positive giving the
+	   logarithm to the base two of the fragment size.  */
+	int type;
+	union
+	  {
+	    struct
+	      {
+		size_t nfree;	/* Free fragments in a fragmented block.  */
+		size_t first;	/* First free fragment of the block.  */
+	      } frag;
+	    /* Size (in blocks) of a large cluster.  */
+	    size_t size;
+	  } info;
+      } busy;
+    /* Heap information for a free block
+       (that may be the first of a free cluster).  */
+    struct
+      {
+	size_t size;		/* Size (in blocks) of a free cluster.  */
+	size_t next;		/* Index of next free cluster.  */
+	size_t prev;		/* Index of previous free cluster.  */
+      } free;
+  } malloc_info;
+
+/* Pointer to first block of the heap.  */
+extern char *_heapbase;
+
+/* Table indexed by block number giving per-block information.  */
+extern malloc_info *_heapinfo;
+
+/* Address to block number and vice versa.  */
+#define BLOCK(A)	(((char *) (A) - _heapbase) / BLOCKSIZE + 1)
+#define ADDRESS(B)	((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
+
+/* Current search index for the heap table.  */
+extern size_t _heapindex;
+
+/* Limit of valid info table indices.  */
+extern size_t _heaplimit;
+
+/* Doubly linked lists of free fragments.  */
+struct list
+  {
+    struct list *next;
+    struct list *prev;
+  };
+
+/* Free list headers for each fragment size.  */
+extern struct list _fraghead[];
+
+/* List of blocks allocated with `memalign' (or `valloc').  */
+struct alignlist
+  {
+    struct alignlist *next;
+    __ptr_t aligned;		/* The address that memaligned returned.  */
+    __ptr_t exact;		/* The address that malloc returned.  */
+  };
+extern struct alignlist *_aligned_blocks;
+
+/* Instrumentation.  */
+extern size_t _chunks_used;
+extern size_t _bytes_used;
+extern size_t _chunks_free;
+extern size_t _bytes_free;
+
+/* Internal version of `free' used in `morecore' (malloc.c). */
+extern void _free_internal __P ((__ptr_t __ptr));
+
+#endif /* _MALLOC_INTERNAL.  */
+
+/* Underlying allocation function; successive calls should
+   return contiguous pieces of memory.  */
+extern __ptr_t (*__morecore) __P ((ptrdiff_t __size));
+
+/* Default value of `__morecore'.  */
+extern __ptr_t __default_morecore __P ((ptrdiff_t __size));
+
+/* If not NULL, this function is called after each time
+   `__morecore' is called to increase the data size.  */
+extern void (*__after_morecore_hook) __P ((void));
+
+/* Nonzero if `malloc' has been called and done its initialization.  */
+extern int __malloc_initialized;
+
+/* Hooks for debugging versions.  */
+extern void (*__free_hook) __P ((__ptr_t __ptr));
+extern __ptr_t (*__malloc_hook) __P ((size_t __size));
+extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
+
+/* Return values for `mprobe': these are the kinds of inconsistencies that
+   `mcheck' enables detection of.  */
+enum mcheck_status
+  {
+    MCHECK_DISABLED = -1,	/* Consistency checking is not turned on.  */
+    MCHECK_OK,			/* Block is fine.  */
+    MCHECK_FREE,		/* Block freed twice.  */
+    MCHECK_HEAD,		/* Memory before the block was clobbered.  */
+    MCHECK_TAIL			/* Memory after the block was clobbered.  */
+  };
+
+/* Activate a standard collection of debugging hooks.  This must be called
+   before `malloc' is ever called.  ABORTFUNC is called with an error code
+   (see enum above) when an inconsistency is detected.  If ABORTFUNC is
+   null, the standard function prints on stderr and then calls `abort'.  */
+extern int mcheck __P ((void (*__abortfunc) __P ((enum mcheck_status))));
+
+/* Check for aberrations in a particular malloc'd block.  You must have
+   called `mcheck' already.  These are the same checks that `mcheck' does
+   when you free or reallocate a block.  */
+extern enum mcheck_status mprobe __P ((__ptr_t __ptr));
+
+/* Activate a standard collection of tracing hooks.  */
+extern void mtrace __P ((void));
+
+/* Statistics available to the user.  */
+struct mstats
+  {
+    size_t bytes_total;		/* Total size of the heap. */
+    size_t chunks_used;		/* Chunks allocated by the user. */
+    size_t bytes_used;		/* Byte total of user-allocated chunks. */
+    size_t chunks_free;		/* Chunks in the free list. */
+    size_t bytes_free;		/* Byte total of chunks in the free list. */
+  };
+
+/* Pick up the current statistics. */
+extern struct mstats mstats __P ((void));
+
+/* Call WARNFUN with a warning message when memory usage is high.  */
+extern void memory_warnings __P ((__ptr_t __start,
+				  void (*__warnfun) __P ((const char *))));
+
+
+/* Relocating allocator.  */
+
+/* Allocate SIZE bytes, and store the address in *HANDLEPTR.  */
+extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, size_t __size));
+
+/* Free the storage allocated in HANDLEPTR.  */
+extern void r_alloc_free __P ((__ptr_t *__handleptr));
+
+/* Adjust the block at HANDLEPTR to be SIZE bytes long.  */
+extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, size_t __size));
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* malloc.h  */
+/* Allocate memory on a page boundary.
+   Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#if defined (__GNU_LIBRARY__) || defined (_LIBC)
+#include <stddef.h>
+#include <sys/cdefs.h>
+extern size_t __getpagesize __P ((void));
+#else
+#include "getpagesize.h"
+#define	 __getpagesize()	getpagesize()
+#endif
+
+#ifndef	_MALLOC_INTERNAL
+#define	_MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+static size_t pagesize;
+
+__ptr_t
+valloc (size)
+     size_t size;
+{
+  if (pagesize == 0)
+    pagesize = __getpagesize ();
+
+  return memalign (pagesize, size);
+}
+/* Memory allocator `malloc'.
+   Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation
+		  Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* How to really get more memory.  */
+__ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore;
+
+/* Debugging hook for `malloc'.  */
+__ptr_t (*__malloc_hook) __P ((size_t __size));
+
+/* Pointer to the base of the first block.  */
+char *_heapbase;
+
+/* Block information table.  Allocated with align/__free (not malloc/free).  */
+malloc_info *_heapinfo;
+
+/* Number of info entries.  */
+static size_t heapsize;
+
+/* Search index in the info table.  */
+size_t _heapindex;
+
+/* Limit of valid info table indices.  */
+size_t _heaplimit;
+
+/* Free lists for each fragment size.  */
+struct list _fraghead[BLOCKLOG];
+
+/* Instrumentation.  */
+size_t _chunks_used;
+size_t _bytes_used;
+size_t _chunks_free;
+size_t _bytes_free;
+
+/* Are you experienced?  */
+int __malloc_initialized;
+
+void (*__after_morecore_hook) __P ((void));
+
+/* Aligned allocation.  */
+static __ptr_t align __P ((size_t));
+static __ptr_t
+align (size)
+     size_t size;
+{
+  __ptr_t result;
+  unsigned long int adj;
+
+  result = (*__morecore) (size);
+  adj = (unsigned long int) ((unsigned long int) ((char *) result -
+						  (char *) NULL)) % BLOCKSIZE;
+  if (adj != 0)
+    {
+      adj = BLOCKSIZE - adj;
+      (void) (*__morecore) (adj);
+      result = (char *) result + adj;
+    }
+
+  if (__after_morecore_hook)
+    (*__after_morecore_hook) ();
+
+  return result;
+}
+
+/* Set everything up and remember that we have.  */
+static int initialize __P ((void));
+static int
+initialize ()
+{
+  heapsize = HEAP / BLOCKSIZE;
+  _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));
+  if (_heapinfo == NULL)
+    return 0;
+  memset (_heapinfo, 0, heapsize * sizeof (malloc_info));
+  _heapinfo[0].free.size = 0;
+  _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
+  _heapindex = 0;
+  _heapbase = (char *) _heapinfo;
+
+  /* Account for the _heapinfo block itself in the statistics.  */
+  _bytes_used = heapsize * sizeof (malloc_info);
+  _chunks_used = 1;
+
+  __malloc_initialized = 1;
+  return 1;
+}
+
+/* Get neatly aligned memory, initializing or
+   growing the heap info table as necessary. */
+static __ptr_t morecore __P ((size_t));
+static __ptr_t
+morecore (size)
+     size_t size;
+{
+  __ptr_t result;
+  malloc_info *newinfo, *oldinfo;
+  size_t newsize;
+
+  result = align (size);
+  if (result == NULL)
+    return NULL;
+
+  /* Check if we need to grow the info table.  */
+  if ((size_t) BLOCK ((char *) result + size) > heapsize)
+    {
+      newsize = heapsize;
+      while ((size_t) BLOCK ((char *) result + size) > newsize)
+	newsize *= 2;
+      newinfo = (malloc_info *) align (newsize * sizeof (malloc_info));
+      if (newinfo == NULL)
+	{
+	  (*__morecore) (-size);
+	  return NULL;
+	}
+      memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info));
+      memset (&newinfo[heapsize], 0,
+	      (newsize - heapsize) * sizeof (malloc_info));
+      oldinfo = _heapinfo;
+      newinfo[BLOCK (oldinfo)].busy.type = 0;
+      newinfo[BLOCK (oldinfo)].busy.info.size
+	= BLOCKIFY (heapsize * sizeof (malloc_info));
+      _heapinfo = newinfo;
+      /* Account for the _heapinfo block itself in the statistics.  */
+      _bytes_used += newsize * sizeof (malloc_info);
+      ++_chunks_used;
+      _free_internal (oldinfo);
+      heapsize = newsize;
+    }
+
+  _heaplimit = BLOCK ((char *) result + size);
+  return result;
+}
+
+/* Allocate memory from the heap.  */
+__ptr_t
+malloc (size)
+     size_t size;
+{
+  __ptr_t result;
+  size_t block, blocks, lastblocks, start;
+  register size_t i;
+  struct list *next;
+
+  /* ANSI C allows `malloc (0)' to either return NULL, or to return a
+     valid address you can realloc and free (though not dereference).
+
+     It turns out that some extant code (sunrpc, at least Ultrix's version)
+     expects `malloc (0)' to return non-NULL and breaks otherwise.
+     Be compatible.  */
+
+#if	0
+  if (size == 0)
+    return NULL;
+#endif
+
+  if (__malloc_hook != NULL)
+    return (*__malloc_hook) (size);
+
+  if (!__malloc_initialized)
+    if (!initialize ())
+      return NULL;
+
+  if (size < sizeof (struct list))
+      size = sizeof (struct list);
+
+#ifdef SUNOS_LOCALTIME_BUG
+  if (size < 16)
+    size = 16;
+#endif
+
+  /* Determine the allocation policy based on the request size.  */
+  if (size <= BLOCKSIZE / 2)
+    {
+      /* Small allocation to receive a fragment of a block.
+	 Determine the logarithm to base two of the fragment size. */
+      register size_t log = 1;
+      --size;
+      while ((size /= 2) != 0)
+	++log;
+
+      /* Look in the fragment lists for a
+	 free fragment of the desired size. */
+      next = _fraghead[log].next;
+      if (next != NULL)
+	{
+	  /* There are free fragments of this size.
+	     Pop a fragment out of the fragment list and return it.
+	     Update the block's nfree and first counters. */
+	  result = (__ptr_t) next;
+	  next->prev->next = next->next;
+	  if (next->next != NULL)
+	    next->next->prev = next->prev;
+	  block = BLOCK (result);
+	  if (--_heapinfo[block].busy.info.frag.nfree != 0)
+	    _heapinfo[block].busy.info.frag.first = (unsigned long int)
+	      ((unsigned long int) ((char *) next->next - (char *) NULL)
+	       % BLOCKSIZE) >> log;
+
+	  /* Update the statistics.  */
+	  ++_chunks_used;
+	  _bytes_used += 1 << log;
+	  --_chunks_free;
+	  _bytes_free -= 1 << log;
+	}
+      else
+	{
+	  /* No free fragments of the desired size, so get a new block
+	     and break it into fragments, returning the first.  */
+	  result = malloc (BLOCKSIZE);
+	  if (result == NULL)
+	    return NULL;
+
+	  /* Link all fragments but the first into the free list.  */
+	  for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i)
+	    {
+	      next = (struct list *) ((char *) result + (i << log));
+	      next->next = _fraghead[log].next;
+	      next->prev = &_fraghead[log];
+	      next->prev->next = next;
+	      if (next->next != NULL)
+		next->next->prev = next;
+	    }
+
+	  /* Initialize the nfree and first counters for this block.  */
+	  block = BLOCK (result);
+	  _heapinfo[block].busy.type = log;
+	  _heapinfo[block].busy.info.frag.nfree = i - 1;
+	  _heapinfo[block].busy.info.frag.first = i - 1;
+
+	  _chunks_free += (BLOCKSIZE >> log) - 1;
+	  _bytes_free += BLOCKSIZE - (1 << log);
+	  _bytes_used -= BLOCKSIZE - (1 << log);
+	}
+    }
+  else
+    {
+      /* Large allocation to receive one or more blocks.
+	 Search the free list in a circle starting at the last place visited.
+	 If we loop completely around without finding a large enough
+	 space we will have to get more memory from the system.  */
+      blocks = BLOCKIFY (size);
+      start = block = _heapindex;
+      while (_heapinfo[block].free.size < blocks)
+	{
+	  block = _heapinfo[block].free.next;
+	  if (block == start)
+	    {
+	      /* Need to get more from the system.  Check to see if
+		 the new core will be contiguous with the final free
+		 block; if so we don't need to get as much.  */
+	      block = _heapinfo[0].free.prev;
+	      lastblocks = _heapinfo[block].free.size;
+	      if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
+		  (*__morecore) (0) == ADDRESS (block + lastblocks) &&
+		  (morecore ((blocks - lastblocks) * BLOCKSIZE)) != NULL)
+		{
+ 		  /* Which block we are extending (the `final free
+ 		     block' referred to above) might have changed, if
+ 		     it got combined with a freed info table.  */
+ 		  block = _heapinfo[0].free.prev;
+  		  _heapinfo[block].free.size += (blocks - lastblocks);
+		  _bytes_free += (blocks - lastblocks) * BLOCKSIZE;
+		  continue;
+		}
+	      result = morecore (blocks * BLOCKSIZE);
+	      if (result == NULL)
+		return NULL;
+	      block = BLOCK (result);
+	      _heapinfo[block].busy.type = 0;
+	      _heapinfo[block].busy.info.size = blocks;
+	      ++_chunks_used;
+	      _bytes_used += blocks * BLOCKSIZE;
+	      return result;
+	    }
+	}
+
+      /* At this point we have found a suitable free list entry.
+	 Figure out how to remove what we need from the list. */
+      result = ADDRESS (block);
+      if (_heapinfo[block].free.size > blocks)
+	{
+	  /* The block we found has a bit left over,
+	     so relink the tail end back into the free list. */
+	  _heapinfo[block + blocks].free.size
+	    = _heapinfo[block].free.size - blocks;
+	  _heapinfo[block + blocks].free.next
+	    = _heapinfo[block].free.next;
+	  _heapinfo[block + blocks].free.prev
+	    = _heapinfo[block].free.prev;
+	  _heapinfo[_heapinfo[block].free.prev].free.next
+	    = _heapinfo[_heapinfo[block].free.next].free.prev
+	    = _heapindex = block + blocks;
+	}
+      else
+	{
+	  /* The block exactly matches our requirements,
+	     so just remove it from the list. */
+	  _heapinfo[_heapinfo[block].free.next].free.prev
+	    = _heapinfo[block].free.prev;
+	  _heapinfo[_heapinfo[block].free.prev].free.next
+	    = _heapindex = _heapinfo[block].free.next;
+	  --_chunks_free;
+	}
+
+      _heapinfo[block].busy.type = 0;
+      _heapinfo[block].busy.info.size = blocks;
+      ++_chunks_used;
+      _bytes_used += blocks * BLOCKSIZE;
+      _bytes_free -= blocks * BLOCKSIZE;
+    }
+
+  return result;
+}
+
+
+#ifndef _LIBC
+
+/* On some ANSI C systems, some libc functions call _malloc, _free
+   and _realloc.  Make them use the GNU functions.  */
+
+__ptr_t
+_malloc (size)
+     size_t size;
+{
+  return malloc (size);
+}
+
+void
+_free (ptr)
+     __ptr_t ptr;
+{
+  free (ptr);
+}
+
+__ptr_t
+_realloc (ptr, size)
+     __ptr_t ptr;
+     size_t size;
+{
+  return realloc (ptr, size);
+}
+
+#endif
+/* Free a block of memory allocated by `malloc'.
+   Copyright 1990, 1991, 1992 Free Software Foundation
+		  Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* Debugging hook for free.  */
+void (*__free_hook) __P ((__ptr_t __ptr));
+
+/* List of blocks allocated by memalign.  */
+struct alignlist *_aligned_blocks = NULL;
+
+/* Return memory to the heap.
+   Like `free' but don't call a __free_hook if there is one.  */
+void
+_free_internal (ptr)
+     __ptr_t ptr;
+{
+  int type;
+  size_t block, blocks;
+  register size_t i;
+  struct list *prev, *next;
+
+  block = BLOCK (ptr);
+
+  type = _heapinfo[block].busy.type;
+  switch (type)
+    {
+    case 0:
+      /* Get as many statistics as early as we can.  */
+      --_chunks_used;
+      _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
+      _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
+
+      /* Find the free cluster previous to this one in the free list.
+	 Start searching at the last block referenced; this may benefit
+	 programs with locality of allocation.  */
+      i = _heapindex;
+      if (i > block)
+	while (i > block)
+	  i = _heapinfo[i].free.prev;
+      else
+	{
+	  do
+	    i = _heapinfo[i].free.next;
+	  while (i > 0 && i < block);
+	  i = _heapinfo[i].free.prev;
+	}
+
+      /* Determine how to link this block into the free list.  */
+      if (block == i + _heapinfo[i].free.size)
+	{
+	  /* Coalesce this block with its predecessor.  */
+	  _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
+	  block = i;
+	}
+      else
+	{
+	  /* Really link this block back into the free list.  */
+	  _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
+	  _heapinfo[block].free.next = _heapinfo[i].free.next;
+	  _heapinfo[block].free.prev = i;
+	  _heapinfo[i].free.next = block;
+	  _heapinfo[_heapinfo[block].free.next].free.prev = block;
+	  ++_chunks_free;
+	}
+
+      /* Now that the block is linked in, see if we can coalesce it
+	 with its successor (by deleting its successor from the list
+	 and adding in its size).  */
+      if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)
+	{
+	  _heapinfo[block].free.size
+	    += _heapinfo[_heapinfo[block].free.next].free.size;
+	  _heapinfo[block].free.next
+	    = _heapinfo[_heapinfo[block].free.next].free.next;
+	  _heapinfo[_heapinfo[block].free.next].free.prev = block;
+	  --_chunks_free;
+	}
+
+      /* Now see if we can return stuff to the system.  */
+      blocks = _heapinfo[block].free.size;
+      if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
+	  && (*__morecore) (0) == ADDRESS (block + blocks))
+	{
+	  register size_t bytes = blocks * BLOCKSIZE;
+	  _heaplimit -= blocks;
+	  (*__morecore) (-bytes);
+	  _heapinfo[_heapinfo[block].free.prev].free.next
+	    = _heapinfo[block].free.next;
+	  _heapinfo[_heapinfo[block].free.next].free.prev
+	    = _heapinfo[block].free.prev;
+	  block = _heapinfo[block].free.prev;
+	  --_chunks_free;
+	  _bytes_free -= bytes;
+	}
+
+      /* Set the next search to begin at this block.  */
+      _heapindex = block;
+      break;
+
+    default:
+      /* Do some of the statistics.  */
+      --_chunks_used;
+      _bytes_used -= 1 << type;
+      ++_chunks_free;
+      _bytes_free += 1 << type;
+
+      /* Get the address of the first free fragment in this block.  */
+      prev = (struct list *) ((char *) ADDRESS (block) +
+			   (_heapinfo[block].busy.info.frag.first << type));
+
+      if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
+	{
+	  /* If all fragments of this block are free, remove them
+	     from the fragment list and free the whole block.  */
+	  next = prev;
+	  for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
+	    next = next->next;
+	  prev->prev->next = next;
+	  if (next != NULL)
+	    next->prev = prev->prev;
+	  _heapinfo[block].busy.type = 0;
+	  _heapinfo[block].busy.info.size = 1;
+
+	  /* Keep the statistics accurate.  */
+	  ++_chunks_used;
+	  _bytes_used += BLOCKSIZE;
+	  _chunks_free -= BLOCKSIZE >> type;
+	  _bytes_free -= BLOCKSIZE;
+
+	  free (ADDRESS (block));
+	}
+      else if (_heapinfo[block].busy.info.frag.nfree != 0)
+	{
+	  /* If some fragments of this block are free, link this
+	     fragment into the fragment list after the first free
+	     fragment of this block. */
+	  next = (struct list *) ptr;
+	  next->next = prev->next;
+	  next->prev = prev;
+	  prev->next = next;
+	  if (next->next != NULL)
+	    next->next->prev = next;
+	  ++_heapinfo[block].busy.info.frag.nfree;
+	}
+      else
+	{
+	  /* No fragments of this block are free, so link this
+	     fragment into the fragment list and announce that
+	     it is the first free fragment of this block. */
+	  prev = (struct list *) ptr;
+	  _heapinfo[block].busy.info.frag.nfree = 1;
+	  _heapinfo[block].busy.info.frag.first = (unsigned long int)
+	    ((unsigned long int) ((char *) ptr - (char *) NULL)
+	     % BLOCKSIZE >> type);
+	  prev->next = _fraghead[type].next;
+	  prev->prev = &_fraghead[type];
+	  prev->prev->next = prev;
+	  if (prev->next != NULL)
+	    prev->next->prev = prev;
+	}
+      break;
+    }
+}
+
+/* Return memory to the heap.  */
+void
+free (ptr)
+     __ptr_t ptr;
+{
+  register struct alignlist *l;
+
+  if (ptr == NULL)
+    return;
+
+  for (l = _aligned_blocks; l != NULL; l = l->next)
+    if (l->aligned == ptr)
+      {
+	l->aligned = NULL;	/* Mark the slot in the list as free.  */
+	ptr = l->exact;
+	break;
+      }
+
+  if (__free_hook != NULL)
+    (*__free_hook) (ptr);
+  else
+    _free_internal (ptr);
+}
+/* Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#ifdef _LIBC
+
+#include <ansidecl.h>
+#include <gnu-stabs.h>
+
+#undef	cfree
+
+function_alias(cfree, free, void, (ptr),
+	       DEFUN(cfree, (ptr), PTR ptr))
+
+#else
+
+void
+cfree (ptr)
+     __ptr_t ptr;
+{
+  free (ptr);
+}
+
+#endif
+/* Change the size of a block allocated by `malloc'.
+   Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+		     Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#if  (defined (MEMMOVE_MISSING) || \
+      !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG))
+
+/* Snarfed directly from Emacs src/dispnew.c:
+   XXX Should use system bcopy if it handles overlap.  */
+#ifndef emacs
+
+/* Like bcopy except never gets confused by overlap.  */
+
+static void
+safe_bcopy (from, to, size)
+     char *from, *to;
+     int size;
+{
+  if (size <= 0 || from == to)
+    return;
+
+  /* If the source and destination don't overlap, then bcopy can
+     handle it.  If they do overlap, but the destination is lower in
+     memory than the source, we'll assume bcopy can handle that.  */
+  if (to < from || from + size <= to)
+    bcopy (from, to, size);
+
+  /* Otherwise, we'll copy from the end.  */
+  else
+    {
+      register char *endf = from + size;
+      register char *endt = to + size;
+
+      /* If TO - FROM is large, then we should break the copy into
+	 nonoverlapping chunks of TO - FROM bytes each.  However, if
+	 TO - FROM is small, then the bcopy function call overhead
+	 makes this not worth it.  The crossover point could be about
+	 anywhere.  Since I don't think the obvious copy loop is too
+	 bad, I'm trying to err in its favor.  */
+      if (to - from < 64)
+	{
+	  do
+	    *--endt = *--endf;
+	  while (endf != from);
+	}
+      else
+	{
+	  for (;;)
+	    {
+	      endt -= (to - from);
+	      endf -= (to - from);
+
+	      if (endt < to)
+		break;
+
+	      bcopy (endf, endt, to - from);
+	    }
+
+	  /* If SIZE wasn't a multiple of TO - FROM, there will be a
+	     little left over.  The amount left over is
+	     (endt + (to - from)) - to, which is endt - from.  */
+	  bcopy (from, to, endt - from);
+	}
+    }
+}     
+#endif	/* Not emacs.  */
+
+#define memmove(to, from, size) safe_bcopy ((from), (to), (size))
+
+#endif
+
+
+#define min(A, B) ((A) < (B) ? (A) : (B))
+
+/* Debugging hook for realloc.  */
+__ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
+
+/* Resize the given region to the new size, returning a pointer
+   to the (possibly moved) region.  This is optimized for speed;
+   some benchmarks seem to indicate that greater compactness is
+   achieved by unconditionally allocating and copying to a
+   new region.  This module has incestuous knowledge of the
+   internals of both free and malloc. */
+__ptr_t
+realloc (ptr, size)
+     __ptr_t ptr;
+     size_t size;
+{
+  __ptr_t result;
+  int type;
+  size_t block, blocks, oldlimit;
+
+  if (size == 0)
+    {
+      free (ptr);
+      return malloc (0);
+    }
+  else if (ptr == NULL)
+    return malloc (size);
+
+  if (__realloc_hook != NULL)
+    return (*__realloc_hook) (ptr, size);
+
+  block = BLOCK (ptr);
+
+  type = _heapinfo[block].busy.type;
+  switch (type)
+    {
+    case 0:
+      /* Maybe reallocate a large block to a small fragment.  */
+      if (size <= BLOCKSIZE / 2)
+	{
+	  result = malloc (size);
+	  if (result != NULL)
+	    {
+	      memcpy (result, ptr, size);
+	      _free_internal (ptr);
+	      return result;
+	    }
+	}
+
+      /* The new size is a large allocation as well;
+	 see if we can hold it in place. */
+      blocks = BLOCKIFY (size);
+      if (blocks < _heapinfo[block].busy.info.size)
+	{
+	  /* The new size is smaller; return
+	     excess memory to the free list. */
+	  _heapinfo[block + blocks].busy.type = 0;
+	  _heapinfo[block + blocks].busy.info.size
+	    = _heapinfo[block].busy.info.size - blocks;
+	  _heapinfo[block].busy.info.size = blocks;
+	  /* We have just created a new chunk by splitting a chunk in two.
+	     Now we will free this chunk; increment the statistics counter
+	     so it doesn't become wrong when _free_internal decrements it.  */
+	  ++_chunks_used;
+	  _free_internal (ADDRESS (block + blocks));
+	  result = ptr;
+	}
+      else if (blocks == _heapinfo[block].busy.info.size)
+	/* No size change necessary.  */
+	result = ptr;
+      else
+	{
+	  /* Won't fit, so allocate a new region that will.
+	     Free the old region first in case there is sufficient
+	     adjacent free space to grow without moving. */
+	  blocks = _heapinfo[block].busy.info.size;
+	  /* Prevent free from actually returning memory to the system.  */
+	  oldlimit = _heaplimit;
+	  _heaplimit = 0;
+	  _free_internal (ptr);
+	  _heaplimit = oldlimit;
+	  result = malloc (size);
+	  if (result == NULL)
+	    {
+	      /* Now we're really in trouble.  We have to unfree
+		 the thing we just freed.  Unfortunately it might
+		 have been coalesced with its neighbors.  */
+	      if (_heapindex == block)
+	        (void) malloc (blocks * BLOCKSIZE);
+	      else
+		{
+		  __ptr_t previous = malloc ((block - _heapindex) * BLOCKSIZE);
+		  (void) malloc (blocks * BLOCKSIZE);
+		  _free_internal (previous);
+		}
+	      return NULL;
+	    }
+	  if (ptr != result)
+	    memmove (result, ptr, blocks * BLOCKSIZE);
+	}
+      break;
+
+    default:
+      /* Old size is a fragment; type is logarithm
+	 to base two of the fragment size.  */
+      if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))
+	/* The new size is the same kind of fragment.  */
+	result = ptr;
+      else
+	{
+	  /* The new size is different; allocate a new space,
+	     and copy the lesser of the new size and the old. */
+	  result = malloc (size);
+	  if (result == NULL)
+	    return NULL;
+	  memcpy (result, ptr, min (size, (size_t) 1 << type));
+	  free (ptr);
+	}
+      break;
+    }
+
+  return result;
+}
+/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define	_MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* Allocate an array of NMEMB elements each SIZE bytes long.
+   The entire array is initialized to zeros.  */
+__ptr_t
+calloc (nmemb, size)
+     register size_t nmemb;
+     register size_t size;
+{
+  register __ptr_t result = malloc (nmemb * size);
+
+  if (result != NULL)
+    (void) memset (result, 0, nmemb * size);
+
+  return result;
+}
+/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library 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.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define	_MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#ifndef	__GNU_LIBRARY__
+#define	__sbrk	sbrk
+#endif
+
+#ifdef __GNU_LIBRARY__
+/* It is best not to declare this and cast its result on foreign operating
+   systems with potentially hostile include files.  */
+extern __ptr_t __sbrk __P ((int increment));
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Allocate INCREMENT more bytes of data space,
+   and return the start of data space, or NULL on errors.
+   If INCREMENT is negative, shrink data space.  */
+__ptr_t
+__default_morecore (increment)
+     ptrdiff_t increment;
+{
+  __ptr_t result = (__ptr_t) __sbrk ((int) increment);
+  if (result == (__ptr_t) -1)
+    return NULL;
+  return result;
+}
+/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+__ptr_t
+memalign (alignment, size)
+     size_t alignment;
+     size_t size;
+{
+  __ptr_t result;
+  unsigned long int adj;
+
+  size = ((size + alignment - 1) / alignment) * alignment;
+
+  result = malloc (size);
+  if (result == NULL)
+    return NULL;
+  adj = (unsigned long int) ((unsigned long int) ((char *) result -
+						  (char *) NULL)) % alignment;
+  if (adj != 0)
+    {
+      struct alignlist *l;
+      for (l = _aligned_blocks; l != NULL; l = l->next)
+	if (l->aligned == NULL)
+	  /* This slot is free.  Use it.  */
+	  break;
+      if (l == NULL)
+	{
+	  l = (struct alignlist *) malloc (sizeof (struct alignlist));
+	  if (l == NULL)
+	    {
+	      free (result);
+	      return NULL;
+	    }
+	  l->next = _aligned_blocks;
+	  _aligned_blocks = l;
+	}
+      l->exact = result;
+      result = l->aligned = (char *) result + alignment - adj;
+    }
+
+  return result;
+}
Index: /indexers/branches/3.03a/mg/lib/huffman.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/huffman.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/huffman.c	(revision 14757)
@@ -0,0 +1,406 @@
+/**************************************************************************
+ *
+ * huffman.c -- Huffman coding functions
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "huffman.h"
+#include "messages.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+/* ->data on success,  
+   NULL on error 
+ */
+huff_data *
+Generate_Huffman_Data (int num, long *freqs, huff_data * data,
+		       u_long * mem)
+{
+  int HNum, i, count;
+  unsigned long *heap;
+  huff_data *hd = data;
+  if (!hd)
+    {
+      if (!(hd = Xmalloc (sizeof (huff_data))))
+	goto error0;
+    }
+  if (!(heap = Xmalloc (num * 2 * sizeof (*heap))))
+    goto error1;
+  if (!(hd->clens = Xmalloc (num * sizeof (char))))
+      goto error2;
+  hd->num_codes = num;
+  if (mem)
+    {
+      if (hd != data)
+	*mem += sizeof (huff_data);
+      *mem += num * sizeof (char);
+    }
+  bcopy ((char *) freqs, (char *) &heap[num], num * sizeof (*heap));
+  bzero ((char *) heap, num * sizeof (*heap));
+
+  /* Initialise the pointers to the leaves */
+  for (count = i = 0; i < num; i++)
+    if (heap[num + i])
+      heap[count++] = num + i;
+
+  /* Reorganise the pointers so that it is a heap */
+  HNum = count;
+  for (i = HNum / 2; i > 0; i--)
+    {
+      register int curr, child;
+      curr = i;
+      child = curr * 2;
+      while (child <= HNum)
+	{
+	  if (child < HNum && heap[heap[child]] < heap[heap[child - 1]])
+	    child++;
+	  if (heap[heap[curr - 1]] > heap[heap[child - 1]])
+	    {
+	      register u_long temp;
+	      temp = heap[child - 1];
+	      heap[child - 1] = heap[curr - 1];
+	      heap[curr - 1] = temp;
+	      curr = child;
+	      child = 2 * curr;
+	    }
+	  else
+	    break;
+	}
+    }
+
+
+  /* Form the huffman tree */
+  while (HNum > 1)
+    {
+      int pos[2];
+
+      for (i = 0; i < 2; i++)
+	{
+	  register int curr, child;
+	  pos[i] = heap[0];
+	  heap[0] = heap[--HNum];
+	  curr = 1;
+	  child = 2;
+	  while (child <= HNum)
+	    {
+	      if (child < HNum &&
+		  heap[heap[child]] < heap[heap[child - 1]])
+		child++;
+	      if (heap[heap[curr - 1]] > heap[heap[child - 1]])
+		{
+		  register int temp;
+		  temp = heap[child - 1];
+		  heap[child - 1] = heap[curr - 1];
+		  heap[curr - 1] = temp;
+		  curr = child;
+		  child = 2 * curr;
+		}
+	      else
+		break;
+	    }
+	}
+
+      heap[HNum + 1] = heap[pos[0]] + heap[pos[1]];
+      heap[pos[0]] = heap[pos[1]] = HNum + 1;
+
+      heap[HNum] = HNum + 1;
+
+      {
+	register int parent, curr;
+	HNum++;
+	curr = HNum;
+	parent = curr >> 1;
+	while (parent && heap[heap[parent - 1]] > heap[heap[curr - 1]])
+	  {
+	    register int temp;
+	    temp = heap[parent - 1];
+	    heap[parent - 1] = heap[curr - 1];
+	    heap[curr - 1] = temp;
+	    curr = parent;
+	    parent = curr >> 1;
+	  }
+      }
+    }
+
+
+  /* Calculate the code lens */
+  heap[0] = -1UL;
+  heap[1] = 0;
+  for (i = 2; i < num * 2; i++)
+    heap[i] = heap[heap[i]] + 1;
+
+  /* zero the lencount's array */
+  bzero ((char *) hd->lencount, sizeof (hd->lencount));
+  hd->maxcodelen = 0;
+  hd->mincodelen = 100;
+
+  /* Set the code length of each leaf in the huffman tree */
+  for (i = 0; i < num; i++)
+    {
+      register u_long codelen = heap[i + num];
+      hd->clens[i] = (char) codelen;
+      if (!codelen)
+	continue;
+      if (codelen > hd->maxcodelen)
+	hd->maxcodelen = codelen;
+      if (codelen < hd->mincodelen)
+	hd->mincodelen = codelen;
+      hd->lencount[codelen]++;
+    }
+
+
+  if (hd->maxcodelen == 0 && hd->mincodelen == 100)
+    {
+      hd->num_codes = 0;
+    }
+  else
+    {
+      /* Calculate the current codes for each different code length */
+      hd->min_code[hd->maxcodelen] = 0;
+      for (i = hd->maxcodelen - 1; i>=0; i--)
+	hd->min_code[i] = (hd->min_code[i + 1] + hd->lencount[i + 1]) >> 1;
+    }
+  free (heap);
+  return (hd);
+
+error2:
+  free (heap);
+error1:
+  if (!data)
+    free (hd);
+error0:
+  return (NULL);
+
+}
+
+unsigned long *
+Generate_Huffman_Codes (huff_data * data, u_long * mem)
+{
+  int i;
+  unsigned long *codes;
+  unsigned long mc[MAX_HUFFCODE_LEN + 1];
+
+  if (!data)
+    return (NULL);
+  if (!(codes = Xmalloc (data->num_codes * sizeof (*codes))))
+    return (NULL);
+  if (mem)
+    *mem += data->num_codes * sizeof (*codes);
+  bcopy ((char *) data->min_code, (char *) mc, sizeof (mc));
+  for (i = 0; i < data->num_codes; i++)
+    if (data->clens[i])
+      codes[i] = mc[(int) (data->clens[i])]++;
+
+  return (codes);
+}
+
+
+unsigned long **
+Generate_Huffman_Vals (huff_data * data, u_long * mem)
+{
+  int i;
+  unsigned long *fcode[MAX_HUFFCODE_LEN + 1];
+  unsigned long **values;
+  unsigned long *vals;
+
+  if (!data)
+    return (NULL);
+  if (!(vals = Xmalloc (data->num_codes * sizeof (*vals))))
+    return (NULL);
+  if (!(values = Xmalloc ((MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *))))
+    {
+      free (vals);
+      return (NULL);
+    }
+
+  bzero ((char *) values, (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *));
+
+  if (mem)
+    *mem += data->num_codes * sizeof (*vals) +
+      (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *);
+
+  fcode[0] = values[0] = &vals[0];
+  for (i = 1; i <= data->maxcodelen; i++)
+    fcode[i] = values[i] = &vals[(values[i - 1] - vals) + data->lencount[i - 1]];
+
+  for (i = 0; i < data->num_codes; i++)
+    if (data->clens[i])
+      *fcode[(int) (data->clens[i])]++ = i;
+  return (values);
+}
+
+
+
+double 
+Calculate_Huffman_Size (int num, long *freqs, long *counts)
+{
+  double size = 0;
+  huff_data hd;
+  int i;
+  if (!Generate_Huffman_Data (num, freqs, &hd, NULL))
+    return -1;
+  for (i = 0; i < num; i++)
+    size += counts[i] * hd.clens[i];
+  Xfree (hd.clens);
+  return size;
+}
+
+
+
+int 
+Write_Huffman_Data (FILE * f, huff_data * hd)
+{
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONSI(hd->num_codes);
+  HTONSI(hd->mincodelen);
+  HTONSI(hd->maxcodelen);
+
+  if (fwrite (&hd->num_codes, sizeof (hd->num_codes), 1, f) != 1)
+    return -1;
+
+  if (fwrite (&hd->mincodelen, sizeof (hd->mincodelen), 1, f) != 1)
+    return -1;
+
+  if (fwrite (&hd->maxcodelen, sizeof (hd->maxcodelen), 1, f) != 1)
+    return -1;
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHSI(hd->num_codes);
+  NTOHSI(hd->mincodelen);
+  NTOHSI(hd->maxcodelen);
+
+  if (hd->num_codes)
+    {
+      /* [RPAP - Jan 97: Endian Ordering] */
+      int i;
+      for (i = hd->mincodelen; i < hd->maxcodelen + 1; i++)
+	HTONSI(hd->lencount[i]);
+      for (i = 0; i < hd->maxcodelen + 1; i++)
+	HTONUL(hd->min_code[i]);
+
+      if (fwrite (hd->lencount + hd->mincodelen, sizeof (*hd->lencount),
+		  hd->maxcodelen - hd->mincodelen + 1, f) !=
+	  hd->maxcodelen - hd->mincodelen + 1)
+	return -1;
+
+      if (fwrite (hd->min_code, sizeof (*hd->min_code), hd->maxcodelen + 1, f) !=
+	  hd->maxcodelen + 1)
+	return -1;
+
+      if (fwrite (hd->clens, sizeof (*hd->clens), hd->num_codes, f) != hd->num_codes)
+	return -1;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (i = hd->mincodelen; i < hd->maxcodelen + 1; i++)
+	NTOHSI(hd->lencount[i]);
+      for (i = 0; i < hd->maxcodelen + 1; i++)
+	NTOHUL(hd->min_code[i]);
+    }
+  return 0;
+}
+
+
+
+
+static int 
+General_Read_Huffman_Data (size_t (*rd) (), void *f,
+			   huff_data * hd, u_long * mem, u_long * disk)
+{
+  if (rd (&hd->num_codes, sizeof (hd->num_codes), 1, f) != 1)
+    return -1;
+
+  if (rd (&hd->mincodelen, sizeof (hd->mincodelen), 1, f) != 1)
+    return -1;
+
+  if (rd (&hd->maxcodelen, sizeof (hd->maxcodelen), 1, f) != 1)
+    return -1;
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHSI(hd->num_codes);
+  NTOHSI(hd->mincodelen);
+  NTOHSI(hd->maxcodelen);
+
+  if (disk)
+    (*disk) += sizeof (hd->num_codes) + sizeof (hd->mincodelen) +
+      sizeof (hd->maxcodelen);
+
+  hd->clens = NULL;
+
+  if (hd->num_codes)
+    {
+      int i;  /* [RPAP - Jan 97: Endian Ordering] */
+
+      bzero ((char *) (hd->lencount), sizeof (hd->lencount));
+      if (rd (hd->lencount + hd->mincodelen, sizeof (*hd->lencount),
+	      hd->maxcodelen - hd->mincodelen + 1, f) !=
+	  hd->maxcodelen - hd->mincodelen + 1)
+	return -1;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (i = hd->mincodelen; i < hd->maxcodelen + 1; i++)
+	NTOHSI(hd->lencount[i]);
+
+      if (disk)
+	(*disk) += sizeof (*hd->lencount) * (hd->maxcodelen - hd->mincodelen + 1);
+
+      bzero ((char *) (hd->min_code), sizeof (hd->min_code));
+
+      if (rd (hd->min_code, sizeof (*hd->min_code), hd->maxcodelen + 1, f) !=
+	  hd->maxcodelen + 1)
+	return -1;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (i = 0; i < hd->maxcodelen + 1; i++)
+	NTOHUL(hd->min_code[i]);
+
+      if (disk)
+	(*disk) += sizeof (*hd->min_code) * (hd->maxcodelen + 1);
+
+      if (!(hd->clens = Xmalloc (sizeof (*hd->clens) * hd->num_codes)))
+	return -1;
+
+
+      if (rd (hd->clens, sizeof (*hd->clens), hd->num_codes, f) != hd->num_codes)
+	return -1;
+
+      if (disk)
+	(*disk) += sizeof (*hd->clens) * hd->num_codes;
+    }
+
+  if (mem)
+    *mem += sizeof (*hd->clens) * hd->num_codes;
+  return 0;
+}
+
+
+
+int 
+Read_Huffman_Data (FILE * f, huff_data * hd, u_long * mem, u_long * disk)
+{
+  return General_Read_Huffman_Data (fread, f, hd, mem, disk);
+}
+
+
+
+
+int 
+F_Read_Huffman_Data (File * f, huff_data * hd, u_long * mem, u_long * disk)
+{
+  return General_Read_Huffman_Data (Fread, f, hd, mem, disk);
+}
Index: /indexers/branches/3.03a/mg/lib/huffman.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/huffman.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/huffman.h	(revision 14757)
@@ -0,0 +1,112 @@
+/**************************************************************************
+ *
+ * huffman.h -- Huffman coding functions
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_HUFFMAN
+#define H_HUFFMAN
+
+#include "sysfuncs.h"
+
+#include "filestats.h"
+
+
+#define MAX_HUFFCODE_LEN 31
+
+typedef struct huff_data
+  {
+    int num_codes;
+    int mincodelen;
+    int maxcodelen;
+    int lencount[MAX_HUFFCODE_LEN + 1];
+    unsigned long min_code[MAX_HUFFCODE_LEN + 1];
+    char *clens;
+  }
+huff_data;
+
+
+huff_data *Generate_Huffman_Data (int num, long *freqs, huff_data * data,
+				  u_long * mem);
+
+unsigned long *Generate_Huffman_Codes (huff_data * data, u_long * mem);
+
+unsigned long **Generate_Huffman_Vals (huff_data * data, u_long * mem);
+
+int Write_Huffman_Data (FILE * f, huff_data * hd);
+
+int Read_Huffman_Data (FILE * f, huff_data * hd, u_long * mem, u_long * disk);
+
+int F_Read_Huffman_Data (File * f, huff_data * hd, u_long * mem, u_long * disk);
+
+/* Calculate the number of bits required to code the data with the
+   specified frequencies. Normally freqs and counts should point to
+   the same array. */
+double Calculate_Huffman_Size (int num, long *freqs, long *counts);
+
+
+
+#define HUFF_ENCODE(x, codes, lens)					\
+  do {									\
+    register int __i;							\
+    register int __clen = (lens)[x];					\
+    register unsigned long __code = (codes)[x];				\
+    for (__i=__clen-1; __i>=0; --__i)					\
+      ENCODE_BIT((__code >> __i) & 1);					\
+  } while(0)
+
+#define HUFF_ENCODE_L(x, codes, lens, count)				\
+  do {									\
+    HUFF_ENCODE(x, codes, lens);		   			\
+    (count) += (lens)[x];						\
+  } while(0)
+
+
+#define HUFF_DECODE(x, mcodes, values)					\
+  do {									\
+    register unsigned long *__min_code = (mcodes);			\
+    register unsigned long *__mclen = __min_code;			\
+    register unsigned long **__values = (values);			\
+    register unsigned long __code = 0;					\
+    do									\
+      {									\
+        DECODE_ADD(__code);						\
+      }									\
+    while (__code < *++__mclen);					\
+    (x) = __values[__mclen - __min_code][__code - *__mclen];		\
+  } while(0);
+
+
+#define HUFF_DECODE_L(x, mcodes, values, count)				\
+  do {									\
+    register unsigned long *__min_code = (mcodes);			\
+    register unsigned long *__mclen = __min_code;			\
+    register unsigned long **__values = (values);			\
+    register unsigned long __code = 0;					\
+    do									\
+      {									\
+        DECODE_ADD(__code);						\
+	(count)++;							\
+      }									\
+    while (__code < *++__mclen);					\
+    (x) = __values[__mclen - __min_code][__code - *__mclen];		\
+  } while(0);
+
+
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/huffman_mem.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/huffman_mem.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/huffman_mem.c	(revision 14757)
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * huffman_mem.c -- Huffman coding functions to memory
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "bitio_m.h"
+#include "bitio_m_mem.h"
+#include "huffman.h"
+
+#if 0
+int fprintf (FILE *, const char *,...);
+#endif
+
+void 
+BIO_Mem_Huff_Encode (unsigned long val, unsigned long *codes,
+		     char *clens, mem_bitio_state * bs)
+{
+  ENCODE_CONTINUE (*bs)
+    HUFF_ENCODE (val, codes, clens);
+  ENCODE_PAUSE (*bs)
+}
+
+unsigned long 
+BIO_Mem_Huff_Decode (unsigned long *mincodes,
+		     unsigned long **values, mem_bitio_state * bs)
+{
+  unsigned long val;
+  DECODE_CONTINUE (*bs)
+    HUFF_DECODE (val, mincodes, values);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
Index: /indexers/branches/3.03a/mg/lib/huffman_mem.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/huffman_mem.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/huffman_mem.h	(revision 14757)
@@ -0,0 +1,34 @@
+/**************************************************************************
+ *
+ * huffman_mem.h -- Huffman coding functions to memory
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_HUFFMAN_MEM
+#define H_HUFFMAN_MEM
+
+
+
+void BIO_Mem_Huff_Encode (unsigned long val, unsigned long *codes,
+			  char *clens, mem_bitio_state * bs);
+
+unsigned long BIO_Mem_Huff_Decode (unsigned long *mincodes,
+			      unsigned long **values, mem_bitio_state * bs);
+
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/huffman_stdio.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/huffman_stdio.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/huffman_stdio.c	(revision 14757)
@@ -0,0 +1,53 @@
+/**************************************************************************
+ *
+ * huffman_stdio.c -- Huffman coding function to a file
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "bitio_m.h"
+#include "bitio_m_stdio.h"
+#include "huffman.h"
+
+#if 0
+int fprintf (FILE *, const char *,...);
+int _filbuf (FILE *);
+int _flsbuf (unsigned, FILE *);
+#endif
+
+void 
+BIO_Stdio_Huff_Encode (unsigned long val, unsigned long *codes,
+		       char *clens, stdio_bitio_state * bs)
+{
+  ENCODE_CONTINUE (*bs)
+    HUFF_ENCODE (val, codes, clens);
+  ENCODE_PAUSE (*bs)
+}
+
+unsigned long 
+BIO_Stdio_Huff_Decode (unsigned long *mincodes,
+		       unsigned long **values,
+		       stdio_bitio_state * bs)
+{
+  unsigned long val;
+  DECODE_CONTINUE (*bs)
+    HUFF_DECODE (val, mincodes, values);
+  DECODE_PAUSE (*bs)
+    return (val);
+}
Index: /indexers/branches/3.03a/mg/lib/huffman_stdio.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/huffman_stdio.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/huffman_stdio.h	(revision 14757)
@@ -0,0 +1,36 @@
+/**************************************************************************
+ *
+ * huffman_stdio.h -- Huffman coding function to a file
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_HUFFMAN_STDIO
+#define H_HUFFMAN_STDIO
+
+
+
+void BIO_Stdio_Huff_Encode (unsigned long val, unsigned long *codes,
+			    char *clens, stdio_bitio_state * bs);
+
+
+unsigned long BIO_Stdio_Huff_Decode (unsigned long *mincodes,
+				     unsigned long **values,
+				     stdio_bitio_state * bs);
+
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/local_strings.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/local_strings.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/local_strings.c	(revision 14757)
@@ -0,0 +1,411 @@
+/**************************************************************************
+ *
+ * local_strings -- provides some extra string routines
+ * Copyright (C) 1994  Authors
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "local_strings.h"
+#include "memlib.h"
+
+/* =========================================================================
+ * Function: arg_atoi
+ * Description: 
+ *      Converts an ascii string to an integer
+ *      but allows a scale string immediately following.
+ *      i.e. "10Mb" or "20Kb" or "40Megabytes"
+ *      There must be no gap between the last digit and the scale.
+ *      Only the fist letter is significant.
+ *      K = Kilo
+ *      M = Mega
+ *      G = Giga
+ * Input: 
+ *      string of form: xxxxxxK or xxxxxxxM or xxxxxxxG
+ *      where x is a digit
+ * Output: 
+ *      a scaled integer
+ * ========================================================================= */
+
+#define KILO 	1024
+#define MEGA	1024*1024
+#define GIGA	1024*1024*1024
+
+int 
+arg_atoi (char *str)
+{
+  char *str_ptr = str;
+  char ch = '\0';
+  long scale = 1;
+
+  /* find any scale letter immediately after digits */
+  ch = *str_ptr;
+  while (!isalpha (ch) && (ch != '\0'))
+    ch = *str_ptr++;
+
+  /* replace scale letter by end-of-string character */
+  *str_ptr = '\0';
+
+  /* set scale appropriately */
+  switch (ch)
+    {
+    case 'K':
+      scale = KILO;
+      break;
+    case 'M':
+      scale = MEGA;
+      break;
+    case 'G':
+      scale = GIGA;
+      break;
+    default:
+      scale = 1;
+      break;
+    }
+
+  return (atoi (str) * scale);
+
+}
+
+/* ===============================================================================
+ * Function: compare
+ * Description: Compare two strings. 
+ * Input: Two binary strings, first byte of string indicates length. 
+ * Output: Like standard strcmp.
+ *      = 0 if s1 = s2
+ *      < 0 if s1 < s2
+ *      > 0 if s1 > s2
+ * =============================================================================== */
+int 
+compare (u_char * s1, u_char * s2)
+{
+  int l1 = *s1, l2 = *s2;
+  int l = (l1 < l2) ? l1 : l2;
+
+  while (l--)
+    if (*++s1 != *++s2)
+      return (*s1 - *s2);
+  return (l1 - l2);
+
+}
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static unsigned char casecharmap[] = {
+	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+	'\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
+	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+/* ===============================================================================
+ * Function: casecompare   [RPAP - Jan 97: Stem Index Change]
+ * Description: Compare two strings in dictionary order
+ * Input: Two binary strings, first byte of string indicates length. 
+ * Output:
+ *      = 0 if s1 = s2
+ *      < 0 if s1 < s2
+ *      > 0 if s1 > s2
+ * =============================================================================== */
+int 
+casecompare (u_char * s1, u_char * s2)
+{
+  int l1 = *s1, l2 = *s2;
+  int l = (l1 < l2) ? l1 : l2;
+  int pos = 0;
+  register int diff = 0;
+
+  while (l--)
+    if ((diff = casecharmap[*++s1] - casecharmap[*++s2]) != 0)
+      return (diff);
+    else if ((diff = *s1 - *s2) != 0)
+      if (!pos)
+	pos = diff;
+
+  return ((l1 - l2) ? (l1 - l2) : (pos));
+
+}
+
+/* =========================================================================
+ * Function: copy_string
+ * Description: 
+ *      Copies a string with the len in 1st byte
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+u_char *
+copy_string (u_char * src_str)
+{
+  u_char *copy = Xmalloc (src_str[0] + 1);
+
+  if (!copy)
+    return NULL;
+
+  bcopy ((char *) src_str, (char *) (copy), src_str[0] + 1);
+  return copy;
+
+}
+
+
+/* ===============================================================================
+ * Function: prefixlen
+ * Description: Returns length of common prefix string between s1 and s2.
+ * Input: two binary strings
+ * Output: prefix length
+ * =============================================================================== */
+int 
+prefixlen (u_char * s1, u_char * s2)
+{
+  int l = (*s1 < *s2) ? *s1 : *s2;
+  int i = 0;
+
+  while (i < l && *++s1 == *++s2)
+    i++;
+  return (i);
+}
+
+
+/* ===============================================================================
+ * Function: char2str
+ * Description: 
+ *      Ensures that non-printable characters are converted to a string
+ *      which is printable i.e. it indentifies the character.
+ *      e.g. carriage-return = "\n".
+ * Input: character (may be non-printable)
+ * Output: pointer to static string
+ * =============================================================================== */
+
+char *
+char2str (u_char c)
+{
+  static char buf[10];
+  switch (c)
+    {
+    case '\n':
+      sprintf (buf, "\\n");
+      break;
+    case '\b':
+      sprintf (buf, "\\b");
+      break;
+    case '\f':
+      sprintf (buf, "\\f");
+      break;
+    case '\t':
+      sprintf (buf, "\\t");
+      break;
+    default:
+	if (c >= ' ' && c <= 126)
+	switch (c)
+	  {
+	  case '\\':
+	    sprintf (buf, "\\\\");
+	    break;
+	  case '\"':
+	    sprintf (buf, "\\\"");
+	    break;
+	  case '\'':
+	    sprintf (buf, "\\\'");
+	    break;
+	  default:
+	    buf[0] = c;
+	    buf[1] = '\0';
+	    break;
+	  }
+      else
+	sprintf (buf, "\\x%02x", c);
+      break;
+    }
+  return buf;
+}
+
+/* ===============================================================================
+ * Function: word2str
+ * Description: 
+ *      Converts a string with possible non-printable characters into a string
+ *      consisting entirely of printable characters.
+ * Input: string, length stored in first byte
+ * Output: pointer to static string
+ * =============================================================================== */
+
+char *
+word2str (u_char * s)
+{
+  static char buf[1024];
+  char *p = buf;
+  int i, len = (int) *s++;
+
+  bzero (buf, sizeof (buf));
+  for (i = 0; i < len; i++)
+    {
+      strcpy (p, char2str (s[i]));
+      p = strchr (p, '\0');
+    }
+  return buf;
+}
+
+
+/* =========================================================================
+ * Function: de_escape_string
+ * Description: 
+ *      Turn a string containing \ escapes into real characters
+ *      Note this destroys the string s in the process
+ * Input: string to de-escape 
+ * Output: the de-escaped string
+ * ========================================================================= */
+char *
+de_escape_string (char *s)
+{
+  char *org = s;
+  char *d = s;
+  while (*s)
+    {
+      if (*s == '\\')
+	{
+	  s++;
+	  switch (*s++)
+	    {
+	    case '\0':
+	      *d++ = '\\';
+	      s--;
+	      break;
+	    case '\\':
+	      *d++ = '\\';
+	      break;
+	    case 'b':
+	      *d++ = '\b';
+	      break;
+	    case 'f':
+	      *d++ = '\f';
+	      break;
+	    case 'n':
+	      *d++ = '\n';
+	      break;
+	    case 'r':
+	      *d++ = '\r';
+	      break;
+	    case 't':
+	      *d++ = '\r';
+	      break;
+	    case '\"':
+	      *d++ = '\"';
+	      break;
+	    case '\'':
+	      *d++ = '\'';
+	      break;
+	    case 'x':
+	      {
+		int num = 0;
+		if (isxdigit (*s))
+		  {
+		    char ch = toupper (*s++);
+		    num = ch <= '9' ? ch - '0' : ch - 'A' + 10;
+		  }
+		if (isxdigit (*s))
+		  {
+		    char ch = toupper (*s++);
+		    num = (num << 4) + (ch <= '9' ? ch - '0' : ch - 'A' + 10);
+		  }
+		*d++ = num;
+		break;
+	      }
+	    case '0':
+	    case '1':
+	    case '2':
+	    case '3':
+	    case '4':
+	    case '5':
+	    case '6':
+	    case '7':
+	      {
+		int num = *(s - 1) - '0';
+		if (*s >= '0' && *s <= '7')
+		  num = (num << 3) + *s++ - '0';
+		if (*s >= '0' && *s <= '7')
+		  num = (num << 3) + *s++ - '0';
+		*d++ = num;
+		break;
+	      }
+	    }
+	}
+      else
+	*d++ = *s++;
+    }
+  *d = '\0';
+  return (org);
+}
+
+/* =========================================================================
+ * Function: str255_to_string 
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+char *
+str255_to_string (u_char * str255, char *str)
+{
+  static char buf[256];
+  char *str_base = NULL;
+  int len = *str255++;
+  int i = 0;
+
+  /* if haven't been given a str to write to then use local buffer */
+  if (!str)
+    str = &(buf[0]);
+
+  str_base = str;
+  for (i = 0; i < len; i++)
+    {
+      *str++ = *str255++;
+    }
+  *str = '\0';
+
+  return str_base;
+}
Index: /indexers/branches/3.03a/mg/lib/local_strings.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/local_strings.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/local_strings.h	(revision 14757)
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * local_strings.h -- string routines
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef LOCAL_STRINGS_H
+#define LOCAL_STRINGS_H
+
+#include "sysfuncs.h"
+
+int arg_atoi (char *str);
+int compare (u_char * s1, u_char * s2);
+int casecompare (u_char * s1, u_char * s2);   /* [RPAP - Jan 97: Stem Index Change] */
+u_char *copy_string (u_char * src_str);
+char *str255_to_string (u_char * str255, char *str);
+int prefixlen (u_char * s1, u_char * s2);
+char *char2str (u_char c);
+char *word2str (u_char * s);
+char *de_escape_string (char *s);
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/longlong.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/longlong.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/longlong.h	(revision 14757)
@@ -0,0 +1,81 @@
+/**************************************************************************
+ *
+ * longlong.h -- Use of GCC's long long integer types
+ * Copyright (C) 1999 Tim A.H. Bell
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_LONGLONG
+#define H_LONGLONG
+
+#ifndef __WIN32__
+#include "config.h"
+#endif
+
+/*
+  Use GCC's "long long" integer types for certain variables, to avoid
+  overflowing 32 bit integers.
+
+  Other files affected:
+  
+    lib:
+        bitio_random.c
+        bitio_random.h
+	
+    src/text:
+        ivf.pass1.c
+        ivf.pass2.c
+        build.h
+        mg_passes.c
+        text.h
+	mgstat.c
+*/
+
+/*#define TESTING_OVERFLOW*/
+
+#ifdef TESTING_OVERFLOW
+
+/* Test the overflow detection by using tiny (16-bit) types */
+typedef unsigned short int mg_ullong;
+typedef short int mg_llong;
+
+#define ULL_FS "u"
+#define LL_FS "d"
+
+#elif defined __GNUC__ && ! defined DISABLE_LONG_LONG
+
+/* We're using GCC, so it's okay to use "long long" (64-bit) types */
+#define USE_LONG_LONG
+
+typedef unsigned long long int mg_ullong;
+typedef long long int mg_llong;
+
+#define ULL_FS "llu"
+#define LL_FS "lld"
+
+#else
+
+/* Not using GCC, so fall back on plain "long" (32-bit) types */
+typedef unsigned long int mg_ullong;
+typedef long int mg_llong;
+
+#define ULL_FS "lu"
+#define LL_FS "ld"
+
+#endif /* __GNUC__ */
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/lovinstem.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/lovinstem.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/lovinstem.c	(revision 14757)
@@ -0,0 +1,1183 @@
+/**************************************************************************
+ *
+ * lovinstem.c -- Stemming code
+ * Copyright (C) 1994  Linh Huynh (linh@kbs.citri.edu.au)
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+
+/*****************************************************************************
+ *
+ *   Transformational Rules used in Recoding Stem Terminations
+ *
+ *   Parameter in functions:
+ *       ch : the second last character of the old ending
+ *            (after removing one of double consonants) 
+ *
+ ****************************************************************************/
+
+
+/************ Conditional rules associated with transformations **************/
+
+static int aio ();
+static int s ();
+static int pt ();
+static int m ();
+static int n ();
+
+static int 
+aio (ch)			/* Rule number 9     */
+     char ch;
+{
+  return ((ch != 'a') && (ch != 'i') && (ch != 'o'));
+}
+
+static int 
+s (ch)				/* Rule Number 24    */
+     char ch;
+{
+  return (ch != 's');
+}
+
+static int 
+pt (ch)				/* Rule number 28    */
+     char ch;
+{
+  return ((ch != 'p') && (ch != 't'));
+}
+
+static int 
+m (ch)				/* Rule number 30    */
+     char ch;
+{
+  return (ch != 'm');
+}
+
+static int 
+n (ch)				/* Rule number 32    */
+     char ch;
+{
+  return (ch != 'n');
+}
+
+
+/**************************************************************************
+ *
+ *  Context-sensitive rules associated with certain endings.
+ *
+ *  The notations of the rules are the same as in Lovins' paper
+ *  except that rule A is replaced by a NULL in the data structure.
+ *
+ *  Function parameters:
+ *      - stem_length: possible stem length
+ *      - end        : pointer points to the end of the possible stem.
+ *
+ *************************************************************************/
+
+
+/********* Context-sensitive rule function declarations ******************/
+
+static int B ();
+static int C ();
+static int D ();
+static int E ();
+static int F ();
+static int G ();
+static int H ();
+static int I ();
+static int J ();
+static int K ();
+static int L ();
+static int M ();
+static int N ();
+static int O ();
+static int P ();
+static int Q ();
+static int R ();
+static int S ();
+static int T ();
+static int U ();
+static int V ();
+static int W ();
+static int X ();
+static int Y ();
+static int Z ();
+static int AA ();
+static int BB ();
+static int CC ();
+
+static int 
+B (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  return (stem_length >= 3);
+}
+
+static int 
+C (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  return (stem_length >= 4);
+}
+
+static int 
+D (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  return (stem_length >= 5);
+}
+
+static int 
+E (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  return (*end != 'e');
+}
+
+static int 
+F (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  return ((stem_length >= 3) && (*end != 'e'));
+}
+
+static int 
+G (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  return ((stem_length >= 3) && (*end == 'f'));
+}
+
+static int 
+H (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1, p2;
+  p1 = *end;
+  p2 = *(end - 1);
+  return ((p1 == 't') || ((p1 == 'l') && (p2 == 'l')));
+}
+
+static int 
+I (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1;
+  p1 = *end;
+  return ((p1 != 'o') && (p1 != 'e'));
+}
+
+static int 
+J (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1;
+  p1 = *end;
+  return ((p1 != 'a') && (p1 != 'e'));
+}
+
+static int 
+K (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1;
+  p1 = *end;
+  return ((stem_length >= 3) &&
+	  ((p1 == 'l') || (p1 == 'i') ||
+	   ((p1 == 'e') && (*(end - 2) == 'u'))));
+}
+
+static int 
+L (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1, p2;
+  p1 = *end;
+  p2 = *(end - 1);
+  if (p1 == 's')
+    return (p2 == 'o');
+  else
+    return ((p1 != 'u') && (p1 != 'x'));
+}
+
+static int 
+M (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1;
+  p1 = *end;
+  return ((p1 != 'a') && (p1 != 'c') &&
+	  (p1 != 'e') && (p1 != 'm'));
+}
+
+static int 
+N (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  if (stem_length >= 3)
+    {
+      if (*(end - 2) == 's')
+	return (stem_length >= 4);
+      else
+	return 1;
+    }
+  else
+    return 0;
+}
+
+static int 
+O (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1;
+  p1 = *end;
+  return ((p1 == 'l') || (p1 == 'i'));
+}
+
+static int 
+P (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  return (*end != 'c');
+}
+
+static int 
+Q (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1;
+  p1 = *end;
+
+  return ((stem_length >= 3) && (p1 != 'l') && (p1 != 'n'));
+}
+
+static int 
+R (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1;
+  p1 = *end;
+  return ((p1 == 'n') || (p1 == 'r'));
+}
+
+static int 
+S (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1, p2;
+  p1 = *end;
+  p2 = *(end - 1);
+
+  if (p1 == 't')
+    return (p2 != 't');
+  else
+    return ((p1 == 'r') && (p2 == 'd'));
+}
+
+static int 
+T (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1, p2;
+  p1 = *end;
+  p2 = *(end - 1);
+
+  if (p1 == 't')
+    return (p2 != 'o');
+  else
+    return (p1 == 's');
+}
+
+static int 
+U (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1;
+  p1 = *end;
+
+  return ((p1 == 'l') || (p1 == 'm') ||
+	  (p1 == 'n') || (p1 == 'r'));
+}
+
+static int 
+V (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  return (*end == 'c');
+}
+
+static int 
+W (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1;
+  p1 = *end;
+
+  return ((p1 != 's') && (p1 != 'u'));
+}
+
+static int 
+X (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1;
+  p1 = *end;
+
+  if (p1 == 'e')
+    return ((stem_length >= 3) && (*(end - 2) == 'u'));
+  else
+    return ((p1 == 'l') || (p1 == 'i'));
+}
+
+static int 
+Y (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  return ((*end == 'n') && (*(end - 1) == 'i'));
+}
+
+static int 
+Z (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  return (*end != 'f');
+}
+
+static int 
+AA (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  char p1, p2;
+  p1 = *end;
+  p2 = *(end - 1);
+
+  if (p1 == 'h')
+    return ((p2 == 'p') || (p2 == 't'));
+  else if (p1 == 'r')
+    return ((p2 == 'e') || (p2 == 'o'));
+  else if (p1 == 's')
+    return (p2 == 'e');
+  else
+    return ((p1 == 'd') || (p1 == 'f') ||
+	    (p1 == 'l') || (p1 == 't'));
+}
+
+static int 
+BB (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  if (stem_length >= 3)
+    {
+      if (stem_length >= 4)
+	return (strncmp (end - 3, "ryst", 4) != 0);
+      else
+	return (strncmp (end - 2, "met", 3) != 0);
+    }
+  else
+    return 0;
+}
+
+static int 
+CC (stem_length, end)
+     int stem_length;
+     char *end;
+{
+  return (*end == 'l');
+}
+
+/**************************************************************************/
+
+#define MIN_STEM_LENGTH 2
+#define MAX_ENDING_SIZE 11
+#define PREDEFINED_SIZE (MAX_ENDING_SIZE + MIN_STEM_LENGTH)
+#define EOS     '\0'
+/* [RPAP - Jan 97: Stem Index Change] */
+#define MAX_STEM_LENGTH 255
+
+static char *remove_ending (char *word, int w_len);
+static void recode_stem (char *stem_end);
+
+/* =========================================================================
+ * Function: stem
+ * Description: 
+ *      Implemetation of the Lovins' stemming algorithm described in
+ *      J.B. Lovins, "Development of a Stemming Algorithm",
+ *      Mechanical Translation and Computational Linguistics, Vol 11,1968.
+ * Input: a word string with the length in the first byte
+ * Output: the stemmed word
+ * ========================================================================= */
+
+void
+lovinstem (u_char * word)
+{
+  char *word_start;		/* points to first letter of word */
+  char *stem_end;		/* points to last character of stem portion */
+  int old_length;		/* length of word */
+  int new_length;		/* length after stemming */
+
+  /* [RPAP - Jan 97: Stem Index Change] */
+  u_char copy[MAX_STEM_LENGTH + 2];
+  bcopy ((char *) word, (char *) copy, *word + 1);
+
+  old_length = *copy; /* [RPAP - Jan 97: Stem Index Change] */
+
+  /* The word must be at least MIN_STEM_LENGTH characters long. */
+  if (old_length <= MIN_STEM_LENGTH)
+    return;
+
+  word_start = (char *) copy + 1;	/* jump over length byte */ /* [RPAP - Jan 97: Stem Index Change] */
+  copy[old_length + 1] = '\0';	/* null terminate string */ /* [RPAP - Jan 97: Stem Index Change] */
+
+  stem_end = remove_ending (word_start, old_length);
+  recode_stem (stem_end);
+
+  /* fix up new length */
+  /* have to use strlen because have no other way of telling length */
+  new_length = strlen (word_start);
+  *copy = new_length;  /* [RPAP - Jan 97: Stem Index Change] */
+
+  /* [RPAP - Jan 97: Stem Index Change] */
+  bcopy ((char *) copy, (char *) word, *copy + 1);
+
+}				/*stem_complex */
+
+/* =========================================================================
+
+ *   Data structure for recoding and the method for recoding the stem. 
+ *
+ * ========================================================================= */
+
+typedef struct
+{
+  char *old_end;		/* old ending */
+  char *new_end;		/* new ending */
+  char old_offset;		/* length of the old ending - 1 */
+  int (*cond) ();		/* condition rule */
+  char end_group;		/* signal the end of the group */
+}
+Recode_Rules;
+
+/*  
+   Stem terminations are divided into groups having the same last
+   character
+ */
+
+static Recode_Rules Rules[] =
+{
+  "uad", "uas", 2, NULL, 0,
+  "vad", "vas", 2, NULL, 0,
+  "cid", "cis", 2, NULL, 0,
+  "lid", "lis", 2, NULL, 0,
+  "erid", "eris", 3, NULL, 0,
+  "pand", "pans", 3, NULL, 0,
+  "end", "ens", 2, s, 0,
+  "end", "ens", 2, m, 0,
+  "ond", "ons", 2, NULL, 0,
+  "lud", "lus", 2, NULL, 0,
+  "rud", "rus", 2, NULL, 1,
+
+  "ul", "l", 1, aio, 1,
+
+  "istr", "ister", 3, NULL, 0,
+  "metr", "meter", 3, NULL, 0,
+  "her", "hes", 2, pt, 1,
+
+  "urs", "ur", 2, NULL, 1,
+
+  "uct", "uc", 2, NULL, 0,
+  "umpt", "um", 3, NULL, 0,
+  "rpt", "rb", 2, NULL, 0,
+  "mit", "mis", 2, NULL, 0,
+  "ert", "ers", 2, NULL, 0,
+  "et", "es", 1, n, 0,
+  "yt", "ys", 1, NULL, 1,
+
+  "iev", "ief", 2, NULL, 0,
+  "olv", "olut", 2, NULL, 1,
+
+  "bex", "bic", 2, NULL, 0,
+  "dex", "dic", 2, NULL, 0,
+  "pex", "pic", 2, NULL, 0,
+  "tex", "tic", 2, NULL, 0,
+  "ax", "ac", 1, NULL, 0,
+  "ex", "ec", 1, NULL, 0,
+  "ix", "ic", 1, NULL, 0,
+  "lux", "luc", 2, NULL, 1,
+
+  "yz", "ys", 1, NULL, 1
+};
+
+typedef struct last
+  {
+    char c;			/* The last character */
+    struct last *left;		/* used in balanced   */
+    struct last *right;		/* binary tree        */
+    Recode_Rules *pt;		/* location of approriate group */
+  }
+Last_Char_Node;
+
+/*------------
+       s
+     /   \
+    l     x
+   / \   / \
+  d   r t   z
+         \
+          v
+---------------*/
+static Last_Char_Node pr[] =
+{
+  'd', NULL, NULL, Rules,
+  'l', pr, pr + 2, Rules + 11,
+  'r', NULL, NULL, Rules + 12,
+  's', pr + 1, pr + 6, Rules + 15,
+  't', NULL, pr + 5, Rules + 16,
+  'v', NULL, NULL, Rules + 23,
+  'x', pr + 4, pr + 7, Rules + 25,
+  'z', NULL, NULL, Rules + 33,
+};
+
+
+/*****************************************************************************
+ *
+ *  Recode the stem according to the transformation rules.
+ *
+ *****************************************************************************/
+
+static void
+recode_stem (char *stem_end)
+{
+  static Last_Char_Node *root = pr + 3;
+  Last_Char_Node *p_last = root;
+  Recode_Rules *rule;		/* points to the transformation list */
+  char *h,			/* points to start of possible ending */
+    ch,				/* last character of the old ending  */
+    ch2;
+
+  h = stem_end - 1;
+  ch = *stem_end;
+  if (*h == ch)			/* Check for double consonant        */
+    {
+      if (strchr ("bdglmnprst", ch) != NULL)
+	{
+	  *stem_end = EOS;
+	  stem_end = h;
+	}
+    }
+
+  do				/* Check for the last character       */
+    {
+      ch2 = p_last->c;
+      if (ch == ch2)
+	break;
+      else if (ch > ch2)
+	p_last = p_last->right;
+      else
+	p_last = p_last->left;
+    }
+  while (p_last != NULL);
+
+  if (p_last != NULL)		/* Check for the rest of suffix list */
+    {
+      rule = p_last->pt;
+      for (;;)
+	{
+	  h = stem_end - rule->old_offset;
+	  if (strcmp (h, rule->old_end) == 0)
+	    {
+	      if (!rule->cond || (*rule->cond) (*(h - 1)))
+		{
+		  (void) strcpy (h, rule->new_end);
+		  break;
+		}
+	    }
+	  if (rule->end_group)
+	    break;
+	  rule++;
+	}
+    }
+}
+
+/* ======================================================================
+
+ *    List of endings and the method to remove the ending 
+ *
+ * ======================================================================*/
+
+/************ Data structures for list of endings  ********************/
+
+typedef struct
+{
+  char *ending;			/* old ending                */
+  int (*cond) ();		/* conditional rule          */
+  signed char left_offset;	/* used to find the siblings */
+  signed char right_offset;	/* in balanced binary tree   */
+}
+Ending_List;
+
+/*
+   The original list of endings is re-organised into groups having
+   the same length and the same first character.
+ */
+
+static Ending_List List[] =
+{
+  "a", NULL, 0, 0,
+
+  "ae", NULL, 0, 0,
+  "al", BB, -1, 2,
+  "ar", X, 0, 0,
+  "as", B, -1, 0,
+
+  "acy", NULL, 0, 1,
+  "age", B, 0, 0,
+  "aic", NULL, -2, 1,
+  "als", BB, 0, 0,
+  "ant", B, -2, 2,
+  "ars", O, 0, 0,
+  "ary", F, -1, 2,
+  "ata", NULL, 0, 0,
+  "ate", NULL, -1, 0,
+
+  "able", NULL, 0, 1,
+  "ably", NULL, 0, 0,
+  "ages", B, -2, 2,
+  "ally", B, 0, 0,
+  "ance", B, -1, 1,
+  "ancy", B, 0, 0,
+  "ants", B, -4, 4,
+  "aric", NULL, 0, 0,
+  "arly", K, -1, 1,
+  "ated", I, 0, 0,
+  "ates", NULL, -2, 2,
+  "atic", B, 0, 0,
+  "ator", NULL, -1, 0,
+
+  "acies", NULL, 0, 0,
+  "acity", NULL, -1, 1,
+  "aging", B, 0, 0,
+  "aical", NULL, -2, 2,
+  "alist", NULL, 0, 0,
+  "alism", B, -1, 0,
+  "ality", NULL, -3, 3,
+  "alize", NULL, 0, 1,
+  "allic", BB, 0, 0,
+  "anced", B, -2, 2,
+  "ances", B, 0, 0,
+  "antic", C, -1, 0,
+  "arial", NULL, -6, 6,
+  "aries", NULL, 0, 1,
+  "arily", NULL, 0, 0,
+  "arity", B, -2, 2,
+  "arize", NULL, 0, 0,
+  "aroid", NULL, -1, 0,
+  "ately", NULL, -3, 3,
+  "ating", I, 0, 1,
+  "ation", B, 0, 0,
+  "ative", NULL, -2, 2,
+  "ators", NULL, 0, 0,
+  "atory", NULL, -1, 1,
+  "ature", E, 0, 0,
+
+  "aceous", NULL, 0, 1,
+  "acious", B, 0, 0,
+  "action", G, -2, 2,
+  "alness", NULL, 0, 0,
+  "ancial", NULL, -1, 1,
+  "ancies", NULL, 0, 0,
+  "ancing", B, -4, 4,
+  "ariser", NULL, 0, 0,
+  "arized", NULL, -1, 1,
+  "arizer", NULL, 0, 0,
+  "atable", NULL, -2, 2,
+  "ations", B, 0, 0,
+  "atives", NULL, -1, 0,
+
+  "ability", NULL, 0, 1,
+  "aically", NULL, 0, 0,
+  "alistic", B, -2, 2,
+  "alities", NULL, 0, 0,
+  "ariness", E, -1, 0,
+  "aristic", NULL, -3, 3,
+  "arizing", NULL, 0, 1,
+  "ateness", NULL, 0, 0,
+  "atingly", NULL, -2, 2,
+  "ational", B, 0, 0,
+  "atively", NULL, -1, 1,
+  "ativism", NULL, 0, 0,
+
+  "ableness", NULL, 0, 1,
+  "arizable", NULL, 0, 0,
+
+  "allically", C, 0, 0,
+  "antaneous", NULL, -1, 1,
+  "antiality", NULL, 0, 0,
+  "arisation", NULL, -2, 2,
+  "arization", NULL, 0, 0,
+  "ationally", B, -1, 1,
+  "ativeness", NULL, 0, 0,
+
+  "antialness", NULL, 0, 0,
+  "arisations", NULL, -1, 1,
+  "arizations", NULL, 0, 0,
+
+  "alistically", B, 0, 1,
+  "arizability", NULL, 0, 0,
+
+  "e", NULL, 0, 0,
+
+  "ed", E, 0, 0,
+  "en", F, -1, 1,
+  "es", E, 0, 0,
+
+  "eal", Y, 0, 0,
+  "ear", Y, -1, 1,
+  "ely", E, 0, 0,
+  "ene", E, -2, 2,
+  "ent", C, 0, 0,
+  "ery", E, -1, 1,
+  "ese", NULL, 0, 0,
+
+  "ealy", Y, 0, 1,
+  "edly", E, 0, 0,
+  "eful", NULL, -2, 1,
+  "eity", NULL, 0, 0,
+  "ence", NULL, -2, 2,
+  "ency", NULL, 0, 0,
+  "ened", E, -1, 2,
+  "enly", E, 0, 0,
+  "eous", NULL, -1, 0,
+
+  "early", Y, 0, 1,
+  "ehood", NULL, 0, 0,
+  "eless", NULL, -2, 2,
+  "elity", NULL, 0, 0,
+  "ement", NULL, -1, 0,
+  "enced", NULL, -3, 3,
+  "ences", NULL, 0, 1,
+  "eness", E, 0, 0,
+  "ening", E, -2, 2,
+  "ental", NULL, 0, 0,
+  "ented", C, -1, 1,
+  "ently", NULL, 0, 0,
+
+  "eature", Z, 0, 0,
+  "efully", NULL, -1, 1,
+  "encies", NULL, 0, 0,
+  "encing", NULL, -2, 2,
+  "ential", NULL, 0, 0,
+  "enting", C, -1, 1,
+  "entist", NULL, 0, 1,
+  "eously", NULL, 0, 0,
+
+  "elihood", E, 0, 1,
+  "encible", NULL, 0, 0,
+  "entally", NULL, -2, 2,
+  "entials", NULL, 0, 0,
+  "entiate", NULL, -1, 1,
+  "entness", NULL, 0, 0,
+
+  "entation", NULL, 0, 0,
+  "entially", NULL, -1, 1,
+  "eousness", NULL, 0, 0,
+
+  "eableness", E, 0, 1,
+  "entations", NULL, 0, 0,
+  "entiality", NULL, -2, 2,
+  "entialize", NULL, 0, 0,
+  "entiation", NULL, -1, 0,
+
+  "entialness", NULL, 0, 0,
+
+  "ful", NULL, 0, 0,
+
+  "fully", NULL, 0, 0,
+
+  "fulness", NULL, 0, 0,
+
+  "hood", NULL, 0, 0,
+
+  "i", NULL, 0, 0,
+
+  "ia", NULL, 0, 0,
+  "ic", NULL, -1, 1,
+  "is", NULL, 0, 0,
+
+  "ial", NULL, 0, 0,
+  "ian", NULL, -1, 1,
+  "ics", NULL, 0, 1,
+  "ide", L, 0, 0,
+  "ied", NULL, -3, 3,
+  "ier", NULL, 0, 0,
+  "ies", P, -1, 0,
+  "ily", NULL, -1, 1,
+  "ine", M, 0, 0,
+  "ing", N, -5, 5,
+  "ion", Q, 0, 0,
+  "ish", C, -1, 1,
+  "ism", B, 0, 1,
+  "ist", NULL, 0, 0,
+  "ite", AA, -3, 3,
+  "ity", NULL, 0, 0,
+  "ium", NULL, -1, 0,
+  "ive", NULL, -1, 1,
+  "ize", F, 0, 0,
+
+  "ials", NULL, 0, 0,
+  "ians", NULL, -1, 0,
+  "ible", NULL, -1, 1,
+  "ibly", NULL, 0, 0,
+  "ical", NULL, -2, 2,
+  "ides", L, 0, 0,
+  "iers", NULL, -1, 1,
+  "iful", NULL, 0, 0,
+  "ines", M, -4, 4,
+  "ings", N, 0, 0,
+  "ions", B, -1, 1,
+  "ious", NULL, 0, 0,
+  "isms", B, -2, 2,
+  "ists", NULL, 0, 0,
+  "itic", H, -1, 1,
+  "ized", F, 0, 1,
+  "izer", F, 0, 0,
+
+  "ially", NULL, 0, 0,
+  "icant", NULL, -1, 1,
+  "ician", NULL, 0, 0,
+  "icide", NULL, -2, 2,
+  "icism", NULL, 0, 0,
+  "icist", NULL, -1, 0,
+  "icity", NULL, -3, 3,
+  "idine", I, 0, 1,
+  "iedly", NULL, 0, 0,
+  "ihood", NULL, -2, 2,
+  "inate", NULL, 0, 0,
+  "iness", NULL, -1, 0,
+  "ingly", B, -6, 6,
+  "inism", J, 0, 1,
+  "inity", CC, 0, 0,
+  "ional", NULL, -2, 2,
+  "ioned", NULL, 0, 0,
+  "ished", NULL, -1, 0,
+  "istic", NULL, -3, 3,
+  "ities", NULL, 0, 1,
+  "itous", NULL, 0, 0,
+  "ively", NULL, -2, 2,
+  "ivity", NULL, 0, 0,
+  "izers", F, -1, 1,
+  "izing", F, 0, 0,
+
+  "ialist", NULL, 0, 0,
+  "iality", NULL, -1, 1,
+  "ialize", NULL, 0, 0,
+  "ically", NULL, -2, 2,
+  "icance", NULL, 0, 0,
+  "icians", NULL, -1, 1,
+  "icists", NULL, 0, 0,
+  "ifully", NULL, -4, 4,
+  "ionals", NULL, 0, 0,
+  "ionate", D, -1, 1,
+  "ioning", NULL, 0, 0,
+  "ionist", NULL, -2, 2,
+  "iously", NULL, 0, 0,
+  "istics", NULL, -1, 1,
+  "izable", E, 0, 0,
+
+  "ibility", NULL, 0, 0,
+  "icalism", NULL, -1, 1,
+  "icalist", NULL, 0, 1,
+  "icality", NULL, 0, 0,
+  "icalize", NULL, -3, 3,
+  "ication", G, 0, 0,
+  "icianry", NULL, -1, 0,
+  "ination", NULL, -1, 1,
+  "ingness", NULL, 0, 0,
+  "ionally", NULL, -5, 5,
+  "isation", NULL, 0, 0,
+  "ishness", NULL, -1, 1,
+  "istical", NULL, 0, 1,
+  "iteness", NULL, 0, 0,
+  "iveness", NULL, -3, 3,
+  "ivistic", NULL, 0, 0,
+  "ivities", NULL, -1, 0,
+  "ization", F, -1, 1,
+  "izement", NULL, 0, 0,
+
+  "ibleness", NULL, 0, 0,
+  "icalness", NULL, -1, 1,
+  "ionalism", NULL, 0, 0,
+  "ionality", NULL, -2, 2,
+  "ionalize", NULL, 0, 0,
+  "iousness", NULL, -1, 1,
+  "izations", NULL, 0, 0,
+
+  "ionalness", NULL, 0, 1,
+  "istically", NULL, 0, 0,
+  "itousness", NULL, -2, 2,
+  "izability", NULL, 0, 0,
+  "izational", NULL, -1, 0,
+
+  "izationally", B, 0, 0,
+
+  "ly", B, 0, 0,
+
+  "less", NULL, 0, 1,
+  "lily", NULL, 0, 0,
+
+  "lessly", NULL, 0, 0,
+
+  "lessness", NULL, 0, 0,
+
+  "ness", NULL, 0, 0,
+
+  "nesses", NULL, 0, 0,
+
+  "o", NULL, 0, 0,
+
+  "on", S, 0, 1,
+  "or", T, 0, 0,
+
+  "oid", NULL, 0, 0,
+  "one", R, -1, 1,
+  "ous", NULL, 0, 0,
+
+  "ogen", NULL, 0, 0,
+
+  "oidal", NULL, 0, 0,
+  "oides", NULL, -1, 2,
+  "otide", NULL, 0, 0,
+  "ously", NULL, -1, 0,
+
+  "oidism", NULL, 0, 0,
+
+  "oidally", NULL, 0, 1,
+  "ousness", NULL, 0, 0,
+
+  "s", W, 0, 0,
+
+  "s'", NULL, 0, 0,
+
+  "um", U, 0, 1,
+  "us", V, 0, 0,
+
+  "ward", NULL, 0, 1,
+  "wise", NULL, 0, 0,
+
+  "y", B, 0, 0,
+
+  "yl", R, 0, 0,
+
+  "ying", B, 0, 1,
+  "yish", NULL, 0, 0,
+
+  "'s", NULL, 0, 0,
+};
+
+typedef struct node
+  {
+    char c;			/* First character  */
+    struct node *left;		/* used in balanced */
+    struct node *right;		/* binary tree      */
+    Ending_List *ptr[11];	/* the approriate location */
+  }
+First_Char_Node;
+
+static First_Char_Node First[] =
+{
+  '\'', NULL, NULL,
+  {NULL,
+   List + 293, NULL, NULL, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL},
+
+  'a', First, NULL,
+  {List,
+   List + 2, List + 9, List + 20, List + 39, List + 58,
+   List + 70, List + 77, List + 82, List + 87, List + 89},
+
+  'e', First + 1, First + 4,
+  {List + 91,
+   List + 93, List + 98, List + 106, List + 116, List + 126,
+   List + 133, List + 138, List + 142, List + 145, NULL},
+
+  'f', NULL, NULL,
+  {NULL,
+   NULL, List + 146, NULL, List + 147, NULL,
+   List + 148, NULL, NULL, NULL, NULL},
+
+  'h', First + 3, First + 5,
+  {NULL,
+   NULL, NULL, List + 149, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL},
+
+  'i', NULL, NULL,
+  {List + 150,
+   List + 152, List + 163, List + 181, List + 202, List + 222,
+   List + 239, List + 252, List + 258, NULL, List + 261},
+
+  'l', First + 2, First + 10,
+  {NULL,
+   List + 262, NULL, List + 263, NULL, List + 265,
+   NULL, List + 266, NULL, NULL, NULL},
+
+  'n', NULL, NULL,
+  {NULL,
+   NULL, NULL, List + 267, NULL, List + 268,
+   NULL, NULL, NULL, NULL, NULL},
+
+  'o', First + 7, First + 9,
+  {List + 269,
+   List + 270, List + 273, List + 275, List + 277, List + 280,
+   List + 281, NULL, NULL, NULL, NULL},
+
+  's', NULL, NULL,
+  {List + 283,
+   List + 284, NULL, NULL, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL},
+
+  'u', First + 8, First + 12,
+  {NULL,
+   List + 285, NULL, NULL, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL},
+
+  'w', NULL, NULL,
+  {NULL,
+   NULL, NULL, List + 287, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL},
+
+  'y', First + 11, NULL,
+  {List + 289,
+   List + 290, NULL, List + 291, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL},
+};
+
+
+/******************************************************************************
+ *
+ *  Look for a match in the suffix list.
+ *  Return the pointer to the end of the new stem if there is a match.
+ *  Otherwise, return the pointer to the end of the original word.
+ *
+ *  Method:
+ *      * Search for the first character in the suffix list.
+ *      * If there is match, search for the rest of the suffix list.
+ *         
+ *****************************************************************************/
+
+static char *
+remove_ending (char *word, int w_len)
+{
+  static First_Char_Node *root = First + 6;	/* the root of binary tree is 'l' */
+  First_Char_Node *p_first;	/* Points to the first character      */
+  /* of the possible suffix             */
+  Ending_List *p_list;		/* Points to the List of Endings      */
+  char *suffix_start,		/* Points to start of possible suffix */
+   *stem_end,			/* Points to the end of possible stem */
+    ch1, ch2;
+  int s_len,			/* Possible stem length               */
+    e_offset,			/* Offset from the end to the start of */
+  /* possible suffix                    */
+    not_done = 1, cmp;
+
+  stem_end = word + w_len - 1;
+  if (w_len > PREDEFINED_SIZE)	/* find the start of suffix   */
+    suffix_start = word + w_len - MAX_ENDING_SIZE;
+  else
+    suffix_start = word + MIN_STEM_LENGTH;
+
+  ch1 = *suffix_start;
+  do				/* Search for the first character     */
+    {
+      p_first = root;
+      do
+	{
+	  ch2 = p_first->c;
+	  if (ch1 == ch2)
+	    break;
+	  else if (ch1 > ch2)
+	    p_first = p_first->right;
+	  else
+	    p_first = p_first->left;
+	}
+      while (p_first != NULL);
+
+      if (p_first != NULL)	/* Search for the rest */
+	{
+	  e_offset = stem_end - suffix_start;
+	  if ((p_list = p_first->ptr[e_offset]) != NULL)
+	    {
+	      for (;;)		/* no need to compare the first char  */
+		{
+		  cmp = strcmp (suffix_start + 1, p_list->ending + 1);
+		  if (cmp > 0)
+		    if (p_list->right_offset)
+		      p_list += p_list->right_offset;
+		    else
+		      break;
+		  else if (cmp < 0)
+		    if (p_list->left_offset)
+		      p_list += p_list->left_offset;
+		    else
+		      break;
+		  else
+		    {
+		      s_len = suffix_start - word;
+		      if (!p_list->cond ||
+			  (*p_list->cond) (s_len, suffix_start - 1))
+			{
+			  *suffix_start = EOS;
+			  stem_end = suffix_start - 1;
+			  not_done = 0;
+			}
+		      break;
+		    }
+		}
+	    }
+	}
+      suffix_start++;
+    }
+  while (not_done && ((ch1 = *suffix_start) != EOS));
+  return (stem_end);
+}
Index: /indexers/branches/3.03a/mg/lib/lovinstem.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/lovinstem.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/lovinstem.h	(revision 14757)
@@ -0,0 +1,28 @@
+/**************************************************************************
+ *
+ * lovinstem.h -- Lovins' stemmer header
+ * Copyright (C) 1994  Linh Huynh, 
+ *                     (glued into library by tes@kbs.citri.edu.au)
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef LOVINSTEM_H
+#define LOVINSTEM_H
+
+void lovinstem (unsigned char *word);
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/memlib.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/memlib.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/memlib.c	(revision 14757)
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * memlib.c -- Malloc wrappers
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "memlib.h"
+
+/* Defined as strdup is not an ANSI function */
+/* change the name so we do not have problems with other libs */
+char *
+my_mg_strdup(const char *str)
+{
+  char *ret_str = malloc(strlen(str)+1);
+  if (ret_str) return strcpy(ret_str, str);
+  else return (char*) 0;
+}
+
+
+Malloc_func Xmalloc = malloc;
+
+Realloc_func Xrealloc = realloc;
+
+Free_func Xfree = free;
+
+Strdup_func Xstrdup = my_mg_strdup;
Index: /indexers/branches/3.03a/mg/lib/memlib.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/memlib.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/memlib.h	(revision 14757)
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * memlib.h -- Malloc wrappers
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+
+#ifndef H_MEMLIB
+#define H_MEMLIB
+
+#ifdef STD_MEM
+
+#define Xmalloc malloc
+#define Xrealloc realloc
+#define Xfree free
+#define Xstrdup strdup
+
+#else
+
+
+#include "sysfuncs.h"
+
+typedef void *(*Malloc_func) (size_t);
+typedef void *(*Realloc_func) (void *, size_t);
+typedef void (*Free_func) (void *);
+typedef char *(*Strdup_func) (const char *);
+
+extern Malloc_func Xmalloc;
+extern Realloc_func Xrealloc;
+extern Free_func Xfree;
+extern Strdup_func Xstrdup;
+#endif
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/messages.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/messages.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/messages.c	(revision 14757)
@@ -0,0 +1,75 @@
+/**************************************************************************
+ *
+ * messages.c -- Message and error functions
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include <stdarg.h>
+#include "messages.h"
+
+char *msg_prefix = "";
+
+
+void VOLATILE 
+FatalError (int ExitCode, const char *fmt,...)
+{
+  char buf[1024];
+  char *s, *pfx;
+  va_list args;
+  va_start (args, fmt);
+  vsprintf (buf, fmt, args);
+  s = strrchr (buf, '\n');
+  if (!s || *(s + 1) != '\0')
+    strcat (buf, "\n");
+  pfx = strrchr (msg_prefix, '/');
+  pfx = pfx ? pfx + 1 : msg_prefix;
+  fprintf (stderr, "%s%s%s", pfx, *pfx ? " : " : "", buf);
+  exit (ExitCode);
+}
+
+
+
+/*
+ * This function writes messages to stderr. Due to the fact that I can't 
+ * guarantee that the fprintf call is monatomic I have to implement a 
+ * semaphore system.
+ */
+void 
+Message (const char *fmt,...)
+{
+  char buf[1024];
+  char *s, *pfx;
+  va_list args;
+
+#ifdef QUIET
+  return; /* stop those messages!!!! */
+#endif  
+
+  va_start (args, fmt);
+  vsprintf (buf, fmt, args);
+  s = strrchr (buf, '\n');
+  if (!s || *(s + 1) != '\0')
+    strcat (buf, "\n");
+
+  pfx = strrchr (msg_prefix, '/');
+  pfx = pfx ? pfx + 1 : msg_prefix;
+  fprintf (stderr, "%s%s%s", pfx, *pfx ? " : " : "", buf);
+
+}
Index: /indexers/branches/3.03a/mg/lib/messages.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/messages.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/messages.h	(revision 14757)
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * messages.h -- Message and error functions
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_MESSAGES
+#define H_MESSAGES
+
+#ifdef __GNUC__
+#define VOLATILE volatile
+#else
+#define VOLATILE
+#endif
+
+extern char *msg_prefix;
+
+void VOLATILE FatalError (int ExitCode, const char *fmt,...);
+
+void Message (const char *fmt,...);
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/mgheap.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/mgheap.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/mgheap.c	(revision 14757)
@@ -0,0 +1,148 @@
+/**************************************************************************
+ *
+ * mgheap.c -- Heap routines
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "mgheap.h"
+
+#define SWAP(s, a, b) 						\
+do {								\
+     register int __i;						\
+     register char *__a = (a), *__b = (b);			\
+     for (__i = (s); __i; __i--)				\
+       {							\
+         register char __t = *__a;				\
+	 *__a++ = *__b; *__b++ = __t;				\
+       }							\
+} while(0)
+
+
+
+#define COPY(s, dst, src) 					\
+do {								\
+     register int __i;						\
+     register char *__dst = (dst), *__src = (src);		\
+     for (__i = (s); __i; __i--)				\
+       *__dst++ = *__src++;					\
+} while(0)
+
+
+
+static void 
+heap_heapify (void *heap, int size, int num, int curr, heap_comp hc)
+{
+  register int child = curr * 2;
+  while (child <= num)
+    {
+      if (child < num && hc ((char *) heap + child * size,
+			     (char *) heap + child * size - size) < 0)
+	child++;
+      if (hc ((char *) heap + (curr - 1) * size, (char *) heap + (child - 1) * size) > 0)
+	{
+	  SWAP (size, (char *) heap + (curr - 1) * size,
+		(char *) heap + (child - 1) * size);
+	  curr = child;
+	  child = child * 2;
+	}
+      else
+	break;
+    }
+}
+
+static void 
+heap_pullup (void *heap, int size, int num, heap_comp hc)
+{
+  register int curr = num;
+  register int parent = curr >> 1;
+  while (parent &&
+	 hc ((char *) heap + (curr - 1) * size, (char *) heap + (parent - 1) * size) < 0)
+    {
+      SWAP (size, (char *) heap + (curr - 1) * size,
+	    (char *) heap + (parent - 1) * size);
+      curr = parent;
+      parent = curr >> 1;
+    }
+}
+
+/************************************************************************
+ *
+ * NOTE: If you choose to change the comparison function the first thing 
+ *       you do after changing the function is call heap_build.
+ *
+ */
+void 
+heap_build (void *heap, int size, int num, heap_comp hc)
+{
+  register int i;
+  for (i = num / 2; i > 0; i--)
+    heap_heapify (heap, size, num, i, hc);
+}
+
+
+
+/****************************************************
+ *
+ * NOTE : The heap must be built before heap_sort is called. 
+ *        This has the effect of reversing the order of the array.
+ *		e.g. if your comparison function is designed to pull the
+ *                   biggest thing off the heap first then the result of
+ *		     sorting with this function will be to put the bigest
+ *                   thing at the end of the array.
+ *
+ */
+void 
+heap_sort (void *heap, int size, int num, heap_comp hc)
+{
+  register int i;
+  for (i = num; i > 1; i--)
+    {
+      SWAP (size, heap, (char *) heap + (i - 1) * size);
+      heap_heapify (heap, size, i - 1, 1, hc);
+    }
+}
+
+
+void 
+heap_deletehead (void *heap, int size, int *num, heap_comp hc)
+{
+  (*num)--;
+  SWAP (size, heap, (char *) heap + *num * size);
+  heap_heapify (heap, size, *num, 1, hc);
+}
+
+
+void 
+heap_changedhead (void *heap, int size, int num, heap_comp hc)
+{
+  heap_heapify (heap, size, num, 1, hc);
+}
+
+
+/***********************************************************************
+ *
+ * This assumes that the item has been added to the end of the
+ * array that is the heap. But that num has not been changed. 
+ *
+ */
+void 
+heap_additem (void *heap, int size, int *num, heap_comp hc)
+{
+  (*num)++;
+  heap_pullup (heap, size, *num, hc);
+}
Index: /indexers/branches/3.03a/mg/lib/mgheap.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/mgheap.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/mgheap.h	(revision 14757)
@@ -0,0 +1,82 @@
+/**************************************************************************
+ *
+ * mgheap.h -- Heap routines
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+/* Care should be taken when using these routines as NO error checking is
+ * done.
+ */
+
+
+
+/* The heap comparison routine should return 
+ * <0 : If a should be before b
+ *  0 : If a and b are equal
+ * >0 : If a should be after b
+ */
+typedef int (*heap_comp) (void *a, void *b);
+
+
+/************************************************************************
+ *
+ * NOTE: If you choose to change the comparison function the first thing 
+ *       you do after changing the function is call heap_build.
+ *
+ */
+void heap_build (void *heap, int size, int num, heap_comp hc);
+
+
+
+/************************************************************************
+ *
+ * NOTE : The heap must be built before heap_sort is called.
+ *        This has the effect of reversing the order of the array.
+ *		e.g. if your comparison function is designed to pull the
+ *                   biggest thing off the heap first then the result of
+ *		     sorting with this function will be to put the bigest
+ *                   thing at the end of the array.
+ *
+ */
+void heap_sort (void *heap, int size, int num, heap_comp hc);
+
+/***********************************************************************
+ *
+ * NOTE: After deleting the head the heap will be one item shorter.
+ *       The deleted item will be placed at the end of the heap.
+ *
+ */
+void heap_deletehead (void *heap, int size, int *num, heap_comp hc);
+
+
+/***********************************************************************
+ *
+ * If you change the "value" of the root node of the heap then you
+ * should call this to re-pritorize the heap.
+ *
+ */
+void heap_changedhead (void *heap, int size, int num, heap_comp hc);
+
+
+/***********************************************************************
+ *
+ * This assumes that the item has been added to the end of the
+ * array that is the heap. But that num has not been changed. 
+ *
+ */
+void heap_additem (void *heap, int size, int *num, heap_comp hc);
Index: /indexers/branches/3.03a/mg/lib/netorder.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/netorder.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/netorder.h	(revision 14757)
@@ -0,0 +1,178 @@
+#ifndef NETORDER_H
+#define NETORDER_H
+
+#include "sysfuncs.h"
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+#include "win32in.h"
+#else
+# include <netinet/in.h>
+#endif
+
+
+#ifndef WORDS_BIGENDIAN
+
+/* double */
+#define HTOND(d)                                                                                  \
+        do {                                                                                      \
+             unsigned long tmph, tmpl;                                                            \
+	     bcopy ((char *) &d, (char *) &tmph, sizeof(double) >> 1);                            \
+	     bcopy ((char *) &d + (sizeof(double) >> 1), (char *) &tmpl, sizeof (double) >> 1);   \
+	     tmph = htonl (tmph);                                                                 \
+	     tmpl = htonl (tmpl);                                                                 \
+	     bcopy ((char *) &tmpl, (char *) &d, sizeof (double) >> 1);                           \
+	     bcopy ((char *) &tmph, (char *) &d + (sizeof(double) >> 1), sizeof (double) >> 1);   \
+	}while(0)
+#define NTOHD(d)                                                                                  \
+        do {                                                                                      \
+             unsigned long tmph, tmpl;                                                            \
+	     bcopy ((char *) &d, (char *) &tmph, sizeof(double) >> 1);                            \
+	     bcopy ((char *) &d + (sizeof(double) >> 1), (char *) &tmpl, sizeof (double) >> 1);   \
+	     tmph = ntohl (tmph);                                                                 \
+	     tmpl = ntohl (tmpl);                                                                 \
+	     bcopy ((char *) &tmpl, (char *) &d, sizeof (double) >> 1);                           \
+	     bcopy ((char *) &tmph, (char *) &d + (sizeof(double) >> 1), sizeof (double) >> 1);   \
+        }while(0)
+#define HTOND2(hd, nd)                                                                            \
+        do {                                                                                      \
+             unsigned long tmph, tmpl;                                                            \
+	     bcopy ((char *) &hd, (char *) &tmph, sizeof(double) >> 1);                           \
+	     bcopy ((char *) &hd + (sizeof(double) >> 1), (char *) &tmpl, sizeof (double) >> 1);  \
+	     tmph = htonl (tmph);                                                                 \
+	     tmpl = htonl (tmpl);                                                                 \
+	     bcopy ((char *) &tmpl, (char *) &nd, sizeof (double) >> 1);                          \
+	     bcopy ((char *) &tmph, (char *) &nd + (sizeof(double) >> 1), sizeof (double) >> 1);  \
+	}while(0)
+#define NTOHD2(nd, hd)                                                                            \
+        do {                                                                                      \
+             unsigned long tmph, tmpl;                                                            \
+	     bcopy ((char *) &nd, (char *) &tmph, sizeof(double) >> 1);                           \
+	     bcopy ((char *) &nd + (sizeof(double) >> 1), (char *) &tmpl, sizeof (double) >> 1);  \
+	     tmph = ntohl (tmph);                                                                 \
+	     tmpl = ntohl (tmpl);                                                                 \
+	     bcopy ((char *) &tmpl, (char *) &hd, sizeof (double) >> 1);                          \
+	     bcopy ((char *) &tmph, (char *) &hd + (sizeof(double) >> 1), sizeof (double) >> 1);  \
+        }while(0)
+
+/* float */
+#define HTONF(f)                                                                   \
+        do {                                                                       \
+             unsigned long tmp;                                                    \
+             bcopy ((char *) &(f), (char *) &tmp, sizeof (float));                 \
+             HTONUL (tmp);                                                         \
+	     bcopy ((char *) &tmp, (char *) &(f), sizeof (float));                 \
+	}while(0)
+#define NTOHF(f)                                                                   \
+        do {                                                                       \
+             unsigned long tmp;                                                    \
+             bcopy ((char *) &(f), (char *) &tmp, sizeof (float));                 \
+	     NTOHUL (tmp);                                                         \
+	     bcopy ((char *) &tmp, (char *) &(f), sizeof (float));                 \
+	}while(0)
+#define HTONF2(hf, nf)                                                             \
+        do {                                                                       \
+             unsigned long tmp;                                                    \
+             bcopy ((char *) &(hf), (char *) &tmp, sizeof (float));                \
+             HTONUL (tmp);                                                         \
+	     bcopy ((char *) &tmp, (char *) &(nf), sizeof (float));                \
+	}while(0)
+#define NTOHF2(nf, hf)                                                             \
+        do {                                                                       \
+             unsigned long tmp;                                                    \
+             bcopy ((char *) &(nf), (char *) &tmp, sizeof (float));                \
+	     NTOHUL (tmp);                                                         \
+	     bcopy ((char *) &tmp, (char *) &(hf), sizeof (float));                \
+	}while(0)
+
+/* pointers */
+#define HTONP(p)          ((p) = (void *) htonl ((unsigned long) p))
+#define NTOHP(p)          ((p) = (void *) ntohl ((unsigned long) p))
+#define HTONP2(hp, np)    ((np) = (void *) htonl ((unsigned long) hp))
+#define NTOHP2(np, hp)    ((hp) = (void *) ntohl ((unsigned long) np))
+
+/* unsigned long */
+#define HTONUL(l)         ((l) = htonl((l)))
+#define NTOHUL(l)         ((l) = ntohl((l)))
+#define HTONUL2(hl, nl)   ((nl) = htonl ((hl)))
+#define NTOHUL2(nl, hl)   ((hl) = ntohl ((nl)))
+
+/* signed long */
+#define HTONSL(l)         ((l) = (long) htonl ((unsigned long) (l)))
+#define NTOHSL(l)         ((l) = (long) ntohl ((unsigned long) (l)))
+#define HTONSL2(hl, nl)   ((nl) = (long) htonl ((unsigned long) (hl)))
+#define NTOHSL2(nl, hl)   ((hl) = (long) ntohl ((unsigned long) (nl)))
+
+/* unsigned int */
+#define HTONUI(i)         ((i) = (unsigned int) htonl ((unsigned long) (i)))
+#define NTOHUI(i)         ((i) = (unsigned int) ntohl ((unsigned long) (i)))
+#define HTONUI2(hi, ni)   ((ni) = (unsigned int) htonl ((unsigned long) (hi)))
+#define NTOHUI2(ni, hi)   ((hi) = (unsigned int) ntohl ((unsigned long) (ni)))
+
+/* signed int */
+#define HTONSI(i)         ((i) = (int) htonl ((unsigned long) (i)))
+#define NTOHSI(i)         ((i) = (int) ntohl ((unsigned long) (i)))
+#define HTONSI2(hi, ni)   ((ni) = (int) htonl ((unsigned long) (hi)))
+#define NTOHSI2(ni, hi)   ((hi) = (int) ntohl ((unsigned long) (ni)))
+
+/* unsigned short */
+#define HTONUS(s)         ((s) = htons((s)))
+#define NTOHUS(s)         ((s) = ntohs((s)))
+#define HTONUS2(hs, ns)   ((ns) = htons((hs)))
+#define NTOHUS2(ns, hs)   ((hs) = ntohs((ns)))
+
+#else   /* WORDS_BIGENDIAN */
+
+/* double */
+#define HTOND(d)          (d)
+#define NTOHD(d)          (d)
+#define HTOND2(hd, nd)    ((hd) = (nd))
+#define NTOHD2(nd, hd)    ((nd) = (hd))
+
+/* float */
+#define HTONF(f)          (f)
+#define NTOHF(f)          (f)
+#define HTONF2(hf, nf)    ((nf) = (hf))
+#define NTOHF2(nf, hf)    ((hf) = (nf))
+
+/* pointers */
+#define HTONP(p)          (p)
+#define NTOHP(p)          (p)
+#define HTONP2(hp, np)    ((np) = (hp))
+#define NTOHP2(np, hp)    ((hp) = (np))
+
+/* unsigned long */
+#define HTONUL(l)         (l)
+#define NTOHUL(l)         (l)
+#define HTONUL2(hl, nl)   ((nl) = (hl))
+#define NTOHUL2(nl, hl)   ((hl) = (nl))
+
+/* signed long */
+#define HTONSL(l)         (l)
+#define NTOHSL(l)         (l)
+#define HTONSL2(hl, nl)   ((nl) = (hl))
+#define NTOHSL2(nl, hl)   ((hl) = (nl))
+
+/* unsigned int */
+#define HTONUI(i)         (i)
+#define NTOHUI(i)         (i)
+#define HTONUI2(hi, ni)   ((ni) = (hi))
+#define NTOHUI2(ni, hi)   ((hi) = (ni))
+
+/* signed int */
+#define HTONSI(i)         (i)
+#define NTOHSI(i)         (i)
+#define HTONSI2(hi, ni)   ((ni) = (hi))
+#define NTOHSI2(ni, hi)   ((hi) = (ni))
+
+/* unsigned short */
+#define HTONUS(s)         (s)
+#define NTOHUS(s)         (s)
+#define HTONUS2(hs, ns)   ((ns) = (hs))
+#define NTOHUS2(ns, hs)   ((hs) = (ns))
+
+
+
+#endif
+
+#endif /* netorder.h */
Index: /indexers/branches/3.03a/mg/lib/pathmax.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/pathmax.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/pathmax.h	(revision 14757)
@@ -0,0 +1,53 @@
+/* Define PATH_MAX somehow.  Requires sys/types.h.
+   Copyright (C) 1992 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 program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef _PATHMAX_H
+#define _PATHMAX_H
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
+   PATH_MAX but might cause redefinition warnings when sys/param.h is
+   later included (as on MORE/BSD 4.3).  */
+#if defined(_POSIX_VERSION) || (defined(HAVE_LIMITS_H) && !defined(__GNUC__))
+#include <limits.h>
+#endif
+
+#ifndef _POSIX_PATH_MAX
+#define _POSIX_PATH_MAX 255
+#endif
+
+#if !defined(PATH_MAX) && defined(_PC_PATH_MAX)
+#define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
+#endif
+
+/* Don't include sys/param.h if it already has been.  */
+#if defined(HAVE_SYS_PARAM_H) && !defined(PATH_MAX) && !defined(MAXPATHLEN)
+#include <sys/param.h>
+#endif
+
+#if !defined(PATH_MAX) && defined(MAXPATHLEN)
+#define PATH_MAX MAXPATHLEN
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX _POSIX_PATH_MAX
+#endif
+
+#endif /* _PATHMAX_H */
Index: /indexers/branches/3.03a/mg/lib/perf_hash.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/perf_hash.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/perf_hash.c	(revision 14757)
@@ -0,0 +1,1079 @@
+/**************************************************************************
+ *
+ * perf_hash.c -- Perfect hashing functions
+ * Copyright (C) 1992  Bohdan S. Majewski
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ * 1994 Neil Sharman
+ *      Small modifications were made to the interface so that it fitted in
+ *      with mg.
+ *
+ **************************************************************************/
+
+#define STRUCT
+
+#include "sysfuncs.h"
+
+#include "local_strings.h"
+#include "memlib.h"
+#include "messages.h"
+#include "perf_hash.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#define FALSE 0
+#define TRUE  1
+
+#define STATIC 0
+
+/* Random Number stuff */
+static long seed[] = {0, 0};
+#define RANDOM() irandm(seed)
+#define SEED_RANDOM(the_seed) do{ seed[0] = the_seed; }while(0)
+
+/* Max number of keys - must be a power of 2 minus 1 */
+static int MAX_M;
+
+
+static int MAX_CH;
+
+
+/* the width of the mapping tables  */
+static int MAX_L;
+
+
+
+#define c     1.23
+static int MAX_N;
+
+/* An arbitrary amount to add to both MAX_N and n for building tree/acyclic
+   graph -- John McPherson - jrm21 (22-02-2001) */
+#define MAX_N_HEADROOM  100
+
+
+static u_char *translate;
+
+#define MEMBER 0
+#define ERASED 1
+
+
+
+/* direction constants for the edge oriented 3-graph representation */
+#define A              0
+#define B        (MAX_M)
+#define C          (2*B)
+
+/* NODEa, NODEb, NODEc, FIRST and NEXT are used to represent a 3-graph */
+static int *NODEa, *NODEb, *NODEc;
+static int *FIRST;
+static int *NEXT;
+
+
+#define norm(e) ((e) % MAX_M)
+/* in general should be ((e) % MAX_M) but MAX_M = 2^k - 1 */
+
+
+static char *mk;		/* for marking edges/vertices as removed */
+static int *g;			/* array g defines a minimal perfect hash function */
+
+
+
+/* stack of edges, created during the independency */
+/* test, used in the assignment step               */
+static struct
+  {
+    int sp;
+    int *st;
+  }
+S;
+#define push(s, e) s.st[s.sp++] = (e)
+#define pop(s, e)  e = s.st[--s.sp]
+
+#ifndef STRUCT
+static long **tb0, **tb1, **tb2;
+#else
+struct tb_entry **tb;
+#endif
+
+
+static int 
+unique (int v)
+{				/* checks if vertex v belongs to only one edge */
+  return (FIRST[v] != 0 && NEXT[FIRST[v]] == 0) ? FIRST[v] : 0;
+}				/*unique */
+
+
+
+
+
+
+
+
+static void 
+delete (int v, int e)
+{				/* deletes edge e from list of v */
+
+  int b;
+
+  b = FIRST[v];
+  assert (norm (b) != 0);
+  if (norm (b) == e)
+    FIRST[v] = NEXT[FIRST[v]];
+  else
+    {
+      while (norm (NEXT[b]) != e)
+	{
+	  b = NEXT[b];
+	  assert (norm (b) != 0);
+	}
+      NEXT[b] = NEXT[NEXT[b]];
+    }
+}				/*delete */
+
+
+
+
+
+
+#if 0
+/* recursively removes the edges of a 3-graph which have at least */
+/* one unique vertex. The removed edges are placed on stack S     */
+static void 
+ph_remove (int e, int v)
+{
+  int b;
+  mk[e] = ERASED;
+  push (S, e);
+
+  if (NODEa[e] != v)
+    delete (NODEa[e], e);
+  if (NODEb[e] != v)
+    delete (NODEb[e], e);
+  if (NODEc[e] != v)
+    delete (NODEc[e], e);
+
+  if (NODEa[e] != v && mk[b = norm (unique (NODEa[e]))] == MEMBER)
+    ph_remove (b, NODEa[e]);
+  if (NODEb[e] != v && mk[b = norm (unique (NODEb[e]))] == MEMBER)
+    ph_remove (b, NODEb[e]);
+  if (NODEc[e] != v && mk[b = norm (unique (NODEc[e]))] == MEMBER)
+    ph_remove (b, NODEc[e]);
+}
+#else
+
+
+static int StackPos, StackMax;
+static struct Stack
+  {
+    int e, v, m;
+  }
+ *Stack = NULL;
+
+#define StackAdd(_e, _v, _m)						\
+  do {									\
+    if (StackPos == StackMax)						\
+      {									\
+        StackMax <<= 1;							\
+	if (!(Stack = Xrealloc(Stack, sizeof(*Stack) * StackMax)))	\
+	  return(-1);							\
+      }									\
+    Stack[StackPos].e = (_e);						\
+    Stack[StackPos].v = (_v);						\
+    Stack[StackPos++].m = (_m);						\
+  } while(0)
+
+
+static int 
+ph_remove (int e, int v)
+{
+  if (!Stack)
+    {
+      StackMax = 256;
+      if (!(Stack = Xmalloc (sizeof (*Stack) * StackMax)))
+	return (-1);
+      StackPos = 0;
+    }
+  Stack[StackPos].e = e;
+  Stack[StackPos].v = v;
+  Stack[StackPos].m = 0;
+  StackPos++;
+  while (StackPos)
+    {
+      int m, b;
+      StackPos--;
+      e = Stack[StackPos].e;
+      v = Stack[StackPos].v;
+      m = Stack[StackPos].m;
+
+
+      switch (m)
+	{
+	case 0:
+	  {
+	    mk[e] = ERASED;
+	    push (S, e);
+
+	    if (NODEa[e] != v)
+	      delete (NODEa[e], e);
+	    if (NODEb[e] != v)
+	      delete (NODEb[e], e);
+	    if (NODEc[e] != v)
+	      delete (NODEc[e], e);
+
+	    if (NODEa[e] != v && mk[b = norm (unique (NODEa[e]))] == MEMBER)
+	      {
+		Stack[StackPos++].m = 1;
+		StackAdd (b, NODEa[e], 0);
+		break;
+	      }
+	  }
+	case 1:
+	  {
+	    if (NODEb[e] != v && mk[b = norm (unique (NODEb[e]))] == MEMBER)
+	      {
+		Stack[StackPos++].m = 2;
+		StackAdd (b, NODEb[e], 0);
+		break;
+	      }
+	  }
+	case 2:
+	  if (NODEc[e] != v && mk[b = norm (unique (NODEc[e]))] == MEMBER)
+	    StackAdd (b, NODEc[e], 0);
+	}
+    }
+  return (0);
+}
+#endif
+
+
+
+
+
+/* returns TRUE if and only if set of edges created in the tree_builder */
+/* procedure form a 3-graph with independent edges. Edges of a 3-graph  */
+/* are independent iff repeated deletion of edges containing vertices   */
+/* of degree 1 results in a graph with no edges in it.                  */
+static int 
+acyclic (int m, int n)
+{
+
+  int v, e;
+  /* build list of edges for each node */
+  for (v = 1; v <= n; FIRST[v++] = 0);
+  for (e = 1; e <= m; e++)
+    {
+      NEXT[A + e] = FIRST[NODEa[e]];
+      FIRST[NODEa[e]] = A + e;
+      NEXT[B + e] = FIRST[NODEb[e]];
+      FIRST[NODEb[e]] = B + e;
+      NEXT[C + e] = FIRST[NODEc[e]];
+      FIRST[NODEc[e]] = C + e;
+
+      /* mark edge e as belonging to the hypergraph */
+      mk[e] = MEMBER;
+    }
+
+
+  S.sp = 0;			/* empty the stack */
+  mk[0] = ERASED;		/* a sentinel for the test below */
+  for (v = 1; v <= n; v++)
+    {
+      if (mk[e = norm (unique (v))] == MEMBER)
+	ph_remove (e, v);
+    }
+
+  /* check if any edges were left in the graph */
+  return S.sp == m;
+}				/*acyclic */
+
+
+
+
+
+
+
+
+/* repeatedly maps words into edges of a 3-graph until the edges */
+/* are independent.                                              */
+static int 
+tree_builder (int num, u_char ** keys, int *n)
+{
+
+  int e, k = 0;
+  int i, j;
+  u_char *w;
+
+  do
+    {
+      /* Added variable - need to increase MAX_N on allocate as well */
+      *n = (int) (num * c + MAX_N_HEADROOM); /* john mcpherson 22-02-2001 */
+
+      /* initialize tables of random integers */
+      for (i = 0; i < MAX_CH; i++)
+	for (j = 0; j < MAX_L; j++)
+	  {
+#ifndef STRUCT
+	    tb0[i][j] = RANDOM () % *n;
+	    tb1[i][j] = RANDOM () % *n;
+	    tb2[i][j] = RANDOM () % *n;
+#else
+	    struct tb_entry *tbp = &tb[i][j];
+	    tbp->tb0 = RANDOM () % *n;
+	    tbp->tb1 = RANDOM () % *n;
+	    tbp->tb2 = RANDOM () % *n;
+#endif
+	  }
+
+      /* compute an edge (NODEa[e], NODEb[e], NODEc[e]) for each word */
+      for (e = 1; e <= num; e++)
+	{
+	  /*generate an edge corresponding to the ith word */
+	  int x = 0, y = 0, z = 0, l;
+	  w = keys[e - 1];
+
+	  l = *w++;
+	  j = (l - 1) % MAX_L;
+
+	  do
+	    {
+#ifndef STRUCT
+	      x += tb0[translate[*w]][j];
+	      y += tb1[translate[*w]][j];
+	      z += tb2[translate[*w]][j];
+#else
+	      struct tb_entry *tbp = &tb[translate[*w]][j];
+	      x += tbp->tb0;
+	      y += tbp->tb1;
+	      z += tbp->tb2;
+#endif
+	      if (++j >= MAX_L)
+		j = 0;
+	      w++;
+	    }
+	  while (--l);
+	  x = (x % *n) + 1;
+	  y = (y % *n) + 1;
+	  z = (z % *n) + 1;
+	  if (y == x && ++y > *n)
+	    y = 1;
+	  if (z == x && ++z > *n)
+	    z = 1;
+	  if (z == y)
+	    {
+	      if (++z > *n)
+		z = 1;
+	      if (z == x && ++z > *n)
+		z = 1;
+	    }
+
+	  NODEa[e] = x;
+	  NODEb[e] = y;
+	  NODEc[e] = z;
+	}
+      if (++k > 50)		/* make sure we will not wait for ever */
+	FatalError (1, "Unable to generate the perfect hash function. "
+		    "This is probably because there aren't enough words");
+    }
+  while (!acyclic (num, *n));
+  return k;
+}				/*tree_builder */
+
+
+
+
+
+
+
+
+
+/* calculates values of the g function/array so that i-th word is */
+/* placed at the (i-1)st position of a hash table.                */
+static void 
+assign (int n)
+{
+
+  int v, w = 0, e;
+
+  /* mark all the vertices of the 3-graph as unassigned */
+  for (v = 1; v <= n; mk[v++] = FALSE);
+
+  while (S.sp > 0)
+    {
+      int xor = 0;
+      pop (S, e);
+      v = NODEa[e];
+      if (mk[v])
+	xor ^= g[v];
+      else
+	{
+	  g[w = v] = 0;
+	  mk[v] = TRUE;
+	}
+      v = NODEb[e];
+      if (mk[v])
+	xor ^= g[v];
+      else
+	{
+	  g[w = v] = 0;
+	  mk[v] = TRUE;
+	}
+      v = NODEc[e];
+      if (mk[v])
+	xor ^= g[v];
+      else
+	{
+	  g[w = v] = 0;
+	  mk[v] = TRUE;
+	}
+      g[w] = (e - 1) ^ xor;
+    }
+}				/*assign */
+
+
+
+
+
+
+
+
+
+/*check returns 0 if no error in mphf is detected, else returns error code */
+static int 
+check (int m)
+{
+
+  int e, err_code = 0;
+
+  /*for each word compute its place in hash table and check if correct */
+  for (e = 1; e <= m; e++)
+    {
+      if ((e - 1) != (g[NODEa[e]] ^ g[NODEb[e]] ^ g[NODEc[e]]))
+	{
+	  (void) fprintf (stderr, "Error for %dth word detected.\n", e);
+	  err_code = e;
+	}
+    }
+  return err_code;
+}				/*check */
+
+
+
+
+
+
+
+#if 0
+void 
+outputh (int m, int n)
+{
+
+  int i, j, w = (int) ceil (log10 ((double) n + 1.0)) + 1;
+
+#if 0
+  char *PRG =
+  "int h(char *s)\n"
+  "{\n"
+  "  int u, v, w, i;\n"
+  "i = (strlen(s) - 1) % _HXL;\n"
+  "  u = v = w = 0;\n"
+  "  while(*s)\n"
+  "    {\n"
+  "      u += mt1[(*s) - _HFC][i];\n"
+  "      v += mt2[(*s) - _HFC][i];\n"
+  "      w += mt3[(*s++) - _HFC][i];\n"
+  "      if(++i >= _HXL) i = 0;\n"
+  "    }\n"
+  "  u %= _HFN; v %= _HFN; w %= _HFN;\n"
+  "  if(u == v && ++v >= _HFN) v = 0;\n"
+  "  if(w == u && ++w >= _HFN) w = 0;\n"
+  "  if(w == v && ++w >= _HFN) w = 0;\n"
+  "  if(w == u && ++w >= _HFN) w = 0;\n"
+  "  return (g[u] ^ g[v] ^ g[w]) % _HFM;\n"
+  "};\n\n";
+#endif
+
+  char *PRG =
+  "int h(char *s)\n"
+  "{\n"
+  "  int u, v, w, i;\n"
+  "  i = (strlen(s) - 1) % _HXL;\n"
+  "  u = v = w = 0;\n"
+  "  while(*s)\n"
+  "    {\n"
+  "      if((u += mt1[(*s) - _HFC][i]) >= _HFN) u -= _HFN;\n"
+  "      if((v += mt2[(*s) - _HFC][i]) >= _HFN) v -= _HFN;\n"
+  "      if((w += mt3[(*s++) - _HFC][i]) >= _HFN) w -= _HFN;\n"
+  "      if(++i >= _HXL) i = 0;\n"
+  "    }\n"
+  "  if(u == v && ++v >= _HFN) v = 0;\n"
+  "  if(w == v) \n"
+  "    {\n"
+  "      if(++w >= _HFN) w = 0;\n"
+  "      if(w == u && ++w >= _HFN) w = 0;\n"
+  "    }\n"
+  "  else\n"
+  "    if(w == u)\n"
+  "      {\n"
+  "	     if(++w >= _HFN) w = 0;\n"
+  "	     if(w == v && ++w >= _HFN) w = 0;\n"
+  "      }\n"
+  "  return ((g[u] ^ g[v] ^ g[w]) > _HFM)? 0 : (g[u] ^ g[v] ^ g[w]);\n"
+  "}\n\n";
+
+  printf ("#define _HFN %d\n#define _HFC %d\n", n, fc);
+  printf ("#define _HFM %d\n#define _HXL %d\n", m, MAX_L);
+  printf ("#define _HFA %d\n\nstatic int g[_HFN] = {\n", lc - fc + 1);
+  for (i = 1; i < n; i++)
+    {
+      if (i % 8 == 0)
+	putchar ('\n');
+      printf ("%5d, ", g[i]);
+    }
+  printf ("%5d};\n\n", g[n]);
+
+  printf ("static int mt1[_HFA][_HXL] = {\n");
+  for (j = fc; j < lc; j++)
+    {
+      printf ("{");
+      for (i = 0; i < MAX_L - 1; i++)
+	printf ("%*d,", w, tb0[j][i]);
+      printf ("%*d},\n", w, tb0[j][MAX_L - 1]);
+    }
+  printf ("{");
+  for (i = 0; i < MAX_L - 1; i++)
+    printf ("%*d,", w, tb0[lc][i]);
+  printf ("%*d}\n", w, tb0[lc][MAX_L - 1]);
+  printf ("};\n\n");
+
+  printf ("static int mt2[_HFA][_HXL] = {\n");
+  for (j = fc; j < lc; j++)
+    {
+      printf ("{");
+      for (i = 0; i < MAX_L - 1; i++)
+	printf ("%*d,", w, tb1[j][i]);
+      printf ("%*d},\n", w, tb1[j][MAX_L - 1]);
+    }
+  printf ("{");
+  for (i = 0; i < MAX_L - 1; i++)
+    printf ("%*d,", w, tb1[lc][i]);
+  printf ("%*d}\n", w, tb1[lc][MAX_L - 1]);
+  printf ("};\n\n");
+
+  printf ("static int mt3[_HFA][_HXL] = {\n");
+  for (j = fc; j < lc; j++)
+    {
+      printf ("{");
+      for (i = 0; i < MAX_L - 1; i++)
+	printf ("%*d,", w, tb2[j][i]);
+      printf ("%*d},\n", w, tb2[j][MAX_L - 1]);
+    }
+  printf ("{");
+  for (i = 0; i < MAX_L - 1; i++)
+    printf ("%*d,", w, tb2[lc][i]);
+  printf ("%*d}\n", w, tb2[lc][MAX_L - 1]);
+  printf ("};\n\n");
+
+  printf ("%s", PRG);
+}				/*outputh */
+#endif
+
+
+
+
+
+
+
+static void 
+make_trans_func (int num, u_char ** keys)
+{
+  int i, j;
+
+  bzero ((char *) translate, sizeof (translate));
+
+  MAX_L = 1;
+  for (i = 0; i < num; i++)
+    {
+      unsigned len = keys[i][0];
+      u_char *s = keys[i] + 1;
+      for (; len; len--, s++)
+	translate[*s] = 1;
+      if (i)
+	{
+	  int l;
+	  l = prefixlen (keys[i - 1], keys[i]);
+	  if (l + 1 > MAX_L)
+	    MAX_L = l + 1;
+	}
+    }
+  j = 0;
+  for (i = 0; i < 256; i++)
+    if (translate[i])
+      translate[i] = j++;
+  MAX_CH = j;
+}
+
+
+static void 
+temp_free (void)
+{
+  if (NODEa)
+    Xfree (NODEa);
+  if (NODEb)
+    Xfree (NODEb);
+  if (NODEc)
+    Xfree (NODEc);
+  if (FIRST)
+    Xfree (FIRST);
+  if (NEXT)
+    Xfree (NEXT);
+  if (S.st)
+    Xfree (S.st);
+  if (mk)
+    Xfree (mk);
+}
+
+static void 
+all_free (void)
+{
+  int i;
+  temp_free ();
+  if (translate)
+    Xfree (translate);
+  if (g)
+    Xfree (g);
+#ifndef STRUCT
+  for (i = 0; i < MAX_CH; i++)
+    {
+      if (tb0 && tb0[i])
+	Xfree (tb0[i]);
+      if (tb1 && tb1[i])
+	Xfree (tb1[i]);
+      if (tb2 && tb2[i])
+	Xfree (tb2[i]);
+    }
+  if (tb0)
+    Xfree (tb0);
+  if (tb1)
+    Xfree (tb1);
+  if (tb2)
+    Xfree (tb2);
+#else
+  for (i = 0; i < MAX_CH; i++)
+    if (tb && tb[i])
+      Xfree (tb[i]);
+  if (tb)
+    Xfree (tb);
+#endif
+}
+
+static int 
+allocate_memory (void)
+{
+  int i, ok = 1;
+  NODEa = Xmalloc (sizeof (int) * (MAX_M + 1));
+  NODEb = Xmalloc (sizeof (int) * (MAX_M + 1));
+  NODEc = Xmalloc (sizeof (int) * (MAX_M + 1));
+  FIRST = Xmalloc (sizeof (int) * (MAX_N + 1));
+  NEXT = Xmalloc (sizeof (int) * (MAX_M + 1) * 3);
+  S.st = Xmalloc (sizeof (int) * MAX_M);
+  mk = Xmalloc (sizeof (char) * (MAX_N + 1));
+  g = Xmalloc (sizeof (int) * (MAX_N + 1));
+#ifndef STRUCT
+  tb0 = Xmalloc (sizeof (int *) * MAX_CH);
+  tb1 = Xmalloc (sizeof (int *) * MAX_CH);
+  tb2 = Xmalloc (sizeof (int *) * MAX_CH);
+  for (i = 0; i < MAX_CH; i++)
+    {
+      if (tb0)
+	if (!(tb0[i] = Xmalloc (sizeof (long) * MAX_L)))
+	    ok = 0;
+      if (tb1)
+	if (!(tb1[i] = Xmalloc (sizeof (long) * MAX_L)))
+	    ok = 0;
+      if (tb2)
+	if (!(tb2[i] = Xmalloc (sizeof (long) * MAX_L)))
+	    ok = 0;
+    }
+
+  if (!(NODEa && NODEb && NODEc && FIRST && NEXT && S.st && mk && g &&
+	tb0 && tb1 && tb2 && ok))
+    {
+      all_free ();
+      return (-1);
+    }
+#else
+  tb = Xmalloc (sizeof (struct tb_entry *) * MAX_CH);
+  for (i = 0; i < MAX_CH; i++)
+    if (tb)
+      if (!(tb[i] = Xmalloc (sizeof (struct tb_entry) * MAX_L)))
+	  ok = 0;
+
+  if (!(NODEa && NODEb && NODEc && FIRST && NEXT && S.st && mk && g &&
+	tb && ok))
+    {
+      all_free ();
+      return (-1);
+    }
+#endif
+  return (0);
+}
+
+
+perf_hash_data *
+gen_hash_func (int num, u_char ** keys, int r)
+{
+  int n;
+  perf_hash_data *phd;
+  translate = Xmalloc (sizeof (u_char) * 256);
+  bzero ((char *) translate, sizeof (u_char) * 256);  /* [RPAP - Feb 97: WIN32 Port] */
+  make_trans_func (num, keys);
+
+  if (r <= 0)
+    SEED_RANDOM ((long) time ((time_t *) NULL));
+  else
+    SEED_RANDOM (r);
+
+  MAX_M = num + 1;
+
+  /* For extremely small lexicons (<4 words), this isn't good enough! 
+   -- John McPherson jrm21 22-02-2001 */
+  /* MAX_N = MAX_M + MAX_M / 4; */
+  MAX_N = (int)(ceil (1.25 * MAX_M)); 
+  /* Add some space for "experimentation" of n in tree_builder() */
+  MAX_N += MAX_N_HEADROOM;
+
+  if (allocate_memory () == -1)
+    return (NULL);
+
+  /* construct an "acyclic" hypergraph */
+  tree_builder (num, keys, &n);
+  /* compute function g */
+  assign (n);
+
+  if (check (num) != 0)
+    FatalError (1, "An error has been detected in the mphf.");
+  temp_free ();
+
+  if (!(phd = Xmalloc (sizeof (perf_hash_data))))
+    return (NULL);
+
+  bcopy ((char *) &g[1], (char *) g, n * sizeof (int));
+
+  phd->MAX_L = MAX_L;
+  phd->MAX_N = n;
+  phd->MAX_M = num;
+  phd->MAX_CH = MAX_CH;
+  phd->translate = translate;
+  phd->g = g;
+#ifndef STRUCT
+  phd->tb0 = tb0;
+  phd->tb1 = tb1;
+  phd->tb2 = tb2;
+#else
+  phd->tb = tb;
+#endif
+  return (phd);
+}
+
+int 
+write_perf_hash_data (FILE * f, perf_hash_data * phd)
+{
+  int tot, i;
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONSI(phd->MAX_L);
+  HTONSI(phd->MAX_N);
+  HTONSI(phd->MAX_M);
+  HTONSI(phd->MAX_CH);
+
+  tot = fwrite ((char *) &phd->MAX_L, sizeof (int), 1, f) * sizeof (int);
+  tot += fwrite ((char *) &phd->MAX_N, sizeof (int), 1, f) * sizeof (int);
+  tot += fwrite ((char *) &phd->MAX_M, sizeof (int), 1, f) * sizeof (int);
+  tot += fwrite ((char *) &phd->MAX_CH, sizeof (int), 1, f) * sizeof (int);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHSI(phd->MAX_L);
+  NTOHSI(phd->MAX_N);
+  NTOHSI(phd->MAX_M);
+  NTOHSI(phd->MAX_CH);
+
+  tot += fwrite ((char *) phd->translate, sizeof (u_char), 256, f);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = 0; i < phd->MAX_N + 1; i++)
+    HTONSI(phd->g[i]);
+
+  tot += fwrite ((char *) phd->g, sizeof (int), phd->MAX_N + 1, f) * sizeof (int);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = 0; i < phd->MAX_N + 1; i++)
+    NTOHSI(phd->g[i]);
+
+#ifndef STRUCT
+  for (i = 0; i < phd->MAX_CH; i++)
+    {
+      /* [RPAP - Jan 97: Endian Ordering] */
+      int j;
+      for (j = 0; j < phd->MAX_L; j++)
+	{
+	  HTONSI(phd->tb0[i][j]);
+	  HTONSI(phd->tb1[i][j]);
+	  HTONSI(phd->tb2[i][j]);
+	}
+
+      tot += fwrite ((char *) phd->tb0[i], sizeof (int), phd->MAX_L, f) *
+        sizeof (int);
+      tot += fwrite ((char *) phd->tb1[i], sizeof (int), phd->MAX_L, f) *
+        sizeof (int);
+      tot += fwrite ((char *) phd->tb2[i], sizeof (int), phd->MAX_L, f) *
+        sizeof (int);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (j = 0; j < phd->MAX_L; j++)
+	{
+	  NTOHSI(phd->tb0[i][j]);
+	  NTOHSI(phd->tb1[i][j]);
+	  NTOHSI(phd->tb2[i][j]);
+	}
+    }
+#else
+  for (i = 0; i < phd->MAX_CH; i++)
+    {
+      /* [RPAP - Jan 97: Endian Ordering] */
+      int j;
+      for (j = 0; j < phd->MAX_L; j++)
+	{
+	  HTONSL(phd->tb[i][j].tb0);
+	  HTONSL(phd->tb[i][j].tb1);
+	  HTONSL(phd->tb[i][j].tb2);
+	}
+
+      tot += fwrite ((char *) phd->tb[i], sizeof (struct tb_entry), phd->MAX_L, f) *
+	sizeof (struct tb_entry);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (j = 0; j < phd->MAX_L; j++)
+	{
+	  NTOHSL(phd->tb[i][j].tb0);
+	  NTOHSL(phd->tb[i][j].tb1);
+	  NTOHSL(phd->tb[i][j].tb2);
+	}
+    }
+#endif
+  return (tot);
+}
+
+
+perf_hash_data *
+read_perf_hash_data (FILE * f)
+{
+  perf_hash_data *phd;
+  int i, tot, ok = 1;
+  if (!(phd = Xmalloc (sizeof (perf_hash_data))))
+    return (NULL);
+  tot = fread ((char *) &phd->MAX_L, sizeof (int), 1, f) * sizeof (int);
+  tot += fread ((char *) &phd->MAX_N, sizeof (int), 1, f) * sizeof (int);
+  tot += fread ((char *) &phd->MAX_M, sizeof (int), 1, f) * sizeof (int);
+  tot += fread ((char *) &phd->MAX_CH, sizeof (int), 1, f) * sizeof (int);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHSI(phd->MAX_L);
+  NTOHSI(phd->MAX_N);
+  NTOHSI(phd->MAX_M);
+  NTOHSI(phd->MAX_CH);
+
+  if (tot != 4 * sizeof (int))
+      return (NULL);
+  phd->translate = Xmalloc (sizeof (u_char) * 256);
+  phd->g = Xmalloc (sizeof (int) * (phd->MAX_N + 1));
+#ifndef STRUCT
+  phd->tb0 = Xmalloc (sizeof (int *) * phd->MAX_CH);
+  phd->tb1 = Xmalloc (sizeof (int *) * phd->MAX_CH);
+  phd->tb2 = Xmalloc (sizeof (int *) * phd->MAX_CH);
+  for (i = 0; i < phd->MAX_CH; i++)
+    {
+      if (phd->tb0)
+	if (!(phd->tb0[i] = Xmalloc (sizeof (long) * phd->MAX_L)))
+	    ok = 0;
+      if (phd->tb1)
+	if (!(phd->tb1[i] = Xmalloc (sizeof (long) * phd->MAX_L)))
+	    ok = 0;
+      if (phd->tb2)
+	if (!(phd->tb2[i] = Xmalloc (sizeof (long) * phd->MAX_L)))
+	    ok = 0;
+    }
+  if (!(phd->translate && phd->g && phd->tb0 && phd->tb1 && phd->tb2 && ok))
+    {
+      if (phd->translate)
+	Xfree (phd->translate);
+      if (phd->g)
+	Xfree (phd->g);
+      for (i = 0; i < MAX_CH; i++)
+	{
+	  if (phd->tb0 && phd->tb0[i])
+	    Xfree (phd->tb0[i]);
+	  if (phd->tb1 && phd->tb1[i])
+	    Xfree (phd->tb1[i]);
+	  if (phd->tb2 && phd->tb2[i])
+	    Xfree (phd->tb2[i]);
+	}
+      if (phd->tb0)
+	Xfree (phd->tb0);
+      if (phd->tb1)
+	Xfree (phd->tb1);
+      if (phd->tb2)
+	Xfree (phd->tb2);
+      Xfree (phd);
+      return (NULL);
+    }
+  tot += fread ((char *) phd->translate, sizeof (u_char), 256, f);
+  tot += fread ((char *) phd->g, sizeof (int), phd->MAX_N + 1, f) * sizeof (int);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = 0; i < phd->MAX_N + 1; i++)
+    NTOHSI(phd->g[i]);
+
+  for (i = 0; i < phd->MAX_CH; i++)
+    {
+      int j;
+
+      tot += fread ((char *) phd->tb0[i], sizeof (long), phd->MAX_L, f) *
+        sizeof (int);
+      tot += fread ((char *) phd->tb1[i], sizeof (long), phd->MAX_L, f) *
+        sizeof (int);
+      tot += fread ((char *) phd->tb2[i], sizeof (long), phd->MAX_L, f) *
+        sizeof (int);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (j = 0; j < phd->MAX_L; j++)
+	{
+	  NTOHSI(phd->tb0[i][j]);
+	  NTOHSI(phd->tb1[i][j]);
+	  NTOHSI(phd->tb2[i][j]);
+	}
+    }
+#else
+  phd->tb = Xmalloc (sizeof (struct tb_entry *) * phd->MAX_CH);
+  for (i = 0; i < phd->MAX_CH; i++)
+    if (phd->tb)
+      if (!(phd->tb[i] = Xmalloc (sizeof (struct tb_entry) * phd->MAX_L)))
+	  ok = 0;
+  if (!(phd->translate && phd->g && phd->tb && ok))
+    {
+      if (phd->translate)
+	Xfree (phd->translate);
+      if (phd->g)
+	Xfree (phd->g);
+      for (i = 0; i < MAX_CH; i++)
+	if (phd->tb && phd->tb[i])
+	  Xfree (phd->tb[i]);
+      if (phd->tb)
+	Xfree (phd->tb);
+      Xfree (phd);
+      return (NULL);
+    }
+  tot += fread ((char *) phd->translate, sizeof (u_char), 256, f);
+  tot += fread ((char *) phd->g, sizeof (int), phd->MAX_N + 1, f) * sizeof (int);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = 0; i < phd->MAX_N + 1; i++)
+    NTOHSI(phd->g[i]);
+
+  for (i = 0; i < phd->MAX_CH; i++)
+    {
+      int j;
+
+      tot += fread ((char *) phd->tb[i], sizeof (struct tb_entry), phd->MAX_L, f) *
+	sizeof (struct tb_entry);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (j = 0; j < phd->MAX_L; j++)
+	{
+	  NTOHSL(phd->tb[i][j].tb0);
+	  NTOHSL(phd->tb[i][j].tb1);
+	  NTOHSL(phd->tb[i][j].tb2);
+	}
+    }
+#endif
+  return (phd);
+}
+
+void 
+free_perf_hash (perf_hash_data * phd)
+{
+  int i;
+  if (phd->translate)
+    Xfree (phd->translate);
+  if (phd->g)
+    Xfree (phd->g);
+  for (i = 0; i < phd->MAX_CH; i++)
+    if (phd->tb && phd->tb[i])
+      Xfree (phd->tb[i]);
+  if (phd->tb)
+    Xfree (phd->tb);
+  Xfree (phd);
+}
+
+
+int 
+perf_hash (perf_hash_data * phd, u_char * s)
+{
+  int u, v, w, i, l;
+  l = *s++;
+  i = (l - 1) % phd->MAX_L;
+  u = v = w = 0;
+  while (l)
+    {
+#ifndef STRUCT
+      if ((u += phd->tb0[phd->translate[*s]][i]) >= phd->MAX_N)
+	u -= phd->MAX_N;
+      if ((v += phd->tb1[phd->translate[*s]][i]) >= phd->MAX_N)
+	v -= phd->MAX_N;
+      if ((w += phd->tb2[phd->translate[*s]][i]) >= phd->MAX_N)
+	w -= phd->MAX_N;
+#else
+      struct tb_entry *tbp = &phd->tb[phd->translate[*s]][i];
+      if ((u += tbp->tb0) >= phd->MAX_N)
+	u -= phd->MAX_N;
+      if ((v += tbp->tb1) >= phd->MAX_N)
+	v -= phd->MAX_N;
+      if ((w += tbp->tb2) >= phd->MAX_N)
+	w -= phd->MAX_N;
+#endif
+      if (++i >= phd->MAX_L)
+	i = 0;
+      l--;
+      s++;
+    }
+  if (u == v && ++v >= phd->MAX_N)
+    v = 0;
+  if (w == v)
+    {
+      if (++w >= phd->MAX_N)
+	w = 0;
+      if (w == u && ++w >= phd->MAX_N)
+	w = 0;
+    }
+  else if (w == u)
+    {
+      if (++w >= phd->MAX_N)
+	w = 0;
+      if (w == v && ++w >= phd->MAX_N)
+	w = 0;
+    }
+  return ((phd->g[u] ^ phd->g[v] ^ phd->g[w]) > phd->MAX_M) ? 0 :
+    (phd->g[u] ^ phd->g[v] ^ phd->g[w]);
+}
Index: /indexers/branches/3.03a/mg/lib/perf_hash.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/perf_hash.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/perf_hash.h	(revision 14757)
@@ -0,0 +1,55 @@
+/**************************************************************************
+ *
+ * perf_hash.h -- Perfect hashing functions
+ * Copyright (C) 1994  Bohdan S. Majewski and Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_PERF_HASH
+#define H_PERF_HASH
+
+
+
+
+struct tb_entry
+  {
+    long tb0, tb1, tb2;
+  };
+
+typedef struct
+  {
+    int MAX_L;
+    int MAX_N;
+    int MAX_M;
+    int MAX_CH;
+    u_char *translate;
+    int *g;
+    struct tb_entry **tb;
+  }
+perf_hash_data;
+
+perf_hash_data *gen_hash_func (int num, u_char ** keys, int r);
+
+int perf_hash (perf_hash_data * phd, u_char * s);
+
+int write_perf_hash_data (FILE * f, perf_hash_data * phd);
+
+void free_perf_hash (perf_hash_data * phd);
+
+perf_hash_data *read_perf_hash_data (FILE * f);
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/random.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/random.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/random.c	(revision 14757)
@@ -0,0 +1,211 @@
+/**************************************************************************
+ *
+ * random.c -- pseudo random number generator
+ * Copyright (C) 1994  Chris Wallace (csw@bruce.cs.monash.edu.au)
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+/*
+ *	A random number generator called as a function by
+ *	random (iseed)	or	irandm (iseed)
+ *	The parameter should be a pointer to a 2-element long vector.
+ *	The first function returns a double uniform in 0 .. 1.
+ *	The second returns a long integer uniform in 0 .. 2**31-1
+ *	Both update iseed[] in exactly the same way.
+ *	iseed[] must be a 2-element integer vector.
+ *	The initial value of the second element may be anything.
+ *
+ *	The period of the random sequence is 2**32 * (2**32-1)
+ *	The table mt[0:127] is defined by mt[i] = 69069 ** (128-i)
+ */
+
+#define MASK ((long) 593970775)
+/*	or in hex, 23674657	*/
+
+#define SCALE ((double) 1.0 / (1024.0 * 1024.0 * 1024.0 * 2.0))
+/*	i.e. 2 to power -31	*/
+
+static long mt [128] =   {
+      902906369,
+     2030498053,
+     -473499623,
+     1640834941,
+      723406961,
+     1993558325,
+     -257162999,
+    -1627724755,
+      913952737,
+      278845029,
+     1327502073,
+    -1261253155,
+      981676113,
+    -1785280363,
+     1700077033,
+      366908557,
+    -1514479167,
+     -682799163,
+      141955545,
+     -830150595,
+      317871153,
+     1542036469,
+     -946413879,
+    -1950779155,
+      985397153,
+      626515237,
+      530871481,
+      783087261,
+    -1512358895,
+     1031357269,
+    -2007710807,
+    -1652747955,
+    -1867214463,
+      928251525,
+     1243003801,
+    -2132510467,
+     1874683889,
+     -717013323,
+      218254473,
+    -1628774995,
+    -2064896159,
+       69678053,
+      281568889,
+    -2104168611,
+     -165128239,
+     1536495125,
+      -39650967,
+      546594317,
+     -725987007,
+     1392966981,
+     1044706649,
+      687331773,
+    -2051306575,
+     1544302965,
+     -758494647,
+    -1243934099,
+      -75073759,
+      293132965,
+    -1935153095,
+      118929437,
+      807830417,
+    -1416222507,
+    -1550074071,
+      -84903219,
+     1355292929,
+     -380482555,
+    -1818444007,
+     -204797315,
+      170442609,
+    -1636797387,
+      868931593,
+     -623503571,
+     1711722209,
+      381210981,
+     -161547783,
+     -272740131,
+    -1450066095,
+     2116588437,
+     1100682473,
+      358442893,
+    -1529216831,
+     2116152005,
+     -776333095,
+     1265240893,
+     -482278607,
+     1067190005,
+      333444553,
+       86502381,
+      753481377,
+       39000101,
+     1779014585,
+      219658653,
+     -920253679,
+     2029538901,
+     1207761577,
+    -1515772851,
+     -236195711,
+      442620293,
+      423166617,
+    -1763648515,
+     -398436623,
+    -1749358155,
+     -538598519,
+     -652439379,
+      430550625,
+    -1481396507,
+     2093206905,
+    -1934691747,
+     -962631983,
+     1454463253,
+    -1877118871,
+     -291917555,
+    -1711673279,
+      201201733,
+     -474645415,
+      -96764739,
+    -1587365199,
+     1945705589,
+     1303896393,
+     1744831853,
+      381957665,
+     2135332261,
+      -55996615,
+    -1190135011,
+     1790562961,
+    -1493191723,
+      475559465,
+          69069
+		};
+
+double 
+random (long is [2])
+{
+	long it, leh, nit;
+
+	it = is [0];
+	leh = is [1];
+	if (it <= 0)	
+		it = (it + it) ^ MASK;
+	else
+		it = it + it;
+	nit = it - 1;
+/*	to ensure all-ones pattern omitted    */
+	leh = leh * mt[nit & 127] + nit;
+	is [0] = it;    is [1] = leh;
+	if (leh < 0) leh = ~leh;
+	return (SCALE * ((long) (leh | 1)));
+}
+
+
+
+long 
+irandm (long is [2])
+{
+	long it, leh, nit;
+
+	it = is [0];
+	leh = is [1];
+	if (it <= 0)	
+		it = (it + it) ^ MASK;
+	else
+		it = it + it;
+	nit = it - 1;
+/*	to ensure all-ones pattern omitted    */
+	leh = leh * mt[nit & 127] + nit;
+	is [0] = it;    is [1] = leh;
+	if (leh < 0) leh = ~leh;
+	return (leh);
+}
Index: /indexers/branches/3.03a/mg/lib/random.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/random.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/random.h	(revision 14757)
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * random.h -- pseudo random number generator
+ * Copyright (C) 1994  Chris Wallace (csw@bruce.cs.monash.edu.au)
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef RANDOM_H
+#define RANDOM_H
+
+/*
+ *	A random number generator called as a function by
+ *	random (iseed)	or	irandm (iseed)
+ *	The parameter should be a pointer to a 2-element long vector.
+ *	The first function returns a double uniform in 0 .. 1.
+ *	The second returns a long integer uniform in 0 .. 2**31-1
+ *	Both update iseed[] in exactly the same way.
+ *	iseed[] must be a 2-element integer vector.
+ *	The initial value of the second element may be anything.
+ *
+ *	The period of the random sequence is 2**32 * (2**32-1)
+ *	The table mt[0:127] is defined by mt[i] = 69069 ** (128-i)
+ */
+
+double random (long is [2]);
+long irandm (long is [2]);
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/regex.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/regex.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/regex.c	(revision 14757)
@@ -0,0 +1,5426 @@
+/* Extended regular expression matching and search library,
+   version 0.12.
+   (Implements POSIX draft P10003.2/D11.2, except for
+   internationalization features.)
+
+   Copyright (C) 1993, 1994, 1995 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 program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* AIX requires this to be the first thing in the file. */
+#if defined (_AIX) && !defined (REGEX_MALLOC)
+  #pragma alloca
+#endif
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+# ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+#  include <win32cfg.h>
+# else
+#  include <sysfuncs.h>
+# endif
+#endif
+
+/* We need this for `regex.h', and perhaps for the Emacs include files.  */
+#include <sys/types.h>
+
+/* This is for other GNU distributions with internationalized messages.  */
+#if HAVE_LIBINTL_H || defined (_LIBC)
+# include <libintl.h>
+#else
+# define gettext(msgid) (msgid)
+#endif
+
+/* The `emacs' switch turns on certain matching commands
+   that make sense only in Emacs. */
+#ifdef emacs
+
+#include "lisp.h"
+#include "buffer.h"
+#include "syntax.h"
+
+#else  /* not emacs */
+
+/* If we are not linking with Emacs proper,
+   we can't use the relocating allocator
+   even if sysfuncs.h says that we can.  */
+#undef REL_ALLOC
+
+#if defined (STDC_HEADERS) || defined (_LIBC)
+#include <stdlib.h>
+#else
+char *malloc ();
+char *realloc ();
+#endif
+
+/* We used to test for `BSTRING' here, but only GCC and Emacs define
+   `BSTRING', as far as I know, and neither of them use this code.  */
+#ifndef INHIBIT_STRING_HEADER
+#if HAVE_STRING_H || STDC_HEADERS || defined (_LIBC)
+#include <string.h>
+#ifndef bcmp
+#define bcmp(s1, s2, n)	memcmp ((s1), (s2), (n))
+#endif
+#ifndef bcopy
+#define bcopy(s, d, n)	memcpy ((d), (s), (n))
+#endif
+#ifndef bzero
+#define bzero(s, n)	memset ((s), 0, (n))
+#endif
+#else
+#include <strings.h>
+#endif
+#endif
+
+/* Define the syntax stuff for \<, \>, etc.  */
+
+/* This must be nonzero for the wordchar and notwordchar pattern
+   commands in re_match_2.  */
+#ifndef Sword 
+#define Sword 1
+#endif
+
+#ifdef SWITCH_ENUM_BUG
+#define SWITCH_ENUM_CAST(x) ((int)(x))
+#else
+#define SWITCH_ENUM_CAST(x) (x)
+#endif
+
+#ifdef SYNTAX_TABLE
+
+extern char *re_syntax_table;
+
+#else /* not SYNTAX_TABLE */
+
+/* How many characters in the character set.  */
+#define CHAR_SET_SIZE 256
+
+static char re_syntax_table[CHAR_SET_SIZE];
+
+static void
+init_syntax_once ()
+{
+   register int c;
+   static int done = 0;
+
+   if (done)
+     return;
+
+   bzero (re_syntax_table, sizeof re_syntax_table);
+
+   for (c = 'a'; c <= 'z'; c++)
+     re_syntax_table[c] = Sword;
+
+   for (c = 'A'; c <= 'Z'; c++)
+     re_syntax_table[c] = Sword;
+
+   for (c = '0'; c <= '9'; c++)
+     re_syntax_table[c] = Sword;
+
+   re_syntax_table['_'] = Sword;
+
+   done = 1;
+}
+
+#endif /* not SYNTAX_TABLE */
+
+#define SYNTAX(c) re_syntax_table[c]
+
+#endif /* not emacs */
+
+
+/* Get the interface, including the syntax bits.  */
+#include "regex.h"
+
+/* isalpha etc. are used for the character classes.  */
+#include <ctype.h>
+
+/* Jim Meyering writes:
+
+   "... Some ctype macros are valid only for character codes that
+   isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
+   using /bin/cc or gcc but without giving an ansi option).  So, all
+   ctype uses should be through macros like ISPRINT...  If
+   STDC_HEADERS is defined, then autoconf has verified that the ctype
+   macros don't need to be guarded with references to isascii. ...
+   Defining isascii to 1 should let any compiler worth its salt
+   eliminate the && through constant folding."  */
+
+#ifndef ISASCII
+#  if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
+#    define ISASCII(c) 1
+#  else
+#    define ISASCII(c) isascii(c)
+#  endif
+#endif
+
+#ifdef isblank
+#define ISBLANK(c) (ISASCII (c) && isblank (c))
+#else
+#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#endif
+#ifdef isgraph
+#define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+#else
+#define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+#endif
+
+#define ISPRINT(c) (ISASCII (c) && isprint (c))
+#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+#define ISALNUM(c) (ISASCII (c) && isalnum (c))
+#define ISALPHA(c) (ISASCII (c) && isalpha (c))
+#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+#define ISLOWER(c) (ISASCII (c) && islower (c))
+#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+#define ISSPACE(c) (ISASCII (c) && isspace (c))
+#define ISUPPER(c) (ISASCII (c) && isupper (c))
+#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* We remove any previous definition of `SIGN_EXTEND_CHAR',
+   since ours (we hope) works properly with all combinations of
+   machines, compilers, `char' and `unsigned char' argument types.
+   (Per Bothner suggested the basic approach.)  */
+#undef SIGN_EXTEND_CHAR
+#if __STDC__
+#define SIGN_EXTEND_CHAR(c) ((signed char) (c))
+#else  /* not __STDC__ */
+/* As in Harbison and Steele.  */
+#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
+#endif
+
+
+/* Should we use malloc or alloca?  If REGEX_MALLOC is not defined, we
+   use `alloca' instead of `malloc'.  This is because using malloc in
+   re_search* or re_match* could cause memory leaks when C-g is used in
+   Emacs; also, malloc is slower and causes storage fragmentation.  On
+   the other hand, malloc is more portable, and easier to debug.  
+   
+   Because we sometimes use alloca, some routines have to be macros,
+   not functions -- `alloca'-allocated space disappears at the end of the
+   function it is called in.  */
+
+#ifdef REGEX_MALLOC
+
+#define REGEX_ALLOCATE malloc
+#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
+#define REGEX_FREE free
+
+#else /* not REGEX_MALLOC  */
+
+/* Emacs already defines alloca, sometimes.  */
+#ifndef alloca
+
+/* Make alloca work the best possible way.  */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#else /* not __GNUC__ or HAVE_ALLOCA_H */
+#ifndef _AIX /* Already did AIX, up at the top.  */
+char *alloca ();
+#endif /* not _AIX */
+#endif /* not HAVE_ALLOCA_H */ 
+#endif /* not __GNUC__ */
+
+#endif /* not alloca */
+
+#define REGEX_ALLOCATE alloca
+
+/* Assumes a `char *destination' variable.  */
+#define REGEX_REALLOCATE(source, osize, nsize)				\
+  (destination = (char *) alloca (nsize),				\
+   bcopy (source, destination, osize),					\
+   destination)
+
+/* No need to do anything to free, after alloca.  */
+#define REGEX_FREE(arg) ((void)0) /* Do nothing!  But inhibit gcc warning.  */
+
+#endif /* not REGEX_MALLOC */
+
+/* Define how to allocate the failure stack.  */
+
+#ifdef REL_ALLOC
+#define REGEX_ALLOCATE_STACK(size)				\
+  r_alloc (&failure_stack_ptr, (size))
+#define REGEX_REALLOCATE_STACK(source, osize, nsize)		\
+  r_re_alloc (&failure_stack_ptr, (nsize))
+#define REGEX_FREE_STACK(ptr)					\
+  r_alloc_free (&failure_stack_ptr)
+
+#else /* not REL_ALLOC */
+
+#ifdef REGEX_MALLOC
+
+#define REGEX_ALLOCATE_STACK malloc
+#define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
+#define REGEX_FREE_STACK free
+
+#else /* not REGEX_MALLOC */
+
+#define REGEX_ALLOCATE_STACK alloca
+
+#define REGEX_REALLOCATE_STACK(source, osize, nsize)			\
+   REGEX_REALLOCATE (source, osize, nsize)
+/* No need to explicitly free anything.  */
+#define REGEX_FREE_STACK(arg)
+
+#endif /* not REGEX_MALLOC */
+#endif /* not REL_ALLOC */
+
+
+/* True if `size1' is non-NULL and PTR is pointing anywhere inside
+   `string1' or just past its end.  This works if PTR is NULL, which is
+   a good thing.  */
+#define FIRST_STRING_P(ptr) 					\
+  (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
+
+/* (Re)Allocate N items of type T using malloc, or fail.  */
+#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
+#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
+#define RETALLOC_IF(addr, n, t) \
+  if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t)
+#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
+
+#define BYTEWIDTH 8 /* In bits.  */
+
+#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+#undef MAX
+#undef MIN
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+typedef char boolean;
+#define false 0
+#define true 1
+
+static int re_match_2_internal ();
+
+
+/* These are the command codes that appear in compiled regular
+   expressions.  Some opcodes are followed by argument bytes.  A
+   command code can specify any interpretation whatsoever for its
+   arguments.  Zero bytes may appear in the compiled regular expression.  */
+
+typedef enum
+{
+  no_op = 0,
+
+  /* Succeed right away--no more backtracking.  */
+  succeed,
+
+        /* Followed by one byte giving n, then by n literal bytes.  */
+  exactn,
+
+        /* Matches any (more or less) character.  */
+  anychar,
+
+        /* Matches any one char belonging to specified set.  First
+           following byte is number of bitmap bytes.  Then come bytes
+           for a bitmap saying which chars are in.  Bits in each byte
+           are ordered low-bit-first.  A character is in the set if its
+           bit is 1.  A character too large to have a bit in the map is
+           automatically not in the set.  */
+  charset,
+
+        /* Same parameters as charset, but match any character that is
+           not one of those specified.  */
+  charset_not,
+
+        /* Start remembering the text that is matched, for storing in a
+           register.  Followed by one byte with the register number, in
+           the range 0 to one less than the pattern buffer's re_nsub
+           field.  Then followed by one byte with the number of groups
+           inner to this one.  (This last has to be part of the
+           start_memory only because we need it in the on_failure_jump
+           of re_match_2.)  */
+  start_memory,
+
+        /* Stop remembering the text that is matched and store it in a
+           memory register.  Followed by one byte with the register
+           number, in the range 0 to one less than `re_nsub' in the
+           pattern buffer, and one byte with the number of inner groups,
+           just like `start_memory'.  (We need the number of inner
+           groups here because we don't have any easy way of finding the
+           corresponding start_memory when we're at a stop_memory.)  */
+  stop_memory,
+
+        /* Match a duplicate of something remembered. Followed by one
+           byte containing the register number.  */
+  duplicate,
+
+        /* Fail unless at beginning of line.  */
+  begline,
+
+        /* Fail unless at end of line.  */
+  endline,
+
+        /* Succeeds if at beginning of buffer (if emacs) or at beginning
+           of string to be matched (if not).  */
+  begbuf,
+
+        /* Analogously, for end of buffer/string.  */
+  endbuf,
+ 
+        /* Followed by two byte relative address to which to jump.  */
+  jump, 
+
+	/* Same as jump, but marks the end of an alternative.  */
+  jump_past_alt,
+
+        /* Followed by two-byte relative address of place to resume at
+           in case of failure.  */
+  on_failure_jump,
+	
+        /* Like on_failure_jump, but pushes a placeholder instead of the
+           current string position when executed.  */
+  on_failure_keep_string_jump,
+  
+        /* Throw away latest failure point and then jump to following
+           two-byte relative address.  */
+  pop_failure_jump,
+
+        /* Change to pop_failure_jump if know won't have to backtrack to
+           match; otherwise change to jump.  This is used to jump
+           back to the beginning of a repeat.  If what follows this jump
+           clearly won't match what the repeat does, such that we can be
+           sure that there is no use backtracking out of repetitions
+           already matched, then we change it to a pop_failure_jump.
+           Followed by two-byte address.  */
+  maybe_pop_jump,
+
+        /* Jump to following two-byte address, and push a dummy failure
+           point. This failure point will be thrown away if an attempt
+           is made to use it for a failure.  A `+' construct makes this
+           before the first repeat.  Also used as an intermediary kind
+           of jump when compiling an alternative.  */
+  dummy_failure_jump,
+
+	/* Push a dummy failure point and continue.  Used at the end of
+	   alternatives.  */
+  push_dummy_failure,
+
+        /* Followed by two-byte relative address and two-byte number n.
+           After matching N times, jump to the address upon failure.  */
+  succeed_n,
+
+        /* Followed by two-byte relative address, and two-byte number n.
+           Jump to the address N times, then fail.  */
+  jump_n,
+
+        /* Set the following two-byte relative address to the
+           subsequent two-byte number.  The address *includes* the two
+           bytes of number.  */
+  set_number_at,
+
+  wordchar,	/* Matches any word-constituent character.  */
+  notwordchar,	/* Matches any char that is not a word-constituent.  */
+
+  wordbeg,	/* Succeeds if at word beginning.  */
+  wordend,	/* Succeeds if at word end.  */
+
+  wordbound,	/* Succeeds if at a word boundary.  */
+  notwordbound	/* Succeeds if not at a word boundary.  */
+
+#ifdef emacs
+  ,before_dot,	/* Succeeds if before point.  */
+  at_dot,	/* Succeeds if at point.  */
+  after_dot,	/* Succeeds if after point.  */
+
+	/* Matches any character whose syntax is specified.  Followed by
+           a byte which contains a syntax code, e.g., Sword.  */
+  syntaxspec,
+
+	/* Matches any character whose syntax is not that specified.  */
+  notsyntaxspec
+#endif /* emacs */
+} re_opcode_t;
+
+
+/* Common operations on the compiled pattern.  */
+
+/* Store NUMBER in two contiguous bytes starting at DESTINATION.  */
+
+#define STORE_NUMBER(destination, number)				\
+  do {									\
+    (destination)[0] = (number) & 0377;					\
+    (destination)[1] = (number) >> 8;					\
+  } while (0)
+
+/* Same as STORE_NUMBER, except increment DESTINATION to
+   the byte after where the number is stored.  Therefore, DESTINATION
+   must be an lvalue.  */
+
+#define STORE_NUMBER_AND_INCR(destination, number)			\
+  do {									\
+    STORE_NUMBER (destination, number);					\
+    (destination) += 2;							\
+  } while (0)
+
+/* Put into DESTINATION a number stored in two contiguous bytes starting
+   at SOURCE.  */
+
+#define EXTRACT_NUMBER(destination, source)				\
+  do {									\
+    (destination) = *(source) & 0377;					\
+    (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8;		\
+  } while (0)
+
+#ifdef DEBUG
+static void
+extract_number (dest, source)
+    int *dest;
+    unsigned char *source;
+{
+  int temp = SIGN_EXTEND_CHAR (*(source + 1)); 
+  *dest = *source & 0377;
+  *dest += temp << 8;
+}
+
+#ifndef EXTRACT_MACROS /* To debug the macros.  */
+#undef EXTRACT_NUMBER
+#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
+#endif /* not EXTRACT_MACROS */
+
+#endif /* DEBUG */
+
+/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
+   SOURCE must be an lvalue.  */
+
+#define EXTRACT_NUMBER_AND_INCR(destination, source)			\
+  do {									\
+    EXTRACT_NUMBER (destination, source);				\
+    (source) += 2; 							\
+  } while (0)
+
+#ifdef DEBUG
+static void
+extract_number_and_incr (destination, source)
+    int *destination;
+    unsigned char **source;
+{ 
+  extract_number (destination, *source);
+  *source += 2;
+}
+
+#ifndef EXTRACT_MACROS
+#undef EXTRACT_NUMBER_AND_INCR
+#define EXTRACT_NUMBER_AND_INCR(dest, src) \
+  extract_number_and_incr (&dest, &src)
+#endif /* not EXTRACT_MACROS */
+
+#endif /* DEBUG */
+
+
+/* If DEBUG is defined, Regex prints many voluminous messages about what
+   it is doing (if the variable `debug' is nonzero).  If linked with the
+   main program in `iregex.c', you can enter patterns and strings
+   interactively.  And if linked with the main program in `main.c' and
+   the other test files, you can run the already-written tests.  */
+
+#ifdef DEBUG
+
+/* We use standard I/O for debugging.  */
+#include <stdio.h>
+
+/* It is useful to test things that ``must'' be true when debugging.  */
+#include <assert.h>
+
+static int debug = 0;
+
+#define DEBUG_STATEMENT(e) e
+#define DEBUG_PRINT1(x) if (debug) printf (x)
+#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
+#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
+#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
+#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) 				\
+  if (debug) print_partial_compiled_pattern (s, e)
+#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)			\
+  if (debug) print_double_string (w, s1, sz1, s2, sz2)
+
+
+/* Print the fastmap in human-readable form.  */
+
+void
+print_fastmap (fastmap)
+    char *fastmap;
+{
+  unsigned was_a_range = 0;
+  unsigned i = 0;  
+  
+  while (i < (1 << BYTEWIDTH))
+    {
+      if (fastmap[i++])
+	{
+	  was_a_range = 0;
+          putchar (i - 1);
+          while (i < (1 << BYTEWIDTH)  &&  fastmap[i])
+            {
+              was_a_range = 1;
+              i++;
+            }
+	  if (was_a_range)
+            {
+              printf ("-");
+              putchar (i - 1);
+            }
+        }
+    }
+  putchar ('\n'); 
+}
+
+
+/* Print a compiled pattern string in human-readable form, starting at
+   the START pointer into it and ending just before the pointer END.  */
+
+void
+print_partial_compiled_pattern (start, end)
+    unsigned char *start;
+    unsigned char *end;
+{
+  int mcnt, mcnt2;
+  unsigned char *p = start;
+  unsigned char *pend = end;
+
+  if (start == NULL)
+    {
+      printf ("(null)\n");
+      return;
+    }
+    
+  /* Loop over pattern commands.  */
+  while (p < pend)
+    {
+      printf ("%d:\t", p - start);
+
+      switch ((re_opcode_t) *p++)
+	{
+        case no_op:
+          printf ("/no_op");
+          break;
+
+	case exactn:
+	  mcnt = *p++;
+          printf ("/exactn/%d", mcnt);
+          do
+	    {
+              putchar ('/');
+	      putchar (*p++);
+            }
+          while (--mcnt);
+          break;
+
+	case start_memory:
+          mcnt = *p++;
+          printf ("/start_memory/%d/%d", mcnt, *p++);
+          break;
+
+	case stop_memory:
+          mcnt = *p++;
+	  printf ("/stop_memory/%d/%d", mcnt, *p++);
+          break;
+
+	case duplicate:
+	  printf ("/duplicate/%d", *p++);
+	  break;
+
+	case anychar:
+	  printf ("/anychar");
+	  break;
+
+	case charset:
+        case charset_not:
+          {
+            register int c, last = -100;
+	    register int in_range = 0;
+
+	    printf ("/charset [%s",
+	            (re_opcode_t) *(p - 1) == charset_not ? "^" : "");
+            
+            assert (p + *p < pend);
+
+            for (c = 0; c < 256; c++)
+	      if (c / 8 < *p
+		  && (p[1 + (c/8)] & (1 << (c % 8))))
+		{
+		  /* Are we starting a range?  */
+		  if (last + 1 == c && ! in_range)
+		    {
+		      putchar ('-');
+		      in_range = 1;
+		    }
+		  /* Have we broken a range?  */
+		  else if (last + 1 != c && in_range)
+              {
+		      putchar (last);
+		      in_range = 0;
+		    }
+                
+		  if (! in_range)
+		    putchar (c);
+
+		  last = c;
+              }
+
+	    if (in_range)
+	      putchar (last);
+
+	    putchar (']');
+
+	    p += 1 + *p;
+	  }
+	  break;
+
+	case begline:
+	  printf ("/begline");
+          break;
+
+	case endline:
+          printf ("/endline");
+          break;
+
+	case on_failure_jump:
+          extract_number_and_incr (&mcnt, &p);
+  	  printf ("/on_failure_jump to %d", p + mcnt - start);
+          break;
+
+	case on_failure_keep_string_jump:
+          extract_number_and_incr (&mcnt, &p);
+  	  printf ("/on_failure_keep_string_jump to %d", p + mcnt - start);
+          break;
+
+	case dummy_failure_jump:
+          extract_number_and_incr (&mcnt, &p);
+  	  printf ("/dummy_failure_jump to %d", p + mcnt - start);
+          break;
+
+	case push_dummy_failure:
+          printf ("/push_dummy_failure");
+          break;
+          
+        case maybe_pop_jump:
+          extract_number_and_incr (&mcnt, &p);
+  	  printf ("/maybe_pop_jump to %d", p + mcnt - start);
+	  break;
+
+        case pop_failure_jump:
+	  extract_number_and_incr (&mcnt, &p);
+  	  printf ("/pop_failure_jump to %d", p + mcnt - start);
+	  break;          
+          
+        case jump_past_alt:
+	  extract_number_and_incr (&mcnt, &p);
+  	  printf ("/jump_past_alt to %d", p + mcnt - start);
+	  break;          
+          
+        case jump:
+	  extract_number_and_incr (&mcnt, &p);
+  	  printf ("/jump to %d", p + mcnt - start);
+	  break;
+
+        case succeed_n: 
+          extract_number_and_incr (&mcnt, &p);
+          extract_number_and_incr (&mcnt2, &p);
+	  printf ("/succeed_n to %d, %d times", p + mcnt - start, mcnt2);
+          break;
+        
+        case jump_n: 
+          extract_number_and_incr (&mcnt, &p);
+          extract_number_and_incr (&mcnt2, &p);
+	  printf ("/jump_n to %d, %d times", p + mcnt - start, mcnt2);
+          break;
+        
+        case set_number_at: 
+          extract_number_and_incr (&mcnt, &p);
+          extract_number_and_incr (&mcnt2, &p);
+	  printf ("/set_number_at location %d to %d", p + mcnt - start, mcnt2);
+          break;
+        
+        case wordbound:
+	  printf ("/wordbound");
+	  break;
+
+	case notwordbound:
+	  printf ("/notwordbound");
+          break;
+
+	case wordbeg:
+	  printf ("/wordbeg");
+	  break;
+          
+	case wordend:
+	  printf ("/wordend");
+          
+#ifdef emacs
+	case before_dot:
+	  printf ("/before_dot");
+          break;
+
+	case at_dot:
+	  printf ("/at_dot");
+          break;
+
+	case after_dot:
+	  printf ("/after_dot");
+          break;
+
+	case syntaxspec:
+          printf ("/syntaxspec");
+	  mcnt = *p++;
+	  printf ("/%d", mcnt);
+          break;
+	  
+	case notsyntaxspec:
+          printf ("/notsyntaxspec");
+	  mcnt = *p++;
+	  printf ("/%d", mcnt);
+	  break;
+#endif /* emacs */
+
+	case wordchar:
+	  printf ("/wordchar");
+          break;
+	  
+	case notwordchar:
+	  printf ("/notwordchar");
+          break;
+
+	case begbuf:
+	  printf ("/begbuf");
+          break;
+
+	case endbuf:
+	  printf ("/endbuf");
+          break;
+
+        default:
+          printf ("?%d", *(p-1));
+	}
+
+      putchar ('\n');
+    }
+
+  printf ("%d:\tend of pattern.\n", p - start);
+}
+
+
+void
+print_compiled_pattern (bufp)
+    struct re_pattern_buffer *bufp;
+{
+  unsigned char *buffer = bufp->buffer;
+
+  print_partial_compiled_pattern (buffer, buffer + bufp->used);
+  printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated);
+
+  if (bufp->fastmap_accurate && bufp->fastmap)
+    {
+      printf ("fastmap: ");
+      print_fastmap (bufp->fastmap);
+    }
+
+  printf ("re_nsub: %d\t", bufp->re_nsub);
+  printf ("regs_alloc: %d\t", bufp->regs_allocated);
+  printf ("can_be_null: %d\t", bufp->can_be_null);
+  printf ("newline_anchor: %d\n", bufp->newline_anchor);
+  printf ("no_sub: %d\t", bufp->no_sub);
+  printf ("not_bol: %d\t", bufp->not_bol);
+  printf ("not_eol: %d\t", bufp->not_eol);
+  printf ("syntax: %d\n", bufp->syntax);
+  /* Perhaps we should print the translate table?  */
+}
+
+
+void
+print_double_string (where, string1, size1, string2, size2)
+    const char *where;
+    const char *string1;
+    const char *string2;
+    int size1;
+    int size2;
+{
+  unsigned this_char;
+  
+  if (where == NULL)
+    printf ("(null)");
+  else
+    {
+      if (FIRST_STRING_P (where))
+        {
+          for (this_char = where - string1; this_char < size1; this_char++)
+            putchar (string1[this_char]);
+
+          where = string2;    
+        }
+
+      for (this_char = where - string2; this_char < size2; this_char++)
+        putchar (string2[this_char]);
+    }
+}
+
+#else /* not DEBUG */
+
+#undef assert
+#define assert(e)
+
+#define DEBUG_STATEMENT(e)
+#define DEBUG_PRINT1(x)
+#define DEBUG_PRINT2(x1, x2)
+#define DEBUG_PRINT3(x1, x2, x3)
+#define DEBUG_PRINT4(x1, x2, x3, x4)
+#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
+#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
+
+#endif /* not DEBUG */
+
+
+/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
+   also be assigned to arbitrarily: each pattern buffer stores its own
+   syntax, so it can be changed between regex compilations.  */
+/* This has no initializer because initialized variables in Emacs
+   become read-only after dumping.  */
+reg_syntax_t re_syntax_options;
+
+
+/* Specify the precise syntax of regexps for compilation.  This provides
+   for compatibility for various utilities which historically have
+   different, incompatible syntaxes.
+
+   The argument SYNTAX is a bit mask comprised of the various bits
+   defined in regex.h.  We return the old syntax.  */
+
+reg_syntax_t
+re_set_syntax (syntax)
+    reg_syntax_t syntax;
+{
+  reg_syntax_t ret = re_syntax_options;
+  
+  re_syntax_options = syntax;
+  return ret;
+}
+
+
+/* This table gives an error message for each of the error codes listed
+   in regex.h.  Obviously the order here has to be same as there.
+   POSIX doesn't require that we do anything for REG_NOERROR,
+   but why not be nice?  */
+
+static const char *re_error_msgid[] =
+  { "Success",					/* REG_NOERROR */
+    "No match",					/* REG_NOMATCH */
+    "Invalid regular expression",		/* REG_BADPAT */
+    "Invalid collation character",		/* REG_ECOLLATE */
+    "Invalid character class name",		/* REG_ECTYPE */
+    "Trailing backslash",			/* REG_EESCAPE */
+    "Invalid back reference",			/* REG_ESUBREG */
+    "Unmatched [ or [^",			/* REG_EBRACK */
+    "Unmatched ( or \\(",			/* REG_EPAREN */
+    "Unmatched \\{",				/* REG_EBRACE */
+    "Invalid content of \\{\\}",		/* REG_BADBR */
+    "Invalid range end",			/* REG_ERANGE */
+    "Memory exhausted",				/* REG_ESPACE */
+    "Invalid preceding regular expression",	/* REG_BADRPT */
+    "Premature end of regular expression",	/* REG_EEND */
+    "Regular expression too big",		/* REG_ESIZE */
+    "Unmatched ) or \\)",			/* REG_ERPAREN */
+  };
+
+
+/* Avoiding alloca during matching, to placate r_alloc.  */
+
+/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the
+   searching and matching functions should not call alloca.  On some
+   systems, alloca is implemented in terms of malloc, and if we're
+   using the relocating allocator routines, then malloc could cause a
+   relocation, which might (if the strings being searched are in the
+   ralloc heap) shift the data out from underneath the regexp
+   routines.
+
+   Here's another reason to avoid allocation: Emacs 
+   processes input from X in a signal handler; processing X input may
+   call malloc; if input arrives while a matching routine is calling
+   malloc, then we're scrod.  But Emacs can't just block input while
+   calling matching routines; then we don't notice interrupts when
+   they come in.  So, Emacs blocks input around all regexp calls
+   except the matching calls, which it leaves unprotected, in the
+   faith that they will not malloc.  */
+
+/* Normally, this is fine.  */
+#define MATCH_MAY_ALLOCATE
+
+/* When using GNU C, we are not REALLY using the C alloca, no matter
+   what sysfuncs.h may say.  So don't take precautions for it.  */
+#ifdef __GNUC__
+#undef C_ALLOCA
+#endif
+
+/* The match routines may not allocate if (1) they would do it with malloc
+   and (2) it's not safe for them to use malloc.
+   Note that if REL_ALLOC is defined, matching would not use malloc for the
+   failure stack, but we would still use it for the register vectors;
+   so REL_ALLOC should not affect this.  */
+#if (defined (C_ALLOCA) || defined (REGEX_MALLOC)) && defined (emacs)
+#undef MATCH_MAY_ALLOCATE
+#endif
+
+
+
+/* Failure stack declarations and macros; both re_compile_fastmap and
+   re_match_2 use a failure stack.  These have to be macros because of
+   REGEX_ALLOCATE_STACK.  */
+   
+
+/* Number of failure points for which to initially allocate space
+   when matching.  If this number is exceeded, we allocate more
+   space, so it is not a hard limit.  */
+#ifndef INIT_FAILURE_ALLOC
+#define INIT_FAILURE_ALLOC 5
+#endif
+
+/* Roughly the maximum number of failure points on the stack.  Would be
+   exactly that if always used MAX_FAILURE_SPACE each time we failed.
+   This is a variable only so users of regex can assign to it; we never
+   change it ourselves.  */
+#if defined (MATCH_MAY_ALLOCATE)
+int re_max_failures = 200000;
+#else
+int re_max_failures = 2000;
+#endif
+
+union fail_stack_elt
+{
+  unsigned char *pointer;
+  int integer;
+};
+
+typedef union fail_stack_elt fail_stack_elt_t;
+
+typedef struct
+{
+  fail_stack_elt_t *stack;
+  unsigned size;
+  unsigned avail;			/* Offset of next open position.  */
+} fail_stack_type;
+
+#define FAIL_STACK_EMPTY()     (fail_stack.avail == 0)
+#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
+#define FAIL_STACK_FULL()      (fail_stack.avail == fail_stack.size)
+
+
+/* Define macros to initialize and free the failure stack.
+   Do `return -2' if the alloc fails.  */
+
+#ifdef MATCH_MAY_ALLOCATE
+#define INIT_FAIL_STACK()						\
+  do {									\
+    fail_stack.stack = (fail_stack_elt_t *)				\
+      REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t));	\
+									\
+    if (fail_stack.stack == NULL)					\
+      return -2;							\
+									\
+    fail_stack.size = INIT_FAILURE_ALLOC;				\
+    fail_stack.avail = 0;						\
+  } while (0)
+
+#define RESET_FAIL_STACK()  REGEX_FREE_STACK (fail_stack.stack)
+#else
+#define INIT_FAIL_STACK()						\
+  do {									\
+    fail_stack.avail = 0;						\
+  } while (0)
+
+#define RESET_FAIL_STACK()
+#endif
+
+
+/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
+
+   Return 1 if succeeds, and 0 if either ran out of memory
+   allocating space for it or it was already too large.  
+   
+   REGEX_REALLOCATE_STACK requires `destination' be declared.   */
+
+#define DOUBLE_FAIL_STACK(fail_stack)					\
+  ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS		\
+   ? 0									\
+   : ((fail_stack).stack = (fail_stack_elt_t *)				\
+        REGEX_REALLOCATE_STACK ((fail_stack).stack, 			\
+          (fail_stack).size * sizeof (fail_stack_elt_t),		\
+          ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)),	\
+									\
+      (fail_stack).stack == NULL					\
+      ? 0								\
+      : ((fail_stack).size <<= 1, 					\
+         1)))
+
+
+/* Push pointer POINTER on FAIL_STACK. 
+   Return 1 if was able to do so and 0 if ran out of memory allocating
+   space to do so.  */
+#define PUSH_PATTERN_OP(POINTER, FAIL_STACK)				\
+  ((FAIL_STACK_FULL ()							\
+    && !DOUBLE_FAIL_STACK (FAIL_STACK))					\
+   ? 0									\
+   : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER,	\
+      1))
+
+/* Push a pointer value onto the failure stack.
+   Assumes the variable `fail_stack'.  Probably should only
+   be called from within `PUSH_FAILURE_POINT'.  */
+#define PUSH_FAILURE_POINTER(item)					\
+  fail_stack.stack[fail_stack.avail++].pointer = (unsigned char *) (item)
+
+/* This pushes an integer-valued item onto the failure stack.
+   Assumes the variable `fail_stack'.  Probably should only
+   be called from within `PUSH_FAILURE_POINT'.  */
+#define PUSH_FAILURE_INT(item)					\
+  fail_stack.stack[fail_stack.avail++].integer = (item)
+
+/* Push a fail_stack_elt_t value onto the failure stack.
+   Assumes the variable `fail_stack'.  Probably should only
+   be called from within `PUSH_FAILURE_POINT'.  */
+#define PUSH_FAILURE_ELT(item)					\
+  fail_stack.stack[fail_stack.avail++] =  (item)
+
+/* These three POP... operations complement the three PUSH... operations.
+   All assume that `fail_stack' is nonempty.  */
+#define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer
+#define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer
+#define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail]
+
+/* Used to omit pushing failure point id's when we're not debugging.  */
+#ifdef DEBUG
+#define DEBUG_PUSH PUSH_FAILURE_INT
+#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT ()
+#else
+#define DEBUG_PUSH(item)
+#define DEBUG_POP(item_addr)
+#endif
+
+
+/* Push the information about the state we will need
+   if we ever fail back to it.  
+   
+   Requires variables fail_stack, regstart, regend, reg_info, and
+   num_regs be declared.  DOUBLE_FAIL_STACK requires `destination' be
+   declared.
+   
+   Does `return FAILURE_CODE' if runs out of memory.  */
+
+#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code)	\
+  do {									\
+    char *destination;							\
+    /* Must be int, so when we don't save any registers, the arithmetic	\
+       of 0 + -1 isn't done as unsigned.  */				\
+    int this_reg;							\
+    									\
+    DEBUG_STATEMENT (failure_id++);					\
+    DEBUG_STATEMENT (nfailure_points_pushed++);				\
+    DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id);		\
+    DEBUG_PRINT2 ("  Before push, next avail: %d\n", (fail_stack).avail);\
+    DEBUG_PRINT2 ("                     size: %d\n", (fail_stack).size);\
+									\
+    DEBUG_PRINT2 ("  slots needed: %d\n", NUM_FAILURE_ITEMS);		\
+    DEBUG_PRINT2 ("     available: %d\n", REMAINING_AVAIL_SLOTS);	\
+									\
+    /* Ensure we have enough space allocated for what we will push.  */	\
+    while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS)			\
+      {									\
+        if (!DOUBLE_FAIL_STACK (fail_stack))				\
+          return failure_code;						\
+									\
+        DEBUG_PRINT2 ("\n  Doubled stack; size now: %d\n",		\
+		       (fail_stack).size);				\
+        DEBUG_PRINT2 ("  slots available: %d\n", REMAINING_AVAIL_SLOTS);\
+      }									\
+									\
+    /* Push the info, starting with the registers.  */			\
+    DEBUG_PRINT1 ("\n");						\
+									\
+    for (this_reg = lowest_active_reg; this_reg <= highest_active_reg;	\
+         this_reg++)							\
+      {									\
+	DEBUG_PRINT2 ("  Pushing reg: %d\n", this_reg);			\
+        DEBUG_STATEMENT (num_regs_pushed++);				\
+									\
+	DEBUG_PRINT2 ("    start: 0x%x\n", regstart[this_reg]);		\
+        PUSH_FAILURE_POINTER (regstart[this_reg]);			\
+                                                                        \
+	DEBUG_PRINT2 ("    end: 0x%x\n", regend[this_reg]);		\
+        PUSH_FAILURE_POINTER (regend[this_reg]);			\
+									\
+	DEBUG_PRINT2 ("    info: 0x%x\n      ", reg_info[this_reg]);	\
+        DEBUG_PRINT2 (" match_null=%d",					\
+                      REG_MATCH_NULL_STRING_P (reg_info[this_reg]));	\
+        DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg]));	\
+        DEBUG_PRINT2 (" matched_something=%d",				\
+                      MATCHED_SOMETHING (reg_info[this_reg]));		\
+        DEBUG_PRINT2 (" ever_matched=%d",				\
+                      EVER_MATCHED_SOMETHING (reg_info[this_reg]));	\
+	DEBUG_PRINT1 ("\n");						\
+        PUSH_FAILURE_ELT (reg_info[this_reg].word);			\
+      }									\
+									\
+    DEBUG_PRINT2 ("  Pushing  low active reg: %d\n", lowest_active_reg);\
+    PUSH_FAILURE_INT (lowest_active_reg);				\
+									\
+    DEBUG_PRINT2 ("  Pushing high active reg: %d\n", highest_active_reg);\
+    PUSH_FAILURE_INT (highest_active_reg);				\
+									\
+    DEBUG_PRINT2 ("  Pushing pattern 0x%x: ", pattern_place);		\
+    DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);		\
+    PUSH_FAILURE_POINTER (pattern_place);				\
+									\
+    DEBUG_PRINT2 ("  Pushing string 0x%x: `", string_place);		\
+    DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2,   \
+				 size2);				\
+    DEBUG_PRINT1 ("'\n");						\
+    PUSH_FAILURE_POINTER (string_place);				\
+									\
+    DEBUG_PRINT2 ("  Pushing failure id: %u\n", failure_id);		\
+    DEBUG_PUSH (failure_id);						\
+  } while (0)
+
+/* This is the number of items that are pushed and popped on the stack
+   for each register.  */
+#define NUM_REG_ITEMS  3
+
+/* Individual items aside from the registers.  */
+#ifdef DEBUG
+#define NUM_NONREG_ITEMS 5 /* Includes failure point id.  */
+#else
+#define NUM_NONREG_ITEMS 4
+#endif
+
+/* We push at most this many items on the stack.  */
+#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
+
+/* We actually push this many items.  */
+#define NUM_FAILURE_ITEMS						\
+  ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS 	\
+    + NUM_NONREG_ITEMS)
+
+/* How many items can still be added to the stack without overflowing it.  */
+#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
+
+
+/* Pops what PUSH_FAIL_STACK pushes.
+
+   We restore into the parameters, all of which should be lvalues:
+     STR -- the saved data position.
+     PAT -- the saved pattern position.
+     LOW_REG, HIGH_REG -- the highest and lowest active registers.
+     REGSTART, REGEND -- arrays of string positions.
+     REG_INFO -- array of information about each subexpression.
+   
+   Also assumes the variables `fail_stack' and (if debugging), `bufp',
+   `pend', `string1', `size1', `string2', and `size2'.  */
+
+#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
+{									\
+  DEBUG_STATEMENT (fail_stack_elt_t failure_id;)			\
+  int this_reg;								\
+  const unsigned char *string_temp;					\
+									\
+  assert (!FAIL_STACK_EMPTY ());					\
+									\
+  /* Remove failure points and point to how many regs pushed.  */	\
+  DEBUG_PRINT1 ("POP_FAILURE_POINT:\n");				\
+  DEBUG_PRINT2 ("  Before pop, next avail: %d\n", fail_stack.avail);	\
+  DEBUG_PRINT2 ("                    size: %d\n", fail_stack.size);	\
+									\
+  assert (fail_stack.avail >= NUM_NONREG_ITEMS);			\
+									\
+  DEBUG_POP (&failure_id);						\
+  DEBUG_PRINT2 ("  Popping failure id: %u\n", failure_id);		\
+									\
+  /* If the saved string location is NULL, it came from an		\
+     on_failure_keep_string_jump opcode, and we want to throw away the	\
+     saved NULL, thus retaining our current position in the string.  */	\
+  string_temp = POP_FAILURE_POINTER ();					\
+  if (string_temp != NULL)						\
+    str = (const char *) string_temp;					\
+									\
+  DEBUG_PRINT2 ("  Popping string 0x%x: `", str);			\
+  DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2);	\
+  DEBUG_PRINT1 ("'\n");							\
+									\
+  pat = (unsigned char *) POP_FAILURE_POINTER ();			\
+  DEBUG_PRINT2 ("  Popping pattern 0x%x: ", pat);			\
+  DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend);			\
+									\
+  /* Restore register info.  */						\
+  high_reg = (unsigned) POP_FAILURE_INT ();				\
+  DEBUG_PRINT2 ("  Popping high active reg: %d\n", high_reg);		\
+									\
+  low_reg = (unsigned) POP_FAILURE_INT ();				\
+  DEBUG_PRINT2 ("  Popping  low active reg: %d\n", low_reg);		\
+									\
+  for (this_reg = high_reg; this_reg >= low_reg; this_reg--)		\
+    {									\
+      DEBUG_PRINT2 ("    Popping reg: %d\n", this_reg);			\
+									\
+      reg_info[this_reg].word = POP_FAILURE_ELT ();			\
+      DEBUG_PRINT2 ("      info: 0x%x\n", reg_info[this_reg]);		\
+									\
+      regend[this_reg] = (const char *) POP_FAILURE_POINTER ();		\
+      DEBUG_PRINT2 ("      end: 0x%x\n", regend[this_reg]);		\
+									\
+      regstart[this_reg] = (const char *) POP_FAILURE_POINTER ();	\
+      DEBUG_PRINT2 ("      start: 0x%x\n", regstart[this_reg]);		\
+    }									\
+									\
+  set_regs_matched_done = 0;						\
+  DEBUG_STATEMENT (nfailure_points_popped++);				\
+} /* POP_FAILURE_POINT */
+
+
+
+
+/* Structure for per-register (a.k.a. per-group) information.
+   Other register information, such as the
+   starting and ending positions (which are addresses), and the list of
+   inner groups (which is a bits list) are maintained in separate
+   variables.  
+   
+   We are making a (strictly speaking) nonportable assumption here: that
+   the compiler will pack our bit fields into something that fits into
+   the type of `word', i.e., is something that fits into one item on the
+   failure stack.  */
+
+typedef union
+{
+  fail_stack_elt_t word;
+  struct
+  {
+      /* This field is one if this group can match the empty string,
+         zero if not.  If not yet determined,  `MATCH_NULL_UNSET_VALUE'.  */
+#define MATCH_NULL_UNSET_VALUE 3
+    unsigned match_null_string_p : 2;
+    unsigned is_active : 1;
+    unsigned matched_something : 1;
+    unsigned ever_matched_something : 1;
+  } bits;
+} register_info_type;
+
+#define REG_MATCH_NULL_STRING_P(R)  ((R).bits.match_null_string_p)
+#define IS_ACTIVE(R)  ((R).bits.is_active)
+#define MATCHED_SOMETHING(R)  ((R).bits.matched_something)
+#define EVER_MATCHED_SOMETHING(R)  ((R).bits.ever_matched_something)
+
+
+/* Call this when have matched a real character; it sets `matched' flags
+   for the subexpressions which we are currently inside.  Also records
+   that those subexprs have matched.  */
+#define SET_REGS_MATCHED()						\
+  do									\
+    {									\
+      if (!set_regs_matched_done)					\
+	{								\
+	  unsigned r;							\
+	  set_regs_matched_done = 1;					\
+	  for (r = lowest_active_reg; r <= highest_active_reg; r++)	\
+	    {								\
+	      MATCHED_SOMETHING (reg_info[r])				\
+		= EVER_MATCHED_SOMETHING (reg_info[r])			\
+		= 1;							\
+	    }								\
+	}								\
+    }									\
+  while (0)
+
+/* Registers are set to a sentinel when they haven't yet matched.  */
+static char reg_unset_dummy;
+#define REG_UNSET_VALUE (&reg_unset_dummy)
+#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
+
+
+/* Subroutine declarations and macros for regex_compile.  */
+
+static void store_op1 (), store_op2 ();
+static void insert_op1 (), insert_op2 ();
+static boolean at_begline_loc_p (), at_endline_loc_p ();
+static boolean group_in_compile_stack ();
+static reg_errcode_t compile_range ();
+
+/* Fetch the next character in the uncompiled pattern---translating it 
+   if necessary.  Also cast from a signed character in the constant
+   string passed to us by the user to an unsigned char that we can use
+   as an array index (in, e.g., `translate').  */
+#define PATFETCH(c)							\
+  do {if (p == pend) return REG_EEND;					\
+    c = (unsigned char) *p++;						\
+    if (translate) c = translate[c]; 					\
+  } while (0)
+
+/* Fetch the next character in the uncompiled pattern, with no
+   translation.  */
+#define PATFETCH_RAW(c)							\
+  do {if (p == pend) return REG_EEND;					\
+    c = (unsigned char) *p++; 						\
+  } while (0)
+
+/* Go backwards one character in the pattern.  */
+#define PATUNFETCH p--
+
+
+/* If `translate' is non-null, return translate[D], else just D.  We
+   cast the subscript to translate because some data is declared as
+   `char *', to avoid warnings when a string constant is passed.  But
+   when we use a character as a subscript we must make it unsigned.  */
+#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d))
+
+
+/* Macros for outputting the compiled pattern into `buffer'.  */
+
+/* If the buffer isn't allocated when it comes in, use this.  */
+#define INIT_BUF_SIZE  32
+
+/* Make sure we have at least N more bytes of space in buffer.  */
+#define GET_BUFFER_SPACE(n)						\
+    while (b - bufp->buffer + (n) > bufp->allocated)			\
+      EXTEND_BUFFER ()
+
+/* Make sure we have one more byte of buffer space and then add C to it.  */
+#define BUF_PUSH(c)							\
+  do {									\
+    GET_BUFFER_SPACE (1);						\
+    *b++ = (unsigned char) (c);						\
+  } while (0)
+
+
+/* Ensure we have two more bytes of buffer space and then append C1 and C2.  */
+#define BUF_PUSH_2(c1, c2)						\
+  do {									\
+    GET_BUFFER_SPACE (2);						\
+    *b++ = (unsigned char) (c1);					\
+    *b++ = (unsigned char) (c2);					\
+  } while (0)
+
+
+/* As with BUF_PUSH_2, except for three bytes.  */
+#define BUF_PUSH_3(c1, c2, c3)						\
+  do {									\
+    GET_BUFFER_SPACE (3);						\
+    *b++ = (unsigned char) (c1);					\
+    *b++ = (unsigned char) (c2);					\
+    *b++ = (unsigned char) (c3);					\
+  } while (0)
+
+
+/* Store a jump with opcode OP at LOC to location TO.  We store a
+   relative address offset by the three bytes the jump itself occupies.  */
+#define STORE_JUMP(op, loc, to) \
+  store_op1 (op, loc, (to) - (loc) - 3)
+
+/* Likewise, for a two-argument jump.  */
+#define STORE_JUMP2(op, loc, to, arg) \
+  store_op2 (op, loc, (to) - (loc) - 3, arg)
+
+/* Like `STORE_JUMP', but for inserting.  Assume `b' is the buffer end.  */
+#define INSERT_JUMP(op, loc, to) \
+  insert_op1 (op, loc, (to) - (loc) - 3, b)
+
+/* Like `STORE_JUMP2', but for inserting.  Assume `b' is the buffer end.  */
+#define INSERT_JUMP2(op, loc, to, arg) \
+  insert_op2 (op, loc, (to) - (loc) - 3, arg, b)
+
+
+/* This is not an arbitrary limit: the arguments which represent offsets
+   into the pattern are two bytes long.  So if 2^16 bytes turns out to
+   be too small, many things would have to change.  */
+#define MAX_BUF_SIZE (1L << 16)
+
+
+/* Extend the buffer by twice its current size via realloc and
+   reset the pointers that pointed into the old block to point to the
+   correct places in the new one.  If extending the buffer results in it
+   being larger than MAX_BUF_SIZE, then flag memory exhausted.  */
+#define EXTEND_BUFFER()							\
+  do { 									\
+    unsigned char *old_buffer = bufp->buffer;				\
+    if (bufp->allocated == MAX_BUF_SIZE) 				\
+      return REG_ESIZE;							\
+    bufp->allocated <<= 1;						\
+    if (bufp->allocated > MAX_BUF_SIZE)					\
+      bufp->allocated = MAX_BUF_SIZE; 					\
+    bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\
+    if (bufp->buffer == NULL)						\
+      return REG_ESPACE;						\
+    /* If the buffer moved, move all the pointers into it.  */		\
+    if (old_buffer != bufp->buffer)					\
+      {									\
+        b = (b - old_buffer) + bufp->buffer;				\
+        begalt = (begalt - old_buffer) + bufp->buffer;			\
+        if (fixup_alt_jump)						\
+          fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
+        if (laststart)							\
+          laststart = (laststart - old_buffer) + bufp->buffer;		\
+        if (pending_exact)						\
+          pending_exact = (pending_exact - old_buffer) + bufp->buffer;	\
+      }									\
+  } while (0)
+
+
+/* Since we have one byte reserved for the register number argument to
+   {start,stop}_memory, the maximum number of groups we can report
+   things about is what fits in that byte.  */
+#define MAX_REGNUM 255
+
+/* But patterns can have more than `MAX_REGNUM' registers.  We just
+   ignore the excess.  */
+typedef unsigned regnum_t;
+
+
+/* Macros for the compile stack.  */
+
+/* Since offsets can go either forwards or backwards, this type needs to
+   be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1.  */
+typedef int pattern_offset_t;
+
+typedef struct
+{
+  pattern_offset_t begalt_offset;
+  pattern_offset_t fixup_alt_jump;
+  pattern_offset_t inner_group_offset;
+  pattern_offset_t laststart_offset;  
+  regnum_t regnum;
+} compile_stack_elt_t;
+
+
+typedef struct
+{
+  compile_stack_elt_t *stack;
+  unsigned size;
+  unsigned avail;			/* Offset of next open position.  */
+} compile_stack_type;
+
+
+#define INIT_COMPILE_STACK_SIZE 32
+
+#define COMPILE_STACK_EMPTY  (compile_stack.avail == 0)
+#define COMPILE_STACK_FULL  (compile_stack.avail == compile_stack.size)
+
+/* The next available element.  */
+#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
+
+
+/* Set the bit for character C in a list.  */
+#define SET_LIST_BIT(c)                               \
+  (b[((unsigned char) (c)) / BYTEWIDTH]               \
+   |= 1 << (((unsigned char) c) % BYTEWIDTH))
+
+
+/* Get the next unsigned number in the uncompiled pattern.  */
+#define GET_UNSIGNED_NUMBER(num) 					\
+  { if (p != pend)							\
+     {									\
+       PATFETCH (c); 							\
+       while (ISDIGIT (c)) 						\
+         { 								\
+           if (num < 0)							\
+              num = 0;							\
+           num = num * 10 + c - '0'; 					\
+           if (p == pend) 						\
+              break; 							\
+           PATFETCH (c);						\
+         } 								\
+       } 								\
+    }		
+
+#define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
+
+#define IS_CHAR_CLASS(string)						\
+   (STREQ (string, "alpha") || STREQ (string, "upper")			\
+    || STREQ (string, "lower") || STREQ (string, "digit")		\
+    || STREQ (string, "alnum") || STREQ (string, "xdigit")		\
+    || STREQ (string, "space") || STREQ (string, "print")		\
+    || STREQ (string, "punct") || STREQ (string, "graph")		\
+    || STREQ (string, "cntrl") || STREQ (string, "blank"))
+
+
+#ifndef MATCH_MAY_ALLOCATE
+
+/* If we cannot allocate large objects within re_match_2_internal,
+   we make the fail stack and register vectors global.
+   The fail stack, we grow to the maximum size when a regexp
+   is compiled.
+   The register vectors, we adjust in size each time we
+   compile a regexp, according to the number of registers it needs.  */
+
+static fail_stack_type fail_stack;
+
+/* Size with which the following vectors are currently allocated.
+   That is so we can make them bigger as needed,
+   but never make them smaller.  */
+static int regs_allocated_size;
+
+static const char **     regstart, **     regend;
+static const char ** old_regstart, ** old_regend;
+static const char **best_regstart, **best_regend;
+static register_info_type *reg_info; 
+static const char **reg_dummy;
+static register_info_type *reg_info_dummy;
+
+/* Make the register vectors big enough for NUM_REGS registers,
+   but don't make them smaller.  */
+
+static
+regex_grow_registers (num_regs)
+     int num_regs;
+{
+  if (num_regs > regs_allocated_size)
+    {
+      RETALLOC_IF (regstart,	 num_regs, const char *);
+      RETALLOC_IF (regend,	 num_regs, const char *);
+      RETALLOC_IF (old_regstart, num_regs, const char *);
+      RETALLOC_IF (old_regend,	 num_regs, const char *);
+      RETALLOC_IF (best_regstart, num_regs, const char *);
+      RETALLOC_IF (best_regend,	 num_regs, const char *);
+      RETALLOC_IF (reg_info,	 num_regs, register_info_type);
+      RETALLOC_IF (reg_dummy,	 num_regs, const char *);
+      RETALLOC_IF (reg_info_dummy, num_regs, register_info_type);
+
+      regs_allocated_size = num_regs;
+    }
+}
+
+#endif /* not MATCH_MAY_ALLOCATE */
+
+
+/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
+   Returns one of error codes defined in `regex.h', or zero for success.
+
+   Assumes the `allocated' (and perhaps `buffer') and `translate'
+   fields are set in BUFP on entry.
+
+   If it succeeds, results are put in BUFP (if it returns an error, the
+   contents of BUFP are undefined):
+     `buffer' is the compiled pattern;
+     `syntax' is set to SYNTAX;
+     `used' is set to the length of the compiled pattern;
+     `fastmap_accurate' is zero;
+     `re_nsub' is the number of subexpressions in PATTERN;
+     `not_bol' and `not_eol' are zero;
+   
+   The `fastmap' and `newline_anchor' fields are neither
+   examined nor set.  */
+
+/* Return, freeing storage we allocated.  */
+#define FREE_STACK_RETURN(value)		\
+  return (free (compile_stack.stack), value)
+
+static reg_errcode_t
+regex_compile (pattern, size, syntax, bufp)
+     const char *pattern;
+     int size;
+     reg_syntax_t syntax;
+     struct re_pattern_buffer *bufp;
+{
+  /* We fetch characters from PATTERN here.  Even though PATTERN is
+     `char *' (i.e., signed), we declare these variables as unsigned, so
+     they can be reliably used as array indices.  */
+  register unsigned char c, c1;
+  
+  /* A random temporary spot in PATTERN.  */
+  const char *p1;
+
+  /* Points to the end of the buffer, where we should append.  */
+  register unsigned char *b;
+  
+  /* Keeps track of unclosed groups.  */
+  compile_stack_type compile_stack;
+
+  /* Points to the current (ending) position in the pattern.  */
+  const char *p = pattern;
+  const char *pend = pattern + size;
+  
+  /* How to translate the characters in the pattern.  */
+  char *translate = bufp->translate;
+
+  /* Address of the count-byte of the most recently inserted `exactn'
+     command.  This makes it possible to tell if a new exact-match
+     character can be added to that command or if the character requires
+     a new `exactn' command.  */
+  unsigned char *pending_exact = 0;
+
+  /* Address of start of the most recently finished expression.
+     This tells, e.g., postfix * where to find the start of its
+     operand.  Reset at the beginning of groups and alternatives.  */
+  unsigned char *laststart = 0;
+
+  /* Address of beginning of regexp, or inside of last group.  */
+  unsigned char *begalt;
+
+  /* Place in the uncompiled pattern (i.e., the {) to
+     which to go back if the interval is invalid.  */
+  const char *beg_interval;
+                
+  /* Address of the place where a forward jump should go to the end of
+     the containing expression.  Each alternative of an `or' -- except the
+     last -- ends with a forward jump of this sort.  */
+  unsigned char *fixup_alt_jump = 0;
+
+  /* Counts open-groups as they are encountered.  Remembered for the
+     matching close-group on the compile stack, so the same register
+     number is put in the stop_memory as the start_memory.  */
+  regnum_t regnum = 0;
+
+#ifdef DEBUG
+  DEBUG_PRINT1 ("\nCompiling pattern: ");
+  if (debug)
+    {
+      unsigned debug_count;
+      
+      for (debug_count = 0; debug_count < size; debug_count++)
+        putchar (pattern[debug_count]);
+      putchar ('\n');
+    }
+#endif /* DEBUG */
+
+  /* Initialize the compile stack.  */
+  compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
+  if (compile_stack.stack == NULL)
+    return REG_ESPACE;
+
+  compile_stack.size = INIT_COMPILE_STACK_SIZE;
+  compile_stack.avail = 0;
+
+  /* Initialize the pattern buffer.  */
+  bufp->syntax = syntax;
+  bufp->fastmap_accurate = 0;
+  bufp->not_bol = bufp->not_eol = 0;
+
+  /* Set `used' to zero, so that if we return an error, the pattern
+     printer (for debugging) will think there's no pattern.  We reset it
+     at the end.  */
+  bufp->used = 0;
+  
+  /* Always count groups, whether or not bufp->no_sub is set.  */
+  bufp->re_nsub = 0;				
+
+#if !defined (emacs) && !defined (SYNTAX_TABLE)
+  /* Initialize the syntax table.  */
+   init_syntax_once ();
+#endif
+
+  if (bufp->allocated == 0)
+    {
+      if (bufp->buffer)
+	{ /* If zero allocated, but buffer is non-null, try to realloc
+             enough space.  This loses if buffer's address is bogus, but
+             that is the user's responsibility.  */
+          RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char);
+        }
+      else
+        { /* Caller did not allocate a buffer.  Do it for them.  */
+          bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char);
+        }
+      if (!bufp->buffer) FREE_STACK_RETURN (REG_ESPACE);
+
+      bufp->allocated = INIT_BUF_SIZE;
+    }
+
+  begalt = b = bufp->buffer;
+
+  /* Loop through the uncompiled pattern until we're at the end.  */
+  while (p != pend)
+    {
+      PATFETCH (c);
+
+      switch (c)
+        {
+        case '^':
+          {
+            if (   /* If at start of pattern, it's an operator.  */
+                   p == pattern + 1
+                   /* If context independent, it's an operator.  */
+                || syntax & RE_CONTEXT_INDEP_ANCHORS
+                   /* Otherwise, depends on what's come before.  */
+                || at_begline_loc_p (pattern, p, syntax))
+              BUF_PUSH (begline);
+            else
+              goto normal_char;
+          }
+          break;
+
+
+        case '$':
+          {
+            if (   /* If at end of pattern, it's an operator.  */
+                   p == pend 
+                   /* If context independent, it's an operator.  */
+                || syntax & RE_CONTEXT_INDEP_ANCHORS
+                   /* Otherwise, depends on what's next.  */
+                || at_endline_loc_p (p, pend, syntax))
+               BUF_PUSH (endline);
+             else
+               goto normal_char;
+           }
+           break;
+
+
+	case '+':
+        case '?':
+          if ((syntax & RE_BK_PLUS_QM)
+              || (syntax & RE_LIMITED_OPS))
+            goto normal_char;
+        handle_plus:
+        case '*':
+          /* If there is no previous pattern... */
+          if (!laststart)
+            {
+              if (syntax & RE_CONTEXT_INVALID_OPS)
+                FREE_STACK_RETURN (REG_BADRPT);
+              else if (!(syntax & RE_CONTEXT_INDEP_OPS))
+                goto normal_char;
+            }
+
+          {
+            /* Are we optimizing this jump?  */
+            boolean keep_string_p = false;
+            
+            /* 1 means zero (many) matches is allowed.  */
+            char zero_times_ok = 0, many_times_ok = 0;
+
+            /* If there is a sequence of repetition chars, collapse it
+               down to just one (the right one).  We can't combine
+               interval operators with these because of, e.g., `a{2}*',
+               which should only match an even number of `a's.  */
+
+            for (;;)
+              {
+                zero_times_ok |= c != '+';
+                many_times_ok |= c != '?';
+
+                if (p == pend)
+                  break;
+
+                PATFETCH (c);
+
+                if (c == '*'
+                    || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
+                  ;
+
+                else if (syntax & RE_BK_PLUS_QM  &&  c == '\\')
+                  {
+                    if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+                    PATFETCH (c1);
+                    if (!(c1 == '+' || c1 == '?'))
+                      {
+                        PATUNFETCH;
+                        PATUNFETCH;
+                        break;
+                      }
+
+                    c = c1;
+                  }
+                else
+                  {
+                    PATUNFETCH;
+                    break;
+                  }
+
+                /* If we get here, we found another repeat character.  */
+               }
+
+            /* Star, etc. applied to an empty pattern is equivalent
+               to an empty pattern.  */
+            if (!laststart)  
+              break;
+
+            /* Now we know whether or not zero matches is allowed
+               and also whether or not two or more matches is allowed.  */
+            if (many_times_ok)
+              { /* More than one repetition is allowed, so put in at the
+                   end a backward relative jump from `b' to before the next
+                   jump we're going to put in below (which jumps from
+                   laststart to after this jump).  
+
+                   But if we are at the `*' in the exact sequence `.*\n',
+                   insert an unconditional jump backwards to the .,
+                   instead of the beginning of the loop.  This way we only
+                   push a failure point once, instead of every time
+                   through the loop.  */
+                assert (p - 1 > pattern);
+
+                /* Allocate the space for the jump.  */
+                GET_BUFFER_SPACE (3);
+
+                /* We know we are not at the first character of the pattern,
+                   because laststart was nonzero.  And we've already
+                   incremented `p', by the way, to be the character after
+                   the `*'.  Do we have to do something analogous here
+                   for null bytes, because of RE_DOT_NOT_NULL?  */
+                if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
+		    && zero_times_ok
+                    && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
+                    && !(syntax & RE_DOT_NEWLINE))
+                  { /* We have .*\n.  */
+                    STORE_JUMP (jump, b, laststart);
+                    keep_string_p = true;
+                  }
+                else
+                  /* Anything else.  */
+                  STORE_JUMP (maybe_pop_jump, b, laststart - 3);
+
+                /* We've added more stuff to the buffer.  */
+                b += 3;
+              }
+
+            /* On failure, jump from laststart to b + 3, which will be the
+               end of the buffer after this jump is inserted.  */
+            GET_BUFFER_SPACE (3);
+            INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
+                                       : on_failure_jump,
+                         laststart, b + 3);
+            pending_exact = 0;
+            b += 3;
+
+            if (!zero_times_ok)
+              {
+                /* At least one repetition is required, so insert a
+                   `dummy_failure_jump' before the initial
+                   `on_failure_jump' instruction of the loop. This
+                   effects a skip over that instruction the first time
+                   we hit that loop.  */
+                GET_BUFFER_SPACE (3);
+                INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
+                b += 3;
+              }
+            }
+	  break;
+
+
+	case '.':
+          laststart = b;
+          BUF_PUSH (anychar);
+          break;
+
+
+        case '[':
+          {
+            boolean had_char_class = false;
+
+            if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+            /* Ensure that we have enough space to push a charset: the
+               opcode, the length count, and the bitset; 34 bytes in all.  */
+	    GET_BUFFER_SPACE (34);
+
+            laststart = b;
+
+            /* We test `*p == '^' twice, instead of using an if
+               statement, so we only need one BUF_PUSH.  */
+            BUF_PUSH (*p == '^' ? charset_not : charset); 
+            if (*p == '^')
+              p++;
+
+            /* Remember the first position in the bracket expression.  */
+            p1 = p;
+
+            /* Push the number of bytes in the bitmap.  */
+            BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+
+            /* Clear the whole map.  */
+            bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+
+            /* charset_not matches newline according to a syntax bit.  */
+            if ((re_opcode_t) b[-2] == charset_not
+                && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
+              SET_LIST_BIT ('\n');
+
+            /* Read in characters and ranges, setting map bits.  */
+            for (;;)
+              {
+                if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+                PATFETCH (c);
+
+                /* \ might escape characters inside [...] and [^...].  */
+                if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+                  {
+                    if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+                    PATFETCH (c1);
+                    SET_LIST_BIT (c1);
+                    continue;
+                  }
+
+                /* Could be the end of the bracket expression.  If it's
+                   not (i.e., when the bracket expression is `[]' so
+                   far), the ']' character bit gets set way below.  */
+                if (c == ']' && p != p1 + 1)
+                  break;
+
+                /* Look ahead to see if it's a range when the last thing
+                   was a character class.  */
+                if (had_char_class && c == '-' && *p != ']')
+                  FREE_STACK_RETURN (REG_ERANGE);
+
+                /* Look ahead to see if it's a range when the last thing
+                   was a character: if this is a hyphen not at the
+                   beginning or the end of a list, then it's the range
+                   operator.  */
+                if (c == '-' 
+                    && !(p - 2 >= pattern && p[-2] == '[') 
+                    && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
+                    && *p != ']')
+                  {
+                    reg_errcode_t ret
+                      = compile_range (&p, pend, translate, syntax, b);
+                    if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+                  }
+
+                else if (p[0] == '-' && p[1] != ']')
+                  { /* This handles ranges made up of characters only.  */
+                    reg_errcode_t ret;
+
+		    /* Move past the `-'.  */
+                    PATFETCH (c1);
+                    
+                    ret = compile_range (&p, pend, translate, syntax, b);
+                    if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+                  }
+
+                /* See if we're at the beginning of a possible character
+                   class.  */
+
+                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
+                  { /* Leave room for the null.  */
+                    char str[CHAR_CLASS_MAX_LENGTH + 1];
+
+                    PATFETCH (c);
+                    c1 = 0;
+
+                    /* If pattern is `[[:'.  */
+                    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+                    for (;;)
+                      {
+                        PATFETCH (c);
+                        if (c == ':' || c == ']' || p == pend
+                            || c1 == CHAR_CLASS_MAX_LENGTH)
+                          break;
+                        str[c1++] = c;
+                      }
+                    str[c1] = '\0';
+
+                    /* If isn't a word bracketed by `[:' and:`]':
+                       undo the ending character, the letters, and leave 
+                       the leading `:' and `[' (but set bits for them).  */
+                    if (c == ':' && *p == ']')
+                      {
+                        int ch;
+                        boolean is_alnum = STREQ (str, "alnum");
+                        boolean is_alpha = STREQ (str, "alpha");
+                        boolean is_blank = STREQ (str, "blank");
+                        boolean is_cntrl = STREQ (str, "cntrl");
+                        boolean is_digit = STREQ (str, "digit");
+                        boolean is_graph = STREQ (str, "graph");
+                        boolean is_lower = STREQ (str, "lower");
+                        boolean is_print = STREQ (str, "print");
+                        boolean is_punct = STREQ (str, "punct");
+                        boolean is_space = STREQ (str, "space");
+                        boolean is_upper = STREQ (str, "upper");
+                        boolean is_xdigit = STREQ (str, "xdigit");
+                        
+                        if (!IS_CHAR_CLASS (str))
+			  FREE_STACK_RETURN (REG_ECTYPE);
+
+                        /* Throw away the ] at the end of the character
+                           class.  */
+                        PATFETCH (c);					
+
+                        if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+                        for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
+                          {
+			    /* This was split into 3 if's to
+			       avoid an arbitrary limit in some compiler.  */
+                            if (   (is_alnum  && ISALNUM (ch))
+                                || (is_alpha  && ISALPHA (ch))
+                                || (is_blank  && ISBLANK (ch))
+                                || (is_cntrl  && ISCNTRL (ch)))
+			      SET_LIST_BIT (ch);
+			    if (   (is_digit  && ISDIGIT (ch))
+                                || (is_graph  && ISGRAPH (ch))
+                                || (is_lower  && ISLOWER (ch))
+                                || (is_print  && ISPRINT (ch)))
+			      SET_LIST_BIT (ch);
+			    if (   (is_punct  && ISPUNCT (ch))
+                                || (is_space  && ISSPACE (ch))
+                                || (is_upper  && ISUPPER (ch))
+                                || (is_xdigit && ISXDIGIT (ch)))
+			      SET_LIST_BIT (ch);
+                          }
+                        had_char_class = true;
+                      }
+                    else
+                      {
+                        c1++;
+                        while (c1--)    
+                          PATUNFETCH;
+                        SET_LIST_BIT ('[');
+                        SET_LIST_BIT (':');
+                        had_char_class = false;
+                      }
+                  }
+                else
+                  {
+                    had_char_class = false;
+                    SET_LIST_BIT (c);
+                  }
+              }
+
+            /* Discard any (non)matching list bytes that are all 0 at the
+               end of the map.  Decrease the map-length byte too.  */
+            while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) 
+              b[-1]--; 
+            b += b[-1];
+          }
+          break;
+
+
+	case '(':
+          if (syntax & RE_NO_BK_PARENS)
+            goto handle_open;
+          else
+            goto normal_char;
+
+
+        case ')':
+          if (syntax & RE_NO_BK_PARENS)
+            goto handle_close;
+          else
+            goto normal_char;
+
+
+        case '\n':
+          if (syntax & RE_NEWLINE_ALT)
+            goto handle_alt;
+          else
+            goto normal_char;
+
+
+	case '|':
+          if (syntax & RE_NO_BK_VBAR)
+            goto handle_alt;
+          else
+            goto normal_char;
+
+
+        case '{':
+           if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
+             goto handle_interval;
+           else
+             goto normal_char;
+
+
+        case '\\':
+          if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+          /* Do not translate the character after the \, so that we can
+             distinguish, e.g., \B from \b, even if we normally would
+             translate, e.g., B to b.  */
+          PATFETCH_RAW (c);
+
+          switch (c)
+            {
+            case '(':
+              if (syntax & RE_NO_BK_PARENS)
+                goto normal_backslash;
+
+            handle_open:
+              bufp->re_nsub++;
+              regnum++;
+
+              if (COMPILE_STACK_FULL)
+                { 
+                  RETALLOC (compile_stack.stack, compile_stack.size << 1,
+                            compile_stack_elt_t);
+                  if (compile_stack.stack == NULL) return REG_ESPACE;
+
+                  compile_stack.size <<= 1;
+                }
+
+              /* These are the values to restore when we hit end of this
+                 group.  They are all relative offsets, so that if the
+                 whole pattern moves because of realloc, they will still
+                 be valid.  */
+              COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
+              COMPILE_STACK_TOP.fixup_alt_jump 
+                = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
+              COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
+              COMPILE_STACK_TOP.regnum = regnum;
+
+              /* We will eventually replace the 0 with the number of
+                 groups inner to this one.  But do not push a
+                 start_memory for groups beyond the last one we can
+                 represent in the compiled pattern.  */
+              if (regnum <= MAX_REGNUM)
+                {
+                  COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2;
+                  BUF_PUSH_3 (start_memory, regnum, 0);
+                }
+                
+              compile_stack.avail++;
+
+              fixup_alt_jump = 0;
+              laststart = 0;
+              begalt = b;
+	      /* If we've reached MAX_REGNUM groups, then this open
+		 won't actually generate any code, so we'll have to
+		 clear pending_exact explicitly.  */
+	      pending_exact = 0;
+              break;
+
+
+            case ')':
+              if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
+
+              if (COMPILE_STACK_EMPTY)
+                if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+                  goto normal_backslash;
+                else
+                  FREE_STACK_RETURN (REG_ERPAREN);
+
+            handle_close:
+              if (fixup_alt_jump)
+                { /* Push a dummy failure point at the end of the
+                     alternative for a possible future
+                     `pop_failure_jump' to pop.  See comments at
+                     `push_dummy_failure' in `re_match_2'.  */
+                  BUF_PUSH (push_dummy_failure);
+                  
+                  /* We allocated space for this jump when we assigned
+                     to `fixup_alt_jump', in the `handle_alt' case below.  */
+                  STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
+                }
+
+              /* See similar code for backslashed left paren above.  */
+              if (COMPILE_STACK_EMPTY)
+                if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+                  goto normal_char;
+                else
+                  FREE_STACK_RETURN (REG_ERPAREN);
+
+              /* Since we just checked for an empty stack above, this
+                 ``can't happen''.  */
+              assert (compile_stack.avail != 0);
+              {
+                /* We don't just want to restore into `regnum', because
+                   later groups should continue to be numbered higher,
+                   as in `(ab)c(de)' -- the second group is #2.  */
+                regnum_t this_group_regnum;
+
+                compile_stack.avail--;		
+                begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
+                fixup_alt_jump
+                  = COMPILE_STACK_TOP.fixup_alt_jump
+                    ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 
+                    : 0;
+                laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
+                this_group_regnum = COMPILE_STACK_TOP.regnum;
+		/* If we've reached MAX_REGNUM groups, then this open
+		   won't actually generate any code, so we'll have to
+		   clear pending_exact explicitly.  */
+		pending_exact = 0;
+
+                /* We're at the end of the group, so now we know how many
+                   groups were inside this one.  */
+                if (this_group_regnum <= MAX_REGNUM)
+                  {
+                    unsigned char *inner_group_loc
+                      = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset;
+                    
+                    *inner_group_loc = regnum - this_group_regnum;
+                    BUF_PUSH_3 (stop_memory, this_group_regnum,
+                                regnum - this_group_regnum);
+                  }
+              }
+              break;
+
+
+            case '|':					/* `\|'.  */
+              if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
+                goto normal_backslash;
+            handle_alt:
+              if (syntax & RE_LIMITED_OPS)
+                goto normal_char;
+
+              /* Insert before the previous alternative a jump which
+                 jumps to this alternative if the former fails.  */
+              GET_BUFFER_SPACE (3);
+              INSERT_JUMP (on_failure_jump, begalt, b + 6);
+              pending_exact = 0;
+              b += 3;
+
+              /* The alternative before this one has a jump after it
+                 which gets executed if it gets matched.  Adjust that
+                 jump so it will jump to this alternative's analogous
+                 jump (put in below, which in turn will jump to the next
+                 (if any) alternative's such jump, etc.).  The last such
+                 jump jumps to the correct final destination.  A picture:
+                          _____ _____ 
+                          |   | |   |   
+                          |   v |   v 
+                         a | b   | c   
+
+                 If we are at `b', then fixup_alt_jump right now points to a
+                 three-byte space after `a'.  We'll put in the jump, set
+                 fixup_alt_jump to right after `b', and leave behind three
+                 bytes which we'll fill in when we get to after `c'.  */
+
+              if (fixup_alt_jump)
+                STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+              /* Mark and leave space for a jump after this alternative,
+                 to be filled in later either by next alternative or
+                 when know we're at the end of a series of alternatives.  */
+              fixup_alt_jump = b;
+              GET_BUFFER_SPACE (3);
+              b += 3;
+
+              laststart = 0;
+              begalt = b;
+              break;
+
+
+            case '{': 
+              /* If \{ is a literal.  */
+              if (!(syntax & RE_INTERVALS)
+                     /* If we're at `\{' and it's not the open-interval 
+                        operator.  */
+                  || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+                  || (p - 2 == pattern  &&  p == pend))
+                goto normal_backslash;
+
+            handle_interval:
+              {
+                /* If got here, then the syntax allows intervals.  */
+
+                /* At least (most) this many matches must be made.  */
+                int lower_bound = -1, upper_bound = -1;
+
+                beg_interval = p - 1;
+
+                if (p == pend)
+                  {
+                    if (syntax & RE_NO_BK_BRACES)
+                      goto unfetch_interval;
+                    else
+                      FREE_STACK_RETURN (REG_EBRACE);
+                  }
+
+                GET_UNSIGNED_NUMBER (lower_bound);
+
+                if (c == ',')
+                  {
+                    GET_UNSIGNED_NUMBER (upper_bound);
+                    if (upper_bound < 0) upper_bound = RE_DUP_MAX;
+                  }
+                else
+                  /* Interval such as `{1}' => match exactly once. */
+                  upper_bound = lower_bound;
+
+                if (lower_bound < 0 || upper_bound > RE_DUP_MAX
+                    || lower_bound > upper_bound)
+                  {
+                    if (syntax & RE_NO_BK_BRACES)
+                      goto unfetch_interval;
+                    else 
+                      FREE_STACK_RETURN (REG_BADBR);
+                  }
+
+                if (!(syntax & RE_NO_BK_BRACES)) 
+                  {
+                    if (c != '\\') FREE_STACK_RETURN (REG_EBRACE);
+
+                    PATFETCH (c);
+                  }
+
+                if (c != '}')
+                  {
+                    if (syntax & RE_NO_BK_BRACES)
+                      goto unfetch_interval;
+                    else 
+                      FREE_STACK_RETURN (REG_BADBR);
+                  }
+
+                /* We just parsed a valid interval.  */
+
+                /* If it's invalid to have no preceding re.  */
+                if (!laststart)
+                  {
+                    if (syntax & RE_CONTEXT_INVALID_OPS)
+                      FREE_STACK_RETURN (REG_BADRPT);
+                    else if (syntax & RE_CONTEXT_INDEP_OPS)
+                      laststart = b;
+                    else
+                      goto unfetch_interval;
+                  }
+
+                /* If the upper bound is zero, don't want to succeed at
+                   all; jump from `laststart' to `b + 3', which will be
+                   the end of the buffer after we insert the jump.  */
+                 if (upper_bound == 0)
+                   {
+                     GET_BUFFER_SPACE (3);
+                     INSERT_JUMP (jump, laststart, b + 3);
+                     b += 3;
+                   }
+
+                 /* Otherwise, we have a nontrivial interval.  When
+                    we're all done, the pattern will look like:
+                      set_number_at <jump count> <upper bound>
+                      set_number_at <succeed_n count> <lower bound>
+                      succeed_n <after jump addr> <succeed_n count>
+                      <body of loop>
+                      jump_n <succeed_n addr> <jump count>
+                    (The upper bound and `jump_n' are omitted if
+                    `upper_bound' is 1, though.)  */
+                 else 
+                   { /* If the upper bound is > 1, we need to insert
+                        more at the end of the loop.  */
+                     unsigned nbytes = 10 + (upper_bound > 1) * 10;
+
+                     GET_BUFFER_SPACE (nbytes);
+
+                     /* Initialize lower bound of the `succeed_n', even
+                        though it will be set during matching by its
+                        attendant `set_number_at' (inserted next),
+                        because `re_compile_fastmap' needs to know.
+                        Jump to the `jump_n' we might insert below.  */
+                     INSERT_JUMP2 (succeed_n, laststart,
+                                   b + 5 + (upper_bound > 1) * 5,
+                                   lower_bound);
+                     b += 5;
+
+                     /* Code to initialize the lower bound.  Insert 
+                        before the `succeed_n'.  The `5' is the last two
+                        bytes of this `set_number_at', plus 3 bytes of
+                        the following `succeed_n'.  */
+                     insert_op2 (set_number_at, laststart, 5, lower_bound, b);
+                     b += 5;
+
+                     if (upper_bound > 1)
+                       { /* More than one repetition is allowed, so
+                            append a backward jump to the `succeed_n'
+                            that starts this interval.
+                            
+                            When we've reached this during matching,
+                            we'll have matched the interval once, so
+                            jump back only `upper_bound - 1' times.  */
+                         STORE_JUMP2 (jump_n, b, laststart + 5,
+                                      upper_bound - 1);
+                         b += 5;
+
+                         /* The location we want to set is the second
+                            parameter of the `jump_n'; that is `b-2' as
+                            an absolute address.  `laststart' will be
+                            the `set_number_at' we're about to insert;
+                            `laststart+3' the number to set, the source
+                            for the relative address.  But we are
+                            inserting into the middle of the pattern --
+                            so everything is getting moved up by 5.
+                            Conclusion: (b - 2) - (laststart + 3) + 5,
+                            i.e., b - laststart.
+                            
+                            We insert this at the beginning of the loop
+                            so that if we fail during matching, we'll
+                            reinitialize the bounds.  */
+                         insert_op2 (set_number_at, laststart, b - laststart,
+                                     upper_bound - 1, b);
+                         b += 5;
+                       }
+                   }
+                pending_exact = 0;
+                beg_interval = NULL;
+              }
+              break;
+
+            unfetch_interval:
+              /* If an invalid interval, match the characters as literals.  */
+               assert (beg_interval);
+               p = beg_interval;
+               beg_interval = NULL;
+
+               /* normal_char and normal_backslash need `c'.  */
+               PATFETCH (c);	
+
+               if (!(syntax & RE_NO_BK_BRACES))
+                 {
+                   if (p > pattern  &&  p[-1] == '\\')
+                     goto normal_backslash;
+                 }
+               goto normal_char;
+
+#ifdef emacs
+            /* There is no way to specify the before_dot and after_dot
+               operators.  rms says this is ok.  --karl  */
+            case '=':
+              BUF_PUSH (at_dot);
+              break;
+
+            case 's':	
+              laststart = b;
+              PATFETCH (c);
+              BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
+              break;
+
+            case 'S':
+              laststart = b;
+              PATFETCH (c);
+              BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
+              break;
+#endif /* emacs */
+
+
+            case 'w':
+              laststart = b;
+              BUF_PUSH (wordchar);
+              break;
+
+
+            case 'W':
+              laststart = b;
+              BUF_PUSH (notwordchar);
+              break;
+
+
+            case '<':
+              BUF_PUSH (wordbeg);
+              break;
+
+            case '>':
+              BUF_PUSH (wordend);
+              break;
+
+            case 'b':
+              BUF_PUSH (wordbound);
+              break;
+
+            case 'B':
+              BUF_PUSH (notwordbound);
+              break;
+
+            case '`':
+              BUF_PUSH (begbuf);
+              break;
+
+            case '\'':
+              BUF_PUSH (endbuf);
+              break;
+
+            case '1': case '2': case '3': case '4': case '5':
+            case '6': case '7': case '8': case '9':
+              if (syntax & RE_NO_BK_REFS)
+                goto normal_char;
+
+              c1 = c - '0';
+
+              if (c1 > regnum)
+                FREE_STACK_RETURN (REG_ESUBREG);
+
+              /* Can't back reference to a subexpression if inside of it.  */
+              if (group_in_compile_stack (compile_stack, c1))
+                goto normal_char;
+
+              laststart = b;
+              BUF_PUSH_2 (duplicate, c1);
+              break;
+
+
+            case '+':
+            case '?':
+              if (syntax & RE_BK_PLUS_QM)
+                goto handle_plus;
+              else
+                goto normal_backslash;
+
+            default:
+            normal_backslash:
+              /* You might think it would be useful for \ to mean
+                 not to translate; but if we don't translate it
+                 it will never match anything.  */
+              c = TRANSLATE (c);
+              goto normal_char;
+            }
+          break;
+
+
+	default:
+        /* Expects the character in `c'.  */
+	normal_char:
+	      /* If no exactn currently being built.  */
+          if (!pending_exact 
+
+              /* If last exactn not at current position.  */
+              || pending_exact + *pending_exact + 1 != b
+              
+              /* We have only one byte following the exactn for the count.  */
+	      || *pending_exact == (1 << BYTEWIDTH) - 1
+
+              /* If followed by a repetition operator.  */
+              || *p == '*' || *p == '^'
+	      || ((syntax & RE_BK_PLUS_QM)
+		  ? *p == '\\' && (p[1] == '+' || p[1] == '?')
+		  : (*p == '+' || *p == '?'))
+	      || ((syntax & RE_INTERVALS)
+                  && ((syntax & RE_NO_BK_BRACES)
+		      ? *p == '{'
+                      : (p[0] == '\\' && p[1] == '{'))))
+	    {
+	      /* Start building a new exactn.  */
+              
+              laststart = b;
+
+	      BUF_PUSH_2 (exactn, 0);
+	      pending_exact = b - 1;
+            }
+            
+	  BUF_PUSH (c);
+          (*pending_exact)++;
+	  break;
+        } /* switch (c) */
+    } /* while p != pend */
+
+  
+  /* Through the pattern now.  */
+  
+  if (fixup_alt_jump)
+    STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+  if (!COMPILE_STACK_EMPTY) 
+    FREE_STACK_RETURN (REG_EPAREN);
+
+  /* If we don't want backtracking, force success
+     the first time we reach the end of the compiled pattern.  */
+  if (syntax & RE_NO_POSIX_BACKTRACKING)
+    BUF_PUSH (succeed);
+
+  free (compile_stack.stack);
+
+  /* We have succeeded; set the length of the buffer.  */
+  bufp->used = b - bufp->buffer;
+
+#ifdef DEBUG
+  if (debug)
+    {
+      DEBUG_PRINT1 ("\nCompiled pattern: \n");
+      print_compiled_pattern (bufp);
+    }
+#endif /* DEBUG */
+
+#ifndef MATCH_MAY_ALLOCATE
+  /* Initialize the failure stack to the largest possible stack.  This
+     isn't necessary unless we're trying to avoid calling alloca in
+     the search and match routines.  */
+  {
+    int num_regs = bufp->re_nsub + 1;
+
+    /* Since DOUBLE_FAIL_STACK refuses to double only if the current size
+       is strictly greater than re_max_failures, the largest possible stack
+       is 2 * re_max_failures failure points.  */
+    if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS))
+      {
+	fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS);
+
+#ifdef emacs
+	if (! fail_stack.stack)
+	  fail_stack.stack
+	    = (fail_stack_elt_t *) xmalloc (fail_stack.size 
+					    * sizeof (fail_stack_elt_t));
+	else
+	  fail_stack.stack
+	    = (fail_stack_elt_t *) xrealloc (fail_stack.stack,
+					     (fail_stack.size
+					      * sizeof (fail_stack_elt_t)));
+#else /* not emacs */
+	if (! fail_stack.stack)
+	  fail_stack.stack
+	    = (fail_stack_elt_t *) malloc (fail_stack.size 
+					   * sizeof (fail_stack_elt_t));
+	else
+	  fail_stack.stack
+	    = (fail_stack_elt_t *) realloc (fail_stack.stack,
+					    (fail_stack.size
+					     * sizeof (fail_stack_elt_t)));
+#endif /* not emacs */
+      }
+
+    regex_grow_registers (num_regs);
+  }
+#endif /* not MATCH_MAY_ALLOCATE */
+
+  return REG_NOERROR;
+} /* regex_compile */
+
+
+/* Subroutines for `regex_compile'.  */
+
+/* Store OP at LOC followed by two-byte integer parameter ARG.  */
+
+static void
+store_op1 (op, loc, arg)
+    re_opcode_t op;
+    unsigned char *loc;
+    int arg;
+{
+  *loc = (unsigned char) op;
+  STORE_NUMBER (loc + 1, arg);
+}
+
+
+/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2.  */
+
+static void
+store_op2 (op, loc, arg1, arg2)
+    re_opcode_t op;
+    unsigned char *loc;
+    int arg1, arg2;
+{
+  *loc = (unsigned char) op;
+  STORE_NUMBER (loc + 1, arg1);
+  STORE_NUMBER (loc + 3, arg2);
+}
+
+
+/* Copy the bytes from LOC to END to open up three bytes of space at LOC
+   for OP followed by two-byte integer parameter ARG.  */
+
+static void
+insert_op1 (op, loc, arg, end)
+    re_opcode_t op;
+    unsigned char *loc;
+    int arg;
+    unsigned char *end;    
+{
+  register unsigned char *pfrom = end;
+  register unsigned char *pto = end + 3;
+
+  while (pfrom != loc)
+    *--pto = *--pfrom;
+    
+  store_op1 (op, loc, arg);
+}
+
+
+/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2.  */
+
+static void
+insert_op2 (op, loc, arg1, arg2, end)
+    re_opcode_t op;
+    unsigned char *loc;
+    int arg1, arg2;
+    unsigned char *end;    
+{
+  register unsigned char *pfrom = end;
+  register unsigned char *pto = end + 5;
+
+  while (pfrom != loc)
+    *--pto = *--pfrom;
+    
+  store_op2 (op, loc, arg1, arg2);
+}
+
+
+/* P points to just after a ^ in PATTERN.  Return true if that ^ comes
+   after an alternative or a begin-subexpression.  We assume there is at
+   least one character before the ^.  */
+
+static boolean
+at_begline_loc_p (pattern, p, syntax)
+    const char *pattern, *p;
+    reg_syntax_t syntax;
+{
+  const char *prev = p - 2;
+  boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
+  
+  return
+       /* After a subexpression?  */
+       (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
+       /* After an alternative?  */
+    || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
+}
+
+
+/* The dual of at_begline_loc_p.  This one is for $.  We assume there is
+   at least one character after the $, i.e., `P < PEND'.  */
+
+static boolean
+at_endline_loc_p (p, pend, syntax)
+    const char *p, *pend;
+    int syntax;
+{
+  const char *next = p;
+  boolean next_backslash = *next == '\\';
+  const char *next_next = p + 1 < pend ? p + 1 : NULL;
+  
+  return
+       /* Before a subexpression?  */
+       (syntax & RE_NO_BK_PARENS ? *next == ')'
+        : next_backslash && next_next && *next_next == ')')
+       /* Before an alternative?  */
+    || (syntax & RE_NO_BK_VBAR ? *next == '|'
+        : next_backslash && next_next && *next_next == '|');
+}
+
+
+/* Returns true if REGNUM is in one of COMPILE_STACK's elements and 
+   false if it's not.  */
+
+static boolean
+group_in_compile_stack (compile_stack, regnum)
+    compile_stack_type compile_stack;
+    regnum_t regnum;
+{
+  int this_element;
+
+  for (this_element = compile_stack.avail - 1;  
+       this_element >= 0; 
+       this_element--)
+    if (compile_stack.stack[this_element].regnum == regnum)
+      return true;
+
+  return false;
+}
+
+
+/* Read the ending character of a range (in a bracket expression) from the
+   uncompiled pattern *P_PTR (which ends at PEND).  We assume the
+   starting character is in `P[-2]'.  (`P[-1]' is the character `-'.)
+   Then we set the translation of all bits between the starting and
+   ending characters (inclusive) in the compiled pattern B.
+   
+   Return an error code.
+   
+   We use these short variable names so we can use the same macros as
+   `regex_compile' itself.  */
+
+static reg_errcode_t
+compile_range (p_ptr, pend, translate, syntax, b)
+    const char **p_ptr, *pend;
+    char *translate;
+    reg_syntax_t syntax;
+    unsigned char *b;
+{
+  unsigned this_char;
+
+  const char *p = *p_ptr;
+  int range_start, range_end;
+  
+  if (p == pend)
+    return REG_ERANGE;
+
+  /* Even though the pattern is a signed `char *', we need to fetch
+     with unsigned char *'s; if the high bit of the pattern character
+     is set, the range endpoints will be negative if we fetch using a
+     signed char *.
+
+     We also want to fetch the endpoints without translating them; the 
+     appropriate translation is done in the bit-setting loop below.  */
+  /* The SVR4 compiler on the 3B2 had trouble with unsigned const char *.  */
+  range_start = ((const unsigned char *) p)[-2];
+  range_end   = ((const unsigned char *) p)[0];
+
+  /* Have to increment the pointer into the pattern string, so the
+     caller isn't still at the ending character.  */
+  (*p_ptr)++;
+
+  /* If the start is after the end, the range is empty.  */
+  if (range_start > range_end)
+    return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
+
+  /* Here we see why `this_char' has to be larger than an `unsigned
+     char' -- the range is inclusive, so if `range_end' == 0xff
+     (assuming 8-bit characters), we would otherwise go into an infinite
+     loop, since all characters <= 0xff.  */
+  for (this_char = range_start; this_char <= range_end; this_char++)
+    {
+      SET_LIST_BIT (TRANSLATE (this_char));
+    }
+  
+  return REG_NOERROR;
+}
+
+
+/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
+   BUFP.  A fastmap records which of the (1 << BYTEWIDTH) possible
+   characters can start a string that matches the pattern.  This fastmap
+   is used by re_search to skip quickly over impossible starting points.
+
+   The caller must supply the address of a (1 << BYTEWIDTH)-byte data
+   area as BUFP->fastmap.
+   
+   We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
+   the pattern buffer.
+
+   Returns 0 if we succeed, -2 if an internal error.   */
+
+int
+re_compile_fastmap (bufp)
+     struct re_pattern_buffer *bufp;
+{
+  int j, k;
+#ifdef MATCH_MAY_ALLOCATE
+  fail_stack_type fail_stack;
+#endif
+#ifndef REGEX_MALLOC
+  char *destination;
+#endif
+  /* We don't push any register information onto the failure stack.  */
+  unsigned num_regs = 0;
+  
+  register char *fastmap = bufp->fastmap;
+  unsigned char *pattern = bufp->buffer;
+  unsigned long size = bufp->used;
+  unsigned char *p = pattern;
+  register unsigned char *pend = pattern + size;
+
+  /* This holds the pointer to the failure stack, when
+     it is allocated relocatably.  */
+  fail_stack_elt_t *failure_stack_ptr;
+
+  /* Assume that each path through the pattern can be null until
+     proven otherwise.  We set this false at the bottom of switch
+     statement, to which we get only if a particular path doesn't
+     match the empty string.  */
+  boolean path_can_be_null = true;
+
+  /* We aren't doing a `succeed_n' to begin with.  */
+  boolean succeed_n_p = false;
+
+  assert (fastmap != NULL && p != NULL);
+  
+  INIT_FAIL_STACK ();
+  bzero (fastmap, 1 << BYTEWIDTH);  /* Assume nothing's valid.  */
+  bufp->fastmap_accurate = 1;	    /* It will be when we're done.  */
+  bufp->can_be_null = 0;
+      
+  while (1)
+    {
+      if (p == pend || *p == succeed)
+	{
+	  /* We have reached the (effective) end of pattern.  */
+	  if (!FAIL_STACK_EMPTY ())
+	    {
+	      bufp->can_be_null |= path_can_be_null;
+
+	      /* Reset for next path.  */
+	      path_can_be_null = true;
+
+	      p = fail_stack.stack[--fail_stack.avail].pointer;
+
+	      continue;
+	    }
+	  else
+	    break;
+	}
+
+      /* We should never be about to go beyond the end of the pattern.  */
+      assert (p < pend);
+      
+      switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
+	{
+
+        /* I guess the idea here is to simply not bother with a fastmap
+           if a backreference is used, since it's too hard to figure out
+           the fastmap for the corresponding group.  Setting
+           `can_be_null' stops `re_search_2' from using the fastmap, so
+           that is all we do.  */
+	case duplicate:
+	  bufp->can_be_null = 1;
+          goto done;
+
+
+      /* Following are the cases which match a character.  These end
+         with `break'.  */
+
+	case exactn:
+          fastmap[p[1]] = 1;
+	  break;
+
+
+        case charset:
+          for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+	    if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
+              fastmap[j] = 1;
+	  break;
+
+
+	case charset_not:
+	  /* Chars beyond end of map must be allowed.  */
+	  for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+            fastmap[j] = 1;
+
+	  for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+	    if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
+              fastmap[j] = 1;
+          break;
+
+
+	case wordchar:
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    if (SYNTAX (j) == Sword)
+	      fastmap[j] = 1;
+	  break;
+
+
+	case notwordchar:
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    if (SYNTAX (j) != Sword)
+	      fastmap[j] = 1;
+	  break;
+
+
+        case anychar:
+	  {
+	    int fastmap_newline = fastmap['\n'];
+
+	    /* `.' matches anything ...  */
+	    for (j = 0; j < (1 << BYTEWIDTH); j++)
+	      fastmap[j] = 1;
+
+	    /* ... except perhaps newline.  */
+	    if (!(bufp->syntax & RE_DOT_NEWLINE))
+	      fastmap['\n'] = fastmap_newline;
+
+	    /* Return if we have already set `can_be_null'; if we have,
+	       then the fastmap is irrelevant.  Something's wrong here.  */
+	    else if (bufp->can_be_null)
+	      goto done;
+
+	    /* Otherwise, have to check alternative paths.  */
+	    break;
+	  }
+
+#ifdef emacs
+        case syntaxspec:
+	  k = *p++;
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    if (SYNTAX (j) == (enum syntaxcode) k)
+	      fastmap[j] = 1;
+	  break;
+
+
+	case notsyntaxspec:
+	  k = *p++;
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    if (SYNTAX (j) != (enum syntaxcode) k)
+	      fastmap[j] = 1;
+	  break;
+
+
+      /* All cases after this match the empty string.  These end with
+         `continue'.  */
+
+
+	case before_dot:
+	case at_dot:
+	case after_dot:
+          continue;
+#endif /* not emacs */
+
+
+        case no_op:
+        case begline:
+        case endline:
+	case begbuf:
+	case endbuf:
+	case wordbound:
+	case notwordbound:
+	case wordbeg:
+	case wordend:
+        case push_dummy_failure:
+          continue;
+
+
+	case jump_n:
+        case pop_failure_jump:
+	case maybe_pop_jump:
+	case jump:
+        case jump_past_alt:
+	case dummy_failure_jump:
+          EXTRACT_NUMBER_AND_INCR (j, p);
+	  p += j;	
+	  if (j > 0)
+	    continue;
+            
+          /* Jump backward implies we just went through the body of a
+             loop and matched nothing.  Opcode jumped to should be
+             `on_failure_jump' or `succeed_n'.  Just treat it like an
+             ordinary jump.  For a * loop, it has pushed its failure
+             point already; if so, discard that as redundant.  */
+          if ((re_opcode_t) *p != on_failure_jump
+	      && (re_opcode_t) *p != succeed_n)
+	    continue;
+
+          p++;
+          EXTRACT_NUMBER_AND_INCR (j, p);
+          p += j;		
+	  
+          /* If what's on the stack is where we are now, pop it.  */
+          if (!FAIL_STACK_EMPTY () 
+	      && fail_stack.stack[fail_stack.avail - 1].pointer == p)
+            fail_stack.avail--;
+
+          continue;
+
+
+        case on_failure_jump:
+        case on_failure_keep_string_jump:
+	handle_on_failure_jump:
+          EXTRACT_NUMBER_AND_INCR (j, p);
+
+          /* For some patterns, e.g., `(a?)?', `p+j' here points to the
+             end of the pattern.  We don't want to push such a point,
+             since when we restore it above, entering the switch will
+             increment `p' past the end of the pattern.  We don't need
+             to push such a point since we obviously won't find any more
+             fastmap entries beyond `pend'.  Such a pattern can match
+             the null string, though.  */
+          if (p + j < pend)
+            {
+              if (!PUSH_PATTERN_OP (p + j, fail_stack))
+		{
+		  RESET_FAIL_STACK ();
+		  return -2;
+		}
+            }
+          else
+            bufp->can_be_null = 1;
+
+          if (succeed_n_p)
+            {
+              EXTRACT_NUMBER_AND_INCR (k, p);	/* Skip the n.  */
+              succeed_n_p = false;
+	    }
+
+          continue;
+
+
+	case succeed_n:
+          /* Get to the number of times to succeed.  */
+          p += 2;		
+
+          /* Increment p past the n for when k != 0.  */
+          EXTRACT_NUMBER_AND_INCR (k, p);
+          if (k == 0)
+	    {
+              p -= 4;
+  	      succeed_n_p = true;  /* Spaghetti code alert.  */
+              goto handle_on_failure_jump;
+            }
+          continue;
+
+
+	case set_number_at:
+          p += 4;
+          continue;
+
+
+	case start_memory:
+        case stop_memory:
+	  p += 2;
+	  continue;
+
+
+	default:
+          abort (); /* We have listed all the cases.  */
+        } /* switch *p++ */
+
+      /* Getting here means we have found the possible starting
+         characters for one path of the pattern -- and that the empty
+         string does not match.  We need not follow this path further.
+         Instead, look at the next alternative (remembered on the
+         stack), or quit if no more.  The test at the top of the loop
+         does these things.  */
+      path_can_be_null = false;
+      p = pend;
+    } /* while p */
+
+  /* Set `can_be_null' for the last path (also the first path, if the
+     pattern is empty).  */
+  bufp->can_be_null |= path_can_be_null;
+
+ done:
+  RESET_FAIL_STACK ();
+  return 0;
+} /* re_compile_fastmap */
+
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
+   this memory for recording register information.  STARTS and ENDS
+   must be allocated using the malloc library routine, and must each
+   be at least NUM_REGS * sizeof (regoff_t) bytes long.
+
+   If NUM_REGS == 0, then subsequent matches should allocate their own
+   register data.
+
+   Unless this function is called, the first search or match using
+   PATTERN_BUFFER will allocate its own register data, without
+   freeing the old data.  */
+
+void
+re_set_registers (bufp, regs, num_regs, starts, ends)
+    struct re_pattern_buffer *bufp;
+    struct re_registers *regs;
+    unsigned num_regs;
+    regoff_t *starts, *ends;
+{
+  if (num_regs)
+    {
+      bufp->regs_allocated = REGS_REALLOCATE;
+      regs->num_regs = num_regs;
+      regs->start = starts;
+      regs->end = ends;
+    }
+  else
+    {
+      bufp->regs_allocated = REGS_UNALLOCATED;
+      regs->num_regs = 0;
+      regs->start = regs->end = (regoff_t *) 0;
+    }
+}
+
+
+/* Searching routines.  */
+
+/* Like re_search_2, below, but only one string is specified, and
+   doesn't let you say where to stop matching. */
+
+int
+re_search (bufp, string, size, startpos, range, regs)
+     struct re_pattern_buffer *bufp;
+     const char *string;
+     int size, startpos, range;
+     struct re_registers *regs;
+{
+  return re_search_2 (bufp, NULL, 0, string, size, startpos, range, 
+		      regs, size);
+}
+
+
+/* Using the compiled pattern in BUFP->buffer, first tries to match the
+   virtual concatenation of STRING1 and STRING2, starting first at index
+   STARTPOS, then at STARTPOS + 1, and so on.
+   
+   STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
+   
+   RANGE is how far to scan while trying to match.  RANGE = 0 means try
+   only at STARTPOS; in general, the last start tried is STARTPOS +
+   RANGE.
+   
+   In REGS, return the indices of the virtual concatenation of STRING1
+   and STRING2 that matched the entire BUFP->buffer and its contained
+   subexpressions.
+   
+   Do not consider matching one past the index STOP in the virtual
+   concatenation of STRING1 and STRING2.
+
+   We return either the position in the strings at which the match was
+   found, -1 if no match, or -2 if error (such as failure
+   stack overflow).  */
+
+int
+re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
+     struct re_pattern_buffer *bufp;
+     const char *string1, *string2;
+     int size1, size2;
+     int startpos;
+     int range;
+     struct re_registers *regs;
+     int stop;
+{
+  int val;
+  register char *fastmap = bufp->fastmap;
+  register char *translate = bufp->translate;
+  int total_size = size1 + size2;
+  int endpos = startpos + range;
+
+  /* Check for out-of-range STARTPOS.  */
+  if (startpos < 0 || startpos > total_size)
+    return -1;
+    
+  /* Fix up RANGE if it might eventually take us outside
+     the virtual concatenation of STRING1 and STRING2.  */
+  if (endpos < -1)
+    range = -1 - startpos;
+  else if (endpos > total_size)
+    range = total_size - startpos;
+
+  /* If the search isn't to be a backwards one, don't waste time in a
+     search for a pattern that must be anchored.  */
+  if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0)
+    {
+      if (startpos > 0)
+	return -1;
+      else
+	range = 1;
+    }
+
+  /* Update the fastmap now if not correct already.  */
+  if (fastmap && !bufp->fastmap_accurate)
+    if (re_compile_fastmap (bufp) == -2)
+      return -2;
+  
+  /* Loop through the string, looking for a place to start matching.  */
+  for (;;)
+    { 
+      /* If a fastmap is supplied, skip quickly over characters that
+         cannot be the start of a match.  If the pattern can match the
+         null string, however, we don't need to skip characters; we want
+         the first null string.  */
+      if (fastmap && startpos < total_size && !bufp->can_be_null)
+	{
+	  if (range > 0)	/* Searching forwards.  */
+	    {
+	      register const char *d;
+	      register int lim = 0;
+	      int irange = range;
+
+              if (startpos < size1 && startpos + range >= size1)
+                lim = range - (size1 - startpos);
+
+	      d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
+   
+              /* Written out as an if-else to avoid testing `translate'
+                 inside the loop.  */
+	      if (translate)
+                while (range > lim
+                       && !fastmap[(unsigned char)
+				   translate[(unsigned char) *d++]])
+                  range--;
+	      else
+                while (range > lim && !fastmap[(unsigned char) *d++])
+                  range--;
+
+	      startpos += irange - range;
+	    }
+	  else				/* Searching backwards.  */
+	    {
+	      register char c = (size1 == 0 || startpos >= size1
+                                 ? string2[startpos - size1] 
+                                 : string1[startpos]);
+
+	      if (!fastmap[(unsigned char) TRANSLATE (c)])
+		goto advance;
+	    }
+	}
+
+      /* If can't match the null string, and that's all we have left, fail.  */
+      if (range >= 0 && startpos == total_size && fastmap
+          && !bufp->can_be_null)
+	return -1;
+
+      val = re_match_2_internal (bufp, string1, size1, string2, size2,
+				 startpos, regs, stop);
+#ifndef REGEX_MALLOC
+#ifdef C_ALLOCA
+      alloca (0);
+#endif
+#endif
+
+      if (val >= 0)
+	return startpos;
+        
+      if (val == -2)
+	return -2;
+
+    advance:
+      if (!range) 
+        break;
+      else if (range > 0) 
+        {
+          range--; 
+          startpos++;
+        }
+      else
+        {
+          range++; 
+          startpos--;
+        }
+    }
+  return -1;
+} /* re_search_2 */
+
+
+/* Declarations and macros for re_match_2.  */
+
+static int bcmp_translate ();
+static boolean alt_match_null_string_p (),
+               common_op_match_null_string_p (),
+               group_match_null_string_p ();
+
+/* This converts PTR, a pointer into one of the search strings `string1'
+   and `string2' into an offset from the beginning of that string.  */
+#define POINTER_TO_OFFSET(ptr)			\
+  (FIRST_STRING_P (ptr)				\
+   ? ((regoff_t) ((ptr) - string1))		\
+   : ((regoff_t) ((ptr) - string2 + size1)))
+
+/* Macros for dealing with the split strings in re_match_2.  */
+
+#define MATCHING_IN_FIRST_STRING  (dend == end_match_1)
+
+/* Call before fetching a character with *d.  This switches over to
+   string2 if necessary.  */
+#define PREFETCH()							\
+  while (d == dend)						    	\
+    {									\
+      /* End of string2 => fail.  */					\
+      if (dend == end_match_2) 						\
+        goto fail;							\
+      /* End of string1 => advance to string2.  */ 			\
+      d = string2;						        \
+      dend = end_match_2;						\
+    }
+
+
+/* Test if at very beginning or at very end of the virtual concatenation
+   of `string1' and `string2'.  If only one string, it's `string2'.  */
+#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
+#define AT_STRINGS_END(d) ((d) == end2)	
+
+
+/* Test if D points to a character which is word-constituent.  We have
+   two special cases to check for: if past the end of string1, look at
+   the first character in string2; and if before the beginning of
+   string2, look at the last character in string1.  */
+#define WORDCHAR_P(d)							\
+  (SYNTAX ((d) == end1 ? *string2					\
+           : (d) == string2 - 1 ? *(end1 - 1) : *(d))			\
+   == Sword)
+
+/* Test if the character before D and the one at D differ with respect
+   to being word-constituent.  */
+#define AT_WORD_BOUNDARY(d)						\
+  (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)				\
+   || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
+
+
+/* Free everything we malloc.  */
+#ifdef MATCH_MAY_ALLOCATE
+#define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
+#define FREE_VARIABLES()						\
+  do {									\
+    REGEX_FREE_STACK (fail_stack.stack);				\
+    FREE_VAR (regstart);						\
+    FREE_VAR (regend);							\
+    FREE_VAR (old_regstart);						\
+    FREE_VAR (old_regend);						\
+    FREE_VAR (best_regstart);						\
+    FREE_VAR (best_regend);						\
+    FREE_VAR (reg_info);						\
+    FREE_VAR (reg_dummy);						\
+    FREE_VAR (reg_info_dummy);						\
+  } while (0)
+#else
+#define FREE_VARIABLES() ((void)0) /* Do nothing!  But inhibit gcc warning.  */
+#endif /* not MATCH_MAY_ALLOCATE */
+
+/* These values must meet several constraints.  They must not be valid
+   register values; since we have a limit of 255 registers (because
+   we use only one byte in the pattern for the register number), we can
+   use numbers larger than 255.  They must differ by 1, because of
+   NUM_FAILURE_ITEMS above.  And the value for the lowest register must
+   be larger than the value for the highest register, so we do not try
+   to actually save any registers when none are active.  */
+#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
+#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
+
+
+/* Matching routines.  */
+
+#ifndef emacs   /* Emacs never uses this.  */
+/* re_match is like re_match_2 except it takes only a single string.  */
+
+int
+re_match (bufp, string, size, pos, regs)
+     struct re_pattern_buffer *bufp;
+     const char *string;
+     int size, pos;
+     struct re_registers *regs;
+{
+  int result = re_match_2_internal (bufp, NULL, 0, string, size,
+				    pos, regs, size);
+  alloca (0);
+  return result;
+}
+#endif /* not emacs */
+
+
+/* re_match_2 matches the compiled pattern in BUFP against the
+   the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
+   and SIZE2, respectively).  We start matching at POS, and stop
+   matching at STOP.
+   
+   If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
+   store offsets for the substring each group matched in REGS.  See the
+   documentation for exactly how many groups we fill.
+
+   We return -1 if no match, -2 if an internal error (such as the
+   failure stack overflowing).  Otherwise, we return the length of the
+   matched substring.  */
+
+int
+re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+     struct re_pattern_buffer *bufp;
+     const char *string1, *string2;
+     int size1, size2;
+     int pos;
+     struct re_registers *regs;
+     int stop;
+{
+  int result = re_match_2_internal (bufp, string1, size1, string2, size2,
+				    pos, regs, stop);
+  alloca (0);
+  return result;
+}
+
+/* This is a separate function so that we can force an alloca cleanup
+   afterwards.  */
+static int
+re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
+     struct re_pattern_buffer *bufp;
+     const char *string1, *string2;
+     int size1, size2;
+     int pos;
+     struct re_registers *regs;
+     int stop;
+{
+  /* General temporaries.  */
+  int mcnt;
+  unsigned char *p1;
+
+  /* Just past the end of the corresponding string.  */
+  const char *end1, *end2;
+
+  /* Pointers into string1 and string2, just past the last characters in
+     each to consider matching.  */
+  const char *end_match_1, *end_match_2;
+
+  /* Where we are in the data, and the end of the current string.  */
+  const char *d, *dend;
+  
+  /* Where we are in the pattern, and the end of the pattern.  */
+  unsigned char *p = bufp->buffer;
+  register unsigned char *pend = p + bufp->used;
+
+  /* Mark the opcode just after a start_memory, so we can test for an
+     empty subpattern when we get to the stop_memory.  */
+  unsigned char *just_past_start_mem = 0;
+
+  /* We use this to map every character in the string.  */
+  char *translate = bufp->translate;
+
+  /* Failure point stack.  Each place that can handle a failure further
+     down the line pushes a failure point on this stack.  It consists of
+     restart, regend, and reg_info for all registers corresponding to
+     the subexpressions we're currently inside, plus the number of such
+     registers, and, finally, two char *'s.  The first char * is where
+     to resume scanning the pattern; the second one is where to resume
+     scanning the strings.  If the latter is zero, the failure point is
+     a ``dummy''; if a failure happens and the failure point is a dummy,
+     it gets discarded and the next next one is tried.  */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global.  */
+  fail_stack_type fail_stack;
+#endif
+#ifdef DEBUG
+  static unsigned failure_id = 0;
+  unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
+#endif
+
+  /* This holds the pointer to the failure stack, when
+     it is allocated relocatably.  */
+  fail_stack_elt_t *failure_stack_ptr;
+
+  /* We fill all the registers internally, independent of what we
+     return, for use in backreferences.  The number here includes
+     an element for register zero.  */
+  unsigned num_regs = bufp->re_nsub + 1;
+  
+  /* The currently active registers.  */
+  unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+  unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+
+  /* Information on the contents of registers. These are pointers into
+     the input strings; they record just what was matched (on this
+     attempt) by a subexpression part of the pattern, that is, the
+     regnum-th regstart pointer points to where in the pattern we began
+     matching and the regnum-th regend points to right after where we
+     stopped matching the regnum-th subexpression.  (The zeroth register
+     keeps track of what the whole pattern matches.)  */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
+  const char **regstart, **regend;
+#endif
+
+  /* If a group that's operated upon by a repetition operator fails to
+     match anything, then the register for its start will need to be
+     restored because it will have been set to wherever in the string we
+     are when we last see its open-group operator.  Similarly for a
+     register's end.  */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
+  const char **old_regstart, **old_regend;
+#endif
+
+  /* The is_active field of reg_info helps us keep track of which (possibly
+     nested) subexpressions we are currently in. The matched_something
+     field of reg_info[reg_num] helps us tell whether or not we have
+     matched any of the pattern so far this time through the reg_num-th
+     subexpression.  These two fields get reset each time through any
+     loop their register is in.  */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global.  */
+  register_info_type *reg_info; 
+#endif
+
+  /* The following record the register info as found in the above
+     variables when we find a match better than any we've seen before. 
+     This happens as we backtrack through the failure points, which in
+     turn happens only if we have not yet matched the entire string. */
+  unsigned best_regs_set = false;
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
+  const char **best_regstart, **best_regend;
+#endif
+  
+  /* Logically, this is `best_regend[0]'.  But we don't want to have to
+     allocate space for that if we're not allocating space for anything
+     else (see below).  Also, we never need info about register 0 for
+     any of the other register vectors, and it seems rather a kludge to
+     treat `best_regend' differently than the rest.  So we keep track of
+     the end of the best match so far in a separate variable.  We
+     initialize this to NULL so that when we backtrack the first time
+     and need to test it, it's not garbage.  */
+  const char *match_end = NULL;
+
+  /* This helps SET_REGS_MATCHED avoid doing redundant work.  */
+  int set_regs_matched_done = 0;
+
+  /* Used when we pop values we don't care about.  */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
+  const char **reg_dummy;
+  register_info_type *reg_info_dummy;
+#endif
+
+#ifdef DEBUG
+  /* Counts the total number of registers pushed.  */
+  unsigned num_regs_pushed = 0; 	
+#endif
+
+  DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
+  
+  INIT_FAIL_STACK ();
+  
+#ifdef MATCH_MAY_ALLOCATE
+  /* Do not bother to initialize all the register variables if there are
+     no groups in the pattern, as it takes a fair amount of time.  If
+     there are groups, we include space for register 0 (the whole
+     pattern), even though we never use it, since it simplifies the
+     array indexing.  We should fix this.  */
+  if (bufp->re_nsub)
+    {
+      regstart = REGEX_TALLOC (num_regs, const char *);
+      regend = REGEX_TALLOC (num_regs, const char *);
+      old_regstart = REGEX_TALLOC (num_regs, const char *);
+      old_regend = REGEX_TALLOC (num_regs, const char *);
+      best_regstart = REGEX_TALLOC (num_regs, const char *);
+      best_regend = REGEX_TALLOC (num_regs, const char *);
+      reg_info = REGEX_TALLOC (num_regs, register_info_type);
+      reg_dummy = REGEX_TALLOC (num_regs, const char *);
+      reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type);
+
+      if (!(regstart && regend && old_regstart && old_regend && reg_info 
+            && best_regstart && best_regend && reg_dummy && reg_info_dummy)) 
+        {
+          FREE_VARIABLES ();
+          return -2;
+        }
+    }
+  else
+    {
+      /* We must initialize all our variables to NULL, so that
+         `FREE_VARIABLES' doesn't try to free them.  */
+      regstart = regend = old_regstart = old_regend = best_regstart
+        = best_regend = reg_dummy = NULL;
+      reg_info = reg_info_dummy = (register_info_type *) NULL;
+    }
+#endif /* MATCH_MAY_ALLOCATE */
+
+  /* The starting position is bogus.  */
+  if (pos < 0 || pos > size1 + size2)
+    {
+      FREE_VARIABLES ();
+      return -1;
+    }
+    
+  /* Initialize subexpression text positions to -1 to mark ones that no
+     start_memory/stop_memory has been seen for. Also initialize the
+     register information struct.  */
+  for (mcnt = 1; mcnt < num_regs; mcnt++)
+    {
+      regstart[mcnt] = regend[mcnt] 
+        = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
+        
+      REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
+      IS_ACTIVE (reg_info[mcnt]) = 0;
+      MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+      EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+    }
+  
+  /* We move `string1' into `string2' if the latter's empty -- but not if
+     `string1' is null.  */
+  if (size2 == 0 && string1 != NULL)
+    {
+      string2 = string1;
+      size2 = size1;
+      string1 = 0;
+      size1 = 0;
+    }
+  end1 = string1 + size1;
+  end2 = string2 + size2;
+
+  /* Compute where to stop matching, within the two strings.  */
+  if (stop <= size1)
+    {
+      end_match_1 = string1 + stop;
+      end_match_2 = string2;
+    }
+  else
+    {
+      end_match_1 = end1;
+      end_match_2 = string2 + stop - size1;
+    }
+
+  /* `p' scans through the pattern as `d' scans through the data. 
+     `dend' is the end of the input string that `d' points within.  `d'
+     is advanced into the following input string whenever necessary, but
+     this happens before fetching; therefore, at the beginning of the
+     loop, `d' can be pointing at the end of a string, but it cannot
+     equal `string2'.  */
+  if (size1 > 0 && pos <= size1)
+    {
+      d = string1 + pos;
+      dend = end_match_1;
+    }
+  else
+    {
+      d = string2 + pos - size1;
+      dend = end_match_2;
+    }
+
+  DEBUG_PRINT1 ("The compiled pattern is: ");
+  DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
+  DEBUG_PRINT1 ("The string to match is: `");
+  DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
+  DEBUG_PRINT1 ("'\n");
+  
+  /* This loops over pattern commands.  It exits by returning from the
+     function if the match is complete, or it drops through if the match
+     fails at this starting point in the input data.  */
+  for (;;)
+    {
+      DEBUG_PRINT2 ("\n0x%x: ", p);
+
+      if (p == pend)
+	{ /* End of pattern means we might have succeeded.  */
+          DEBUG_PRINT1 ("end of pattern ... ");
+          
+	  /* If we haven't matched the entire string, and we want the
+             longest match, try backtracking.  */
+          if (d != end_match_2)
+	    {
+	      /* 1 if this match ends in the same string (string1 or string2)
+		 as the best previous match.  */
+	      boolean same_str_p = (FIRST_STRING_P (match_end) 
+				    == MATCHING_IN_FIRST_STRING);
+	      /* 1 if this match is the best seen so far.  */
+	      boolean best_match_p;
+
+	      /* AIX compiler got confused when this was combined
+		 with the previous declaration.  */
+	      if (same_str_p)
+		best_match_p = d > match_end;
+	      else
+		best_match_p = !MATCHING_IN_FIRST_STRING;
+
+              DEBUG_PRINT1 ("backtracking.\n");
+              
+              if (!FAIL_STACK_EMPTY ())
+                { /* More failure points to try.  */
+
+                  /* If exceeds best match so far, save it.  */
+                  if (!best_regs_set || best_match_p)
+                    {
+                      best_regs_set = true;
+                      match_end = d;
+                      
+                      DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
+                      
+                      for (mcnt = 1; mcnt < num_regs; mcnt++)
+                        {
+                          best_regstart[mcnt] = regstart[mcnt];
+                          best_regend[mcnt] = regend[mcnt];
+                        }
+                    }
+                  goto fail;	       
+                }
+
+              /* If no failure points, don't restore garbage.  And if
+                 last match is real best match, don't restore second
+                 best one. */
+              else if (best_regs_set && !best_match_p)
+                {
+  	        restore_best_regs:
+                  /* Restore best match.  It may happen that `dend ==
+                     end_match_1' while the restored d is in string2.
+                     For example, the pattern `x.*y.*z' against the
+                     strings `x-' and `y-z-', if the two strings are
+                     not consecutive in memory.  */
+                  DEBUG_PRINT1 ("Restoring best registers.\n");
+                  
+                  d = match_end;
+                  dend = ((d >= string1 && d <= end1)
+		           ? end_match_1 : end_match_2);
+
+		  for (mcnt = 1; mcnt < num_regs; mcnt++)
+		    {
+		      regstart[mcnt] = best_regstart[mcnt];
+		      regend[mcnt] = best_regend[mcnt];
+		    }
+                }
+            } /* d != end_match_2 */
+
+	succeed_label:
+          DEBUG_PRINT1 ("Accepting match.\n");
+
+          /* If caller wants register contents data back, do it.  */
+          if (regs && !bufp->no_sub)
+	    {
+              /* Have the register data arrays been allocated?  */
+              if (bufp->regs_allocated == REGS_UNALLOCATED)
+                { /* No.  So allocate them with malloc.  We need one
+                     extra element beyond `num_regs' for the `-1' marker
+                     GNU code uses.  */
+                  regs->num_regs = MAX (RE_NREGS, num_regs + 1);
+                  regs->start = TALLOC (regs->num_regs, regoff_t);
+                  regs->end = TALLOC (regs->num_regs, regoff_t);
+                  if (regs->start == NULL || regs->end == NULL)
+		    {
+		      FREE_VARIABLES ();
+		      return -2;
+		    }
+                  bufp->regs_allocated = REGS_REALLOCATE;
+                }
+              else if (bufp->regs_allocated == REGS_REALLOCATE)
+                { /* Yes.  If we need more elements than were already
+                     allocated, reallocate them.  If we need fewer, just
+                     leave it alone.  */
+                  if (regs->num_regs < num_regs + 1)
+                    {
+                      regs->num_regs = num_regs + 1;
+                      RETALLOC (regs->start, regs->num_regs, regoff_t);
+                      RETALLOC (regs->end, regs->num_regs, regoff_t);
+                      if (regs->start == NULL || regs->end == NULL)
+			{
+			  FREE_VARIABLES ();
+			  return -2;
+			}
+                    }
+                }
+              else
+		{
+		  /* These braces fend off a "empty body in an else-statement"
+		     warning under GCC when assert expands to nothing.  */
+		  assert (bufp->regs_allocated == REGS_FIXED);
+		}
+
+              /* Convert the pointer data in `regstart' and `regend' to
+                 indices.  Register zero has to be set differently,
+                 since we haven't kept track of any info for it.  */
+              if (regs->num_regs > 0)
+                {
+                  regs->start[0] = pos;
+                  regs->end[0] = (MATCHING_IN_FIRST_STRING
+				  ? ((regoff_t) (d - string1))
+			          : ((regoff_t) (d - string2 + size1)));
+                }
+              
+              /* Go through the first `min (num_regs, regs->num_regs)'
+                 registers, since that is all we initialized.  */
+	      for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++)
+		{
+                  if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
+                    regs->start[mcnt] = regs->end[mcnt] = -1;
+                  else
+                    {
+		      regs->start[mcnt]
+			= (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]);
+                      regs->end[mcnt]
+			= (regoff_t) POINTER_TO_OFFSET (regend[mcnt]);
+                    }
+		}
+              
+              /* If the regs structure we return has more elements than
+                 were in the pattern, set the extra elements to -1.  If
+                 we (re)allocated the registers, this is the case,
+                 because we always allocate enough to have at least one
+                 -1 at the end.  */
+              for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++)
+                regs->start[mcnt] = regs->end[mcnt] = -1;
+	    } /* regs && !bufp->no_sub */
+
+          DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
+                        nfailure_points_pushed, nfailure_points_popped,
+                        nfailure_points_pushed - nfailure_points_popped);
+          DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
+
+          mcnt = d - pos - (MATCHING_IN_FIRST_STRING 
+			    ? string1 
+			    : string2 - size1);
+
+          DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
+
+          FREE_VARIABLES ();
+          return mcnt;
+        }
+
+      /* Otherwise match next pattern command.  */
+      switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
+	{
+        /* Ignore these.  Used to ignore the n of succeed_n's which
+           currently have n == 0.  */
+        case no_op:
+          DEBUG_PRINT1 ("EXECUTING no_op.\n");
+          break;
+
+	case succeed:
+          DEBUG_PRINT1 ("EXECUTING succeed.\n");
+	  goto succeed_label;
+
+        /* Match the next n pattern characters exactly.  The following
+           byte in the pattern defines n, and the n bytes after that
+           are the characters to match.  */
+	case exactn:
+	  mcnt = *p++;
+          DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
+
+          /* This is written out as an if-else so we don't waste time
+             testing `translate' inside the loop.  */
+          if (translate)
+	    {
+	      do
+		{
+		  PREFETCH ();
+		  if (translate[(unsigned char) *d++] != (char) *p++)
+                    goto fail;
+		}
+	      while (--mcnt);
+	    }
+	  else
+	    {
+	      do
+		{
+		  PREFETCH ();
+		  if (*d++ != (char) *p++) goto fail;
+		}
+	      while (--mcnt);
+	    }
+	  SET_REGS_MATCHED ();
+          break;
+
+
+        /* Match any character except possibly a newline or a null.  */
+	case anychar:
+          DEBUG_PRINT1 ("EXECUTING anychar.\n");
+
+          PREFETCH ();
+
+          if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
+              || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
+	    goto fail;
+
+          SET_REGS_MATCHED ();
+          DEBUG_PRINT2 ("  Matched `%d'.\n", *d);
+          d++;
+	  break;
+
+
+	case charset:
+	case charset_not:
+	  {
+	    register unsigned char c;
+	    boolean not = (re_opcode_t) *(p - 1) == charset_not;
+
+            DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
+
+	    PREFETCH ();
+	    c = TRANSLATE (*d); /* The character to match.  */
+
+            /* Cast to `unsigned' instead of `unsigned char' in case the
+               bit list is a full 32 bytes long.  */
+	    if (c < (unsigned) (*p * BYTEWIDTH)
+		&& p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+	      not = !not;
+
+	    p += 1 + *p;
+
+	    if (!not) goto fail;
+            
+	    SET_REGS_MATCHED ();
+            d++;
+	    break;
+	  }
+
+
+        /* The beginning of a group is represented by start_memory.
+           The arguments are the register number in the next byte, and the
+           number of groups inner to this one in the next.  The text
+           matched within the group is recorded (in the internal
+           registers data structure) under the register number.  */
+        case start_memory:
+	  DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
+
+          /* Find out if this group can match the empty string.  */
+	  p1 = p;		/* To send to group_match_null_string_p.  */
+          
+          if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
+            REG_MATCH_NULL_STRING_P (reg_info[*p]) 
+              = group_match_null_string_p (&p1, pend, reg_info);
+
+          /* Save the position in the string where we were the last time
+             we were at this open-group operator in case the group is
+             operated upon by a repetition operator, e.g., with `(a*)*b'
+             against `ab'; then we want to ignore where we are now in
+             the string in case this attempt to match fails.  */
+          old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+                             ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
+                             : regstart[*p];
+	  DEBUG_PRINT2 ("  old_regstart: %d\n", 
+			 POINTER_TO_OFFSET (old_regstart[*p]));
+
+          regstart[*p] = d;
+	  DEBUG_PRINT2 ("  regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
+
+          IS_ACTIVE (reg_info[*p]) = 1;
+          MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+	  /* Clear this whenever we change the register activity status.  */
+	  set_regs_matched_done = 0;
+          
+          /* This is the new highest active register.  */
+          highest_active_reg = *p;
+          
+          /* If nothing was active before, this is the new lowest active
+             register.  */
+          if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+            lowest_active_reg = *p;
+
+          /* Move past the register number and inner group count.  */
+          p += 2;
+	  just_past_start_mem = p;
+
+          break;
+
+
+        /* The stop_memory opcode represents the end of a group.  Its
+           arguments are the same as start_memory's: the register
+           number, and the number of inner groups.  */
+	case stop_memory:
+	  DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
+             
+          /* We need to save the string position the last time we were at
+             this close-group operator in case the group is operated
+             upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
+             against `aba'; then we want to ignore where we are now in
+             the string in case this attempt to match fails.  */
+          old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+                           ? REG_UNSET (regend[*p]) ? d : regend[*p]
+			   : regend[*p];
+	  DEBUG_PRINT2 ("      old_regend: %d\n", 
+			 POINTER_TO_OFFSET (old_regend[*p]));
+
+          regend[*p] = d;
+	  DEBUG_PRINT2 ("      regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
+
+          /* This register isn't active anymore.  */
+          IS_ACTIVE (reg_info[*p]) = 0;
+
+	  /* Clear this whenever we change the register activity status.  */
+	  set_regs_matched_done = 0;
+
+          /* If this was the only register active, nothing is active
+             anymore.  */
+          if (lowest_active_reg == highest_active_reg)
+            {
+              lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+              highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+            }
+          else
+            { /* We must scan for the new highest active register, since
+                 it isn't necessarily one less than now: consider
+                 (a(b)c(d(e)f)g).  When group 3 ends, after the f), the
+                 new highest active register is 1.  */
+              unsigned char r = *p - 1;
+              while (r > 0 && !IS_ACTIVE (reg_info[r]))
+                r--;
+              
+              /* If we end up at register zero, that means that we saved
+                 the registers as the result of an `on_failure_jump', not
+                 a `start_memory', and we jumped to past the innermost
+                 `stop_memory'.  For example, in ((.)*) we save
+                 registers 1 and 2 as a result of the *, but when we pop
+                 back to the second ), we are at the stop_memory 1.
+                 Thus, nothing is active.  */
+	      if (r == 0)
+                {
+                  lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+                  highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+                }
+              else
+                highest_active_reg = r;
+            }
+          
+          /* If just failed to match something this time around with a
+             group that's operated on by a repetition operator, try to
+             force exit from the ``loop'', and restore the register
+             information for this group that we had before trying this
+             last match.  */
+          if ((!MATCHED_SOMETHING (reg_info[*p])
+               || just_past_start_mem == p - 1)
+	      && (p + 2) < pend)              
+            {
+              boolean is_a_jump_n = false;
+              
+              p1 = p + 2;
+              mcnt = 0;
+              switch ((re_opcode_t) *p1++)
+                {
+                  case jump_n:
+		    is_a_jump_n = true;
+                  case pop_failure_jump:
+		  case maybe_pop_jump:
+		  case jump:
+		  case dummy_failure_jump:
+                    EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+		    if (is_a_jump_n)
+		      p1 += 2;
+                    break;
+                  
+                  default:
+                    /* do nothing */ ;
+                }
+	      p1 += mcnt;
+        
+              /* If the next operation is a jump backwards in the pattern
+	         to an on_failure_jump right before the start_memory
+                 corresponding to this stop_memory, exit from the loop
+                 by forcing a failure after pushing on the stack the
+                 on_failure_jump's jump in the pattern, and d.  */
+              if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
+                  && (re_opcode_t) p1[3] == start_memory && p1[4] == *p)
+		{
+                  /* If this group ever matched anything, then restore
+                     what its registers were before trying this last
+                     failed match, e.g., with `(a*)*b' against `ab' for
+                     regstart[1], and, e.g., with `((a*)*(b*)*)*'
+                     against `aba' for regend[3].
+                     
+                     Also restore the registers for inner groups for,
+                     e.g., `((a*)(b*))*' against `aba' (register 3 would
+                     otherwise get trashed).  */
+                     
+                  if (EVER_MATCHED_SOMETHING (reg_info[*p]))
+		    {
+		      unsigned r; 
+        
+                      EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
+                      
+		      /* Restore this and inner groups' (if any) registers.  */
+                      for (r = *p; r < *p + *(p + 1); r++)
+                        {
+                          regstart[r] = old_regstart[r];
+
+                          /* xx why this test?  */
+                          if (old_regend[r] >= regstart[r])
+                            regend[r] = old_regend[r];
+                        }     
+                    }
+		  p1++;
+                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+                  PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
+
+                  goto fail;
+                }
+            }
+          
+          /* Move past the register number and the inner group count.  */
+          p += 2;
+          break;
+
+
+	/* \<digit> has been turned into a `duplicate' command which is
+           followed by the numeric value of <digit> as the register number.  */
+        case duplicate:
+	  {
+	    register const char *d2, *dend2;
+	    int regno = *p++;   /* Get which register to match against.  */
+	    DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
+
+	    /* Can't back reference a group which we've never matched.  */
+            if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
+              goto fail;
+              
+            /* Where in input to try to start matching.  */
+            d2 = regstart[regno];
+            
+            /* Where to stop matching; if both the place to start and
+               the place to stop matching are in the same string, then
+               set to the place to stop, otherwise, for now have to use
+               the end of the first string.  */
+
+            dend2 = ((FIRST_STRING_P (regstart[regno]) 
+		      == FIRST_STRING_P (regend[regno]))
+		     ? regend[regno] : end_match_1);
+	    for (;;)
+	      {
+		/* If necessary, advance to next segment in register
+                   contents.  */
+		while (d2 == dend2)
+		  {
+		    if (dend2 == end_match_2) break;
+		    if (dend2 == regend[regno]) break;
+
+                    /* End of string1 => advance to string2. */
+                    d2 = string2;
+                    dend2 = regend[regno];
+		  }
+		/* At end of register contents => success */
+		if (d2 == dend2) break;
+
+		/* If necessary, advance to next segment in data.  */
+		PREFETCH ();
+
+		/* How many characters left in this segment to match.  */
+		mcnt = dend - d;
+                
+		/* Want how many consecutive characters we can match in
+                   one shot, so, if necessary, adjust the count.  */
+                if (mcnt > dend2 - d2)
+		  mcnt = dend2 - d2;
+                  
+		/* Compare that many; failure if mismatch, else move
+                   past them.  */
+		if (translate 
+                    ? bcmp_translate (d, d2, mcnt, translate) 
+                    : bcmp (d, d2, mcnt))
+		  goto fail;
+		d += mcnt, d2 += mcnt;
+
+		/* Do this because we've match some characters.  */
+		SET_REGS_MATCHED ();
+	      }
+	  }
+	  break;
+
+
+        /* begline matches the empty string at the beginning of the string
+           (unless `not_bol' is set in `bufp'), and, if
+           `newline_anchor' is set, after newlines.  */
+	case begline:
+          DEBUG_PRINT1 ("EXECUTING begline.\n");
+          
+          if (AT_STRINGS_BEG (d))
+            {
+              if (!bufp->not_bol) break;
+            }
+          else if (d[-1] == '\n' && bufp->newline_anchor)
+            {
+              break;
+            }
+          /* In all other cases, we fail.  */
+          goto fail;
+
+
+        /* endline is the dual of begline.  */
+	case endline:
+          DEBUG_PRINT1 ("EXECUTING endline.\n");
+
+          if (AT_STRINGS_END (d))
+            {
+              if (!bufp->not_eol) break;
+            }
+          
+          /* We have to ``prefetch'' the next character.  */
+          else if ((d == end1 ? *string2 : *d) == '\n'
+                   && bufp->newline_anchor)
+            {
+              break;
+            }
+          goto fail;
+
+
+	/* Match at the very beginning of the data.  */
+        case begbuf:
+          DEBUG_PRINT1 ("EXECUTING begbuf.\n");
+          if (AT_STRINGS_BEG (d))
+            break;
+          goto fail;
+
+
+	/* Match at the very end of the data.  */
+        case endbuf:
+          DEBUG_PRINT1 ("EXECUTING endbuf.\n");
+	  if (AT_STRINGS_END (d))
+	    break;
+          goto fail;
+
+
+        /* on_failure_keep_string_jump is used to optimize `.*\n'.  It
+           pushes NULL as the value for the string on the stack.  Then
+           `pop_failure_point' will keep the current value for the
+           string, instead of restoring it.  To see why, consider
+           matching `foo\nbar' against `.*\n'.  The .* matches the foo;
+           then the . fails against the \n.  But the next thing we want
+           to do is match the \n against the \n; if we restored the
+           string value, we would be back at the foo.
+           
+           Because this is used only in specific cases, we don't need to
+           check all the things that `on_failure_jump' does, to make
+           sure the right things get saved on the stack.  Hence we don't
+           share its code.  The only reason to push anything on the
+           stack at all is that otherwise we would have to change
+           `anychar's code to do something besides goto fail in this
+           case; that seems worse than this.  */
+        case on_failure_keep_string_jump:
+          DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
+          
+          EXTRACT_NUMBER_AND_INCR (mcnt, p);
+          DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
+
+          PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
+          break;
+
+
+	/* Uses of on_failure_jump:
+        
+           Each alternative starts with an on_failure_jump that points
+           to the beginning of the next alternative.  Each alternative
+           except the last ends with a jump that in effect jumps past
+           the rest of the alternatives.  (They really jump to the
+           ending jump of the following alternative, because tensioning
+           these jumps is a hassle.)
+
+           Repeats start with an on_failure_jump that points past both
+           the repetition text and either the following jump or
+           pop_failure_jump back to this on_failure_jump.  */
+	case on_failure_jump:
+        on_failure:
+          DEBUG_PRINT1 ("EXECUTING on_failure_jump");
+
+          EXTRACT_NUMBER_AND_INCR (mcnt, p);
+          DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
+
+          /* If this on_failure_jump comes right before a group (i.e.,
+             the original * applied to a group), save the information
+             for that group and all inner ones, so that if we fail back
+             to this point, the group's information will be correct.
+             For example, in \(a*\)*\1, we need the preceding group,
+             and in \(\(a*\)b*\)\2, we need the inner group.  */
+
+          /* We can't use `p' to check ahead because we push
+             a failure point to `p + mcnt' after we do this.  */
+          p1 = p;
+
+          /* We need to skip no_op's before we look for the
+             start_memory in case this on_failure_jump is happening as
+             the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
+             against aba.  */
+          while (p1 < pend && (re_opcode_t) *p1 == no_op)
+            p1++;
+
+          if (p1 < pend && (re_opcode_t) *p1 == start_memory)
+            {
+              /* We have a new highest active register now.  This will
+                 get reset at the start_memory we are about to get to,
+                 but we will have saved all the registers relevant to
+                 this repetition op, as described above.  */
+              highest_active_reg = *(p1 + 1) + *(p1 + 2);
+              if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+                lowest_active_reg = *(p1 + 1);
+            }
+
+          DEBUG_PRINT1 (":\n");
+          PUSH_FAILURE_POINT (p + mcnt, d, -2);
+          break;
+
+
+        /* A smart repeat ends with `maybe_pop_jump'.
+	   We change it to either `pop_failure_jump' or `jump'.  */
+        case maybe_pop_jump:
+          EXTRACT_NUMBER_AND_INCR (mcnt, p);
+          DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
+          {
+	    register unsigned char *p2 = p;
+
+            /* Compare the beginning of the repeat with what in the
+               pattern follows its end. If we can establish that there
+               is nothing that they would both match, i.e., that we
+               would have to backtrack because of (as in, e.g., `a*a')
+               then we can change to pop_failure_jump, because we'll
+               never have to backtrack.
+               
+               This is not true in the case of alternatives: in
+               `(a|ab)*' we do need to backtrack to the `ab' alternative
+               (e.g., if the string was `ab').  But instead of trying to
+               detect that here, the alternative has put on a dummy
+               failure point which is what we will end up popping.  */
+
+	    /* Skip over open/close-group commands.
+	       If what follows this loop is a ...+ construct,
+	       look at what begins its body, since we will have to
+	       match at least one of that.  */
+	    while (1)
+	      {
+		if (p2 + 2 < pend
+		    && ((re_opcode_t) *p2 == stop_memory
+			|| (re_opcode_t) *p2 == start_memory))
+		  p2 += 3;
+		else if (p2 + 6 < pend
+			 && (re_opcode_t) *p2 == dummy_failure_jump)
+		  p2 += 6;
+		else
+		  break;
+	      }
+
+	    p1 = p + mcnt;
+	    /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
+	       to the `maybe_finalize_jump' of this case.  Examine what 
+	       follows.  */
+
+            /* If we're at the end of the pattern, we can change.  */
+            if (p2 == pend)
+	      {
+		/* Consider what happens when matching ":\(.*\)"
+		   against ":/".  I don't really understand this code
+		   yet.  */
+  	        p[-3] = (unsigned char) pop_failure_jump;
+                DEBUG_PRINT1
+                  ("  End of pattern: change to `pop_failure_jump'.\n");
+              }
+
+            else if ((re_opcode_t) *p2 == exactn
+		     || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
+	      {
+		register unsigned char c
+                  = *p2 == (unsigned char) endline ? '\n' : p2[2];
+
+                if ((re_opcode_t) p1[3] == exactn && p1[5] != c)
+                  {
+  		    p[-3] = (unsigned char) pop_failure_jump;
+                    DEBUG_PRINT3 ("  %c != %c => pop_failure_jump.\n",
+                                  c, p1[5]);
+                  }
+                  
+		else if ((re_opcode_t) p1[3] == charset
+			 || (re_opcode_t) p1[3] == charset_not)
+		  {
+		    int not = (re_opcode_t) p1[3] == charset_not;
+                    
+		    if (c < (unsigned char) (p1[4] * BYTEWIDTH)
+			&& p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+		      not = !not;
+
+                    /* `not' is equal to 1 if c would match, which means
+                        that we can't change to pop_failure_jump.  */
+		    if (!not)
+                      {
+  		        p[-3] = (unsigned char) pop_failure_jump;
+                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
+                      }
+		  }
+	      }
+            else if ((re_opcode_t) *p2 == charset)
+	      {
+#ifdef DEBUG
+		register unsigned char c
+                  = *p2 == (unsigned char) endline ? '\n' : p2[2];
+#endif
+
+                if ((re_opcode_t) p1[3] == exactn
+		    && ! ((int) p2[1] * BYTEWIDTH > (int) p1[4]
+			  && (p2[1 + p1[4] / BYTEWIDTH]
+			      & (1 << (p1[4] % BYTEWIDTH)))))
+                  {
+  		    p[-3] = (unsigned char) pop_failure_jump;
+                    DEBUG_PRINT3 ("  %c != %c => pop_failure_jump.\n",
+                                  c, p1[5]);
+                  }
+                  
+		else if ((re_opcode_t) p1[3] == charset_not)
+		  {
+		    int idx;
+		    /* We win if the charset_not inside the loop
+		       lists every character listed in the charset after.  */
+		    for (idx = 0; idx < (int) p2[1]; idx++)
+		      if (! (p2[2 + idx] == 0
+			     || (idx < (int) p1[4]
+				 && ((p2[2 + idx] & ~ p1[5 + idx]) == 0))))
+			break;
+
+		    if (idx == p2[1])
+                      {
+  		        p[-3] = (unsigned char) pop_failure_jump;
+                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
+                      }
+		  }
+		else if ((re_opcode_t) p1[3] == charset)
+		  {
+		    int idx;
+		    /* We win if the charset inside the loop
+		       has no overlap with the one after the loop.  */
+		    for (idx = 0;
+			 idx < (int) p2[1] && idx < (int) p1[4];
+			 idx++)
+		      if ((p2[2 + idx] & p1[5 + idx]) != 0)
+			break;
+
+		    if (idx == p2[1] || idx == p1[4])
+                      {
+  		        p[-3] = (unsigned char) pop_failure_jump;
+                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
+                      }
+		  }
+	      }
+	  }
+	  p -= 2;		/* Point at relative address again.  */
+	  if ((re_opcode_t) p[-1] != pop_failure_jump)
+	    {
+	      p[-1] = (unsigned char) jump;
+              DEBUG_PRINT1 ("  Match => jump.\n");
+	      goto unconditional_jump;
+	    }
+        /* Note fall through.  */
+
+
+	/* The end of a simple repeat has a pop_failure_jump back to
+           its matching on_failure_jump, where the latter will push a
+           failure point.  The pop_failure_jump takes off failure
+           points put on by this pop_failure_jump's matching
+           on_failure_jump; we got through the pattern to here from the
+           matching on_failure_jump, so didn't fail.  */
+        case pop_failure_jump:
+          {
+            /* We need to pass separate storage for the lowest and
+               highest registers, even though we don't care about the
+               actual values.  Otherwise, we will restore only one
+               register from the stack, since lowest will == highest in
+               `pop_failure_point'.  */
+            unsigned dummy_low_reg, dummy_high_reg;
+            unsigned char *pdummy;
+            const char *sdummy;
+
+            DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
+            POP_FAILURE_POINT (sdummy, pdummy,
+                               dummy_low_reg, dummy_high_reg,
+                               reg_dummy, reg_dummy, reg_info_dummy);
+          }
+          /* Note fall through.  */
+
+          
+        /* Unconditionally jump (without popping any failure points).  */
+        case jump:
+	unconditional_jump:
+	  EXTRACT_NUMBER_AND_INCR (mcnt, p);	/* Get the amount to jump.  */
+          DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
+	  p += mcnt;				/* Do the jump.  */
+          DEBUG_PRINT2 ("(to 0x%x).\n", p);
+	  break;
+
+	
+        /* We need this opcode so we can detect where alternatives end
+           in `group_match_null_string_p' et al.  */
+        case jump_past_alt:
+          DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
+          goto unconditional_jump;
+
+
+        /* Normally, the on_failure_jump pushes a failure point, which
+           then gets popped at pop_failure_jump.  We will end up at
+           pop_failure_jump, also, and with a pattern of, say, `a+', we
+           are skipping over the on_failure_jump, so we have to push
+           something meaningless for pop_failure_jump to pop.  */
+        case dummy_failure_jump:
+          DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
+          /* It doesn't matter what we push for the string here.  What
+             the code at `fail' tests is the value for the pattern.  */
+          PUSH_FAILURE_POINT (0, 0, -2);
+          goto unconditional_jump;
+
+
+        /* At the end of an alternative, we need to push a dummy failure
+           point in case we are followed by a `pop_failure_jump', because
+           we don't want the failure point for the alternative to be
+           popped.  For example, matching `(a|ab)*' against `aab'
+           requires that we match the `ab' alternative.  */
+        case push_dummy_failure:
+          DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
+          /* See comments just above at `dummy_failure_jump' about the
+             two zeroes.  */
+          PUSH_FAILURE_POINT (0, 0, -2);
+          break;
+
+        /* Have to succeed matching what follows at least n times.
+           After that, handle like `on_failure_jump'.  */
+        case succeed_n: 
+          EXTRACT_NUMBER (mcnt, p + 2);
+          DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
+
+          assert (mcnt >= 0);
+          /* Originally, this is how many times we HAVE to succeed.  */
+          if (mcnt > 0)
+            {
+               mcnt--;
+	       p += 2;
+               STORE_NUMBER_AND_INCR (p, mcnt);
+               DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p, mcnt);
+            }
+	  else if (mcnt == 0)
+            {
+              DEBUG_PRINT2 ("  Setting two bytes from 0x%x to no_op.\n", p+2);
+	      p[2] = (unsigned char) no_op;
+              p[3] = (unsigned char) no_op;
+              goto on_failure;
+            }
+          break;
+        
+        case jump_n: 
+          EXTRACT_NUMBER (mcnt, p + 2);
+          DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
+
+          /* Originally, this is how many times we CAN jump.  */
+          if (mcnt)
+            {
+               mcnt--;
+               STORE_NUMBER (p + 2, mcnt);
+	       goto unconditional_jump;	     
+            }
+          /* If don't have to jump any more, skip over the rest of command.  */
+	  else      
+	    p += 4;		     
+          break;
+        
+	case set_number_at:
+	  {
+            DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
+
+            EXTRACT_NUMBER_AND_INCR (mcnt, p);
+            p1 = p + mcnt;
+            EXTRACT_NUMBER_AND_INCR (mcnt, p);
+            DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p1, mcnt);
+	    STORE_NUMBER (p1, mcnt);
+            break;
+          }
+
+        case wordbound:
+          DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+          if (AT_WORD_BOUNDARY (d))
+	    break;
+          goto fail;
+
+	case notwordbound:
+          DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+	  if (AT_WORD_BOUNDARY (d))
+	    goto fail;
+          break;
+
+	case wordbeg:
+          DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
+	  if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
+	    break;
+          goto fail;
+
+	case wordend:
+          DEBUG_PRINT1 ("EXECUTING wordend.\n");
+	  if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
+              && (!WORDCHAR_P (d) || AT_STRINGS_END (d)))
+	    break;
+          goto fail;
+
+#ifdef emacs
+  	case before_dot:
+          DEBUG_PRINT1 ("EXECUTING before_dot.\n");
+ 	  if (PTR_CHAR_POS ((unsigned char *) d) >= point)
+  	    goto fail;
+  	  break;
+  
+  	case at_dot:
+          DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+ 	  if (PTR_CHAR_POS ((unsigned char *) d) != point)
+  	    goto fail;
+  	  break;
+  
+  	case after_dot:
+          DEBUG_PRINT1 ("EXECUTING after_dot.\n");
+          if (PTR_CHAR_POS ((unsigned char *) d) <= point)
+  	    goto fail;
+  	  break;
+#if 0 /* not emacs19 */
+	case at_dot:
+          DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+	  if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point)
+	    goto fail;
+	  break;
+#endif /* not emacs19 */
+
+	case syntaxspec:
+          DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
+	  mcnt = *p++;
+	  goto matchsyntax;
+
+        case wordchar:
+          DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
+	  mcnt = (int) Sword;
+        matchsyntax:
+	  PREFETCH ();
+	  /* Can't use *d++ here; SYNTAX may be an unsafe macro.  */
+	  d++;
+	  if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt)
+	    goto fail;
+          SET_REGS_MATCHED ();
+	  break;
+
+	case notsyntaxspec:
+          DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
+	  mcnt = *p++;
+	  goto matchnotsyntax;
+
+        case notwordchar:
+          DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
+	  mcnt = (int) Sword;
+        matchnotsyntax:
+	  PREFETCH ();
+	  /* Can't use *d++ here; SYNTAX may be an unsafe macro.  */
+	  d++;
+	  if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt)
+	    goto fail;
+	  SET_REGS_MATCHED ();
+          break;
+
+#else /* not emacs */
+	case wordchar:
+          DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
+	  PREFETCH ();
+          if (!WORDCHAR_P (d))
+            goto fail;
+	  SET_REGS_MATCHED ();
+          d++;
+	  break;
+	  
+	case notwordchar:
+          DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
+	  PREFETCH ();
+	  if (WORDCHAR_P (d))
+            goto fail;
+          SET_REGS_MATCHED ();
+          d++;
+	  break;
+#endif /* not emacs */
+          
+        default:
+          abort ();
+	}
+      continue;  /* Successfully executed one pattern command; keep going.  */
+
+
+    /* We goto here if a matching operation fails. */
+    fail:
+      if (!FAIL_STACK_EMPTY ())
+	{ /* A restart point is known.  Restore to that state.  */
+          DEBUG_PRINT1 ("\nFAIL:\n");
+          POP_FAILURE_POINT (d, p,
+                             lowest_active_reg, highest_active_reg,
+                             regstart, regend, reg_info);
+
+          /* If this failure point is a dummy, try the next one.  */
+          if (!p)
+	    goto fail;
+
+          /* If we failed to the end of the pattern, don't examine *p.  */
+	  assert (p <= pend);
+          if (p < pend)
+            {
+              boolean is_a_jump_n = false;
+              
+              /* If failed to a backwards jump that's part of a repetition
+                 loop, need to pop this failure point and use the next one.  */
+              switch ((re_opcode_t) *p)
+                {
+                case jump_n:
+                  is_a_jump_n = true;
+                case maybe_pop_jump:
+                case pop_failure_jump:
+                case jump:
+                  p1 = p + 1;
+                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+                  p1 += mcnt;	
+
+                  if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
+                      || (!is_a_jump_n
+                          && (re_opcode_t) *p1 == on_failure_jump))
+                    goto fail;
+                  break;
+                default:
+                  /* do nothing */ ;
+                }
+            }
+
+          if (d >= string1 && d <= end1)
+	    dend = end_match_1;
+        }
+      else
+        break;   /* Matching at this starting point really fails.  */
+    } /* for (;;) */
+
+  if (best_regs_set)
+    goto restore_best_regs;
+
+  FREE_VARIABLES ();
+
+  return -1;         			/* Failure to match.  */
+} /* re_match_2 */
+
+
+/* Subroutine definitions for re_match_2.  */
+
+
+/* We are passed P pointing to a register number after a start_memory.
+   
+   Return true if the pattern up to the corresponding stop_memory can
+   match the empty string, and false otherwise.
+   
+   If we find the matching stop_memory, sets P to point to one past its number.
+   Otherwise, sets P to an undefined byte less than or equal to END.
+
+   We don't handle duplicates properly (yet).  */
+
+static boolean
+group_match_null_string_p (p, end, reg_info)
+    unsigned char **p, *end;
+    register_info_type *reg_info;
+{
+  int mcnt;
+  /* Point to after the args to the start_memory.  */
+  unsigned char *p1 = *p + 2;
+  
+  while (p1 < end)
+    {
+      /* Skip over opcodes that can match nothing, and return true or
+	 false, as appropriate, when we get to one that can't, or to the
+         matching stop_memory.  */
+      
+      switch ((re_opcode_t) *p1)
+        {
+        /* Could be either a loop or a series of alternatives.  */
+        case on_failure_jump:
+          p1++;
+          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+          
+          /* If the next operation is not a jump backwards in the
+	     pattern.  */
+
+	  if (mcnt >= 0)
+	    {
+              /* Go through the on_failure_jumps of the alternatives,
+                 seeing if any of the alternatives cannot match nothing.
+                 The last alternative starts with only a jump,
+                 whereas the rest start with on_failure_jump and end
+                 with a jump, e.g., here is the pattern for `a|b|c':
+
+                 /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
+                 /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
+                 /exactn/1/c						
+
+                 So, we have to first go through the first (n-1)
+                 alternatives and then deal with the last one separately.  */
+
+
+              /* Deal with the first (n-1) alternatives, which start
+                 with an on_failure_jump (see above) that jumps to right
+                 past a jump_past_alt.  */
+
+              while ((re_opcode_t) p1[mcnt-3] == jump_past_alt)
+                {
+                  /* `mcnt' holds how many bytes long the alternative
+                     is, including the ending `jump_past_alt' and
+                     its number.  */
+
+                  if (!alt_match_null_string_p (p1, p1 + mcnt - 3, 
+				                      reg_info))
+                    return false;
+
+                  /* Move to right after this alternative, including the
+		     jump_past_alt.  */
+                  p1 += mcnt;	
+
+                  /* Break if it's the beginning of an n-th alternative
+                     that doesn't begin with an on_failure_jump.  */
+                  if ((re_opcode_t) *p1 != on_failure_jump)
+                    break;
+		
+		  /* Still have to check that it's not an n-th
+		     alternative that starts with an on_failure_jump.  */
+		  p1++;
+                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+                  if ((re_opcode_t) p1[mcnt-3] != jump_past_alt)
+                    {
+		      /* Get to the beginning of the n-th alternative.  */
+                      p1 -= 3;
+                      break;
+                    }
+                }
+
+              /* Deal with the last alternative: go back and get number
+                 of the `jump_past_alt' just before it.  `mcnt' contains
+                 the length of the alternative.  */
+              EXTRACT_NUMBER (mcnt, p1 - 2);
+
+              if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info))
+                return false;
+
+              p1 += mcnt;	/* Get past the n-th alternative.  */
+            } /* if mcnt > 0 */
+          break;
+
+          
+        case stop_memory:
+	  assert (p1[1] == **p);
+          *p = p1 + 2;
+          return true;
+
+        
+        default: 
+          if (!common_op_match_null_string_p (&p1, end, reg_info))
+            return false;
+        }
+    } /* while p1 < end */
+
+  return false;
+} /* group_match_null_string_p */
+
+
+/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
+   It expects P to be the first byte of a single alternative and END one
+   byte past the last. The alternative can contain groups.  */
+   
+static boolean
+alt_match_null_string_p (p, end, reg_info)
+    unsigned char *p, *end;
+    register_info_type *reg_info;
+{
+  int mcnt;
+  unsigned char *p1 = p;
+  
+  while (p1 < end)
+    {
+      /* Skip over opcodes that can match nothing, and break when we get 
+         to one that can't.  */
+      
+      switch ((re_opcode_t) *p1)
+        {
+	/* It's a loop.  */
+        case on_failure_jump:
+          p1++;
+          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+          p1 += mcnt;
+          break;
+          
+	default: 
+          if (!common_op_match_null_string_p (&p1, end, reg_info))
+            return false;
+        }
+    }  /* while p1 < end */
+
+  return true;
+} /* alt_match_null_string_p */
+
+
+/* Deals with the ops common to group_match_null_string_p and
+   alt_match_null_string_p.  
+   
+   Sets P to one after the op and its arguments, if any.  */
+
+static boolean
+common_op_match_null_string_p (p, end, reg_info)
+    unsigned char **p, *end;
+    register_info_type *reg_info;
+{
+  int mcnt;
+  boolean ret;
+  int reg_no;
+  unsigned char *p1 = *p;
+
+  switch ((re_opcode_t) *p1++)
+    {
+    case no_op:
+    case begline:
+    case endline:
+    case begbuf:
+    case endbuf:
+    case wordbeg:
+    case wordend:
+    case wordbound:
+    case notwordbound:
+#ifdef emacs
+    case before_dot:
+    case at_dot:
+    case after_dot:
+#endif
+      break;
+
+    case start_memory:
+      reg_no = *p1;
+      assert (reg_no > 0 && reg_no <= MAX_REGNUM);
+      ret = group_match_null_string_p (&p1, end, reg_info);
+      
+      /* Have to set this here in case we're checking a group which
+         contains a group and a back reference to it.  */
+
+      if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
+        REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
+
+      if (!ret)
+        return false;
+      break;
+          
+    /* If this is an optimized succeed_n for zero times, make the jump.  */
+    case jump:
+      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+      if (mcnt >= 0)
+        p1 += mcnt;
+      else
+        return false;
+      break;
+
+    case succeed_n:
+      /* Get to the number of times to succeed.  */
+      p1 += 2;		
+      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+      if (mcnt == 0)
+        {
+          p1 -= 4;
+          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+          p1 += mcnt;
+        }
+      else
+        return false;
+      break;
+
+    case duplicate: 
+      if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
+        return false;
+      break;
+
+    case set_number_at:
+      p1 += 4;
+
+    default:
+      /* All other opcodes mean we cannot match the empty string.  */
+      return false;
+  }
+
+  *p = p1;
+  return true;
+} /* common_op_match_null_string_p */
+
+
+/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
+   bytes; nonzero otherwise.  */
+   
+static int
+bcmp_translate (s1, s2, len, translate)
+     unsigned char *s1, *s2;
+     register int len;
+     char *translate;
+{
+  register unsigned char *p1 = s1, *p2 = s2;
+  while (len)
+    {
+      if (translate[*p1++] != translate[*p2++]) return 1;
+      len--;
+    }
+  return 0;
+}
+
+
+/* Entry points for GNU code.  */
+
+/* re_compile_pattern is the GNU regular expression compiler: it
+   compiles PATTERN (of length SIZE) and puts the result in BUFP.
+   Returns 0 if the pattern was valid, otherwise an error string.
+   
+   Assumes the `allocated' (and perhaps `buffer') and `translate' fields
+   are set in BUFP on entry.
+   
+   We call regex_compile to do the actual compilation.  */
+
+const char *
+re_compile_pattern (pattern, length, bufp)
+     const char *pattern;
+     int length;
+     struct re_pattern_buffer *bufp;
+{
+  reg_errcode_t ret;
+  
+  /* GNU code is written to assume at least RE_NREGS registers will be set
+     (and at least one extra will be -1).  */
+  bufp->regs_allocated = REGS_UNALLOCATED;
+  
+  /* And GNU code determines whether or not to get register information
+     by passing null for the REGS argument to re_match, etc., not by
+     setting no_sub.  */
+  bufp->no_sub = 0;
+  
+  /* Match anchors at newline.  */
+  bufp->newline_anchor = 1;
+  
+  ret = regex_compile (pattern, length, re_syntax_options, bufp);
+
+  if (!ret)
+    return NULL;
+  return gettext (re_error_msgid[(int) ret]);
+}     
+
+
+/* Entry points compatible with 4.2 BSD regex library.  We don't define
+   them unless specifically requested.  */
+
+#ifdef _REGEX_RE_COMP
+
+/* BSD has one and only one pattern buffer.  */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+re_comp (s)
+    const char *s;
+{
+  reg_errcode_t ret;
+  
+  if (!s)
+    {
+      if (!re_comp_buf.buffer)
+	return gettext ("No previous regular expression");
+      return 0;
+    }
+
+  if (!re_comp_buf.buffer)
+    {
+      re_comp_buf.buffer = (unsigned char *) malloc (200);
+      if (re_comp_buf.buffer == NULL)
+        return gettext (re_error_msgid[(int) REG_ESPACE]);
+      re_comp_buf.allocated = 200;
+
+      re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
+      if (re_comp_buf.fastmap == NULL)
+	return gettext (re_error_msgid[(int) REG_ESPACE]);
+    }
+
+  /* Since `re_exec' always passes NULL for the `regs' argument, we
+     don't need to initialize the pattern buffer fields which affect it.  */
+
+  /* Match anchors at newlines.  */
+  re_comp_buf.newline_anchor = 1;
+
+  ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
+  
+  if (!ret)
+    return NULL;
+
+  /* Yes, we're discarding `const' here if !HAVE_LIBINTL.  */
+  return (char *) gettext (re_error_msgid[(int) ret]);
+}
+
+
+int
+re_exec (s)
+    const char *s;
+{
+  const int len = strlen (s);
+  return
+    0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
+}
+#endif /* _REGEX_RE_COMP */
+
+
+/* POSIX.2 functions.  Don't define these for Emacs.  */
+
+#ifndef emacs
+
+/* regcomp takes a regular expression as a string and compiles it.
+
+   PREG is a regex_t *.  We do not expect any fields to be initialized,
+   since POSIX says we shouldn't.  Thus, we set
+
+     `buffer' to the compiled pattern;
+     `used' to the length of the compiled pattern;
+     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
+       REG_EXTENDED bit in CFLAGS is set; otherwise, to
+       RE_SYNTAX_POSIX_BASIC;
+     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
+     `fastmap' and `fastmap_accurate' to zero;
+     `re_nsub' to the number of subexpressions in PATTERN.
+
+   PATTERN is the address of the pattern string.
+
+   CFLAGS is a series of bits which affect compilation.
+
+     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
+     use POSIX basic syntax.
+
+     If REG_NEWLINE is set, then . and [^...] don't match newline.
+     Also, regexec will try a match beginning after every newline.
+
+     If REG_ICASE is set, then we considers upper- and lowercase
+     versions of letters to be equivalent when matching.
+
+     If REG_NOSUB is set, then when PREG is passed to regexec, that
+     routine will report only success or failure, and nothing about the
+     registers.
+
+   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
+   the return codes and their meanings.)  */
+
+int
+regcomp (preg, pattern, cflags)
+    regex_t *preg;
+    const char *pattern; 
+    int cflags;
+{
+  reg_errcode_t ret;
+  unsigned syntax
+    = (cflags & REG_EXTENDED) ?
+      RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
+
+  /* regex_compile will allocate the space for the compiled pattern.  */
+  preg->buffer = 0;
+  preg->allocated = 0;
+  preg->used = 0;
+  
+  /* Don't bother to use a fastmap when searching.  This simplifies the
+     REG_NEWLINE case: if we used a fastmap, we'd have to put all the
+     characters after newlines into the fastmap.  This way, we just try
+     every character.  */
+  preg->fastmap = 0;
+  
+  if (cflags & REG_ICASE)
+    {
+      unsigned i;
+      
+      preg->translate = (char *) malloc (CHAR_SET_SIZE);
+      if (preg->translate == NULL)
+        return (int) REG_ESPACE;
+
+      /* Map uppercase characters to corresponding lowercase ones.  */
+      for (i = 0; i < CHAR_SET_SIZE; i++)
+        preg->translate[i] = ISUPPER (i) ? tolower (i) : i;
+    }
+  else
+    preg->translate = NULL;
+
+  /* If REG_NEWLINE is set, newlines are treated differently.  */
+  if (cflags & REG_NEWLINE)
+    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
+      syntax &= ~RE_DOT_NEWLINE;
+      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+      /* It also changes the matching behavior.  */
+      preg->newline_anchor = 1;
+    }
+  else
+    preg->newline_anchor = 0;
+
+  preg->no_sub = !!(cflags & REG_NOSUB);
+
+  /* POSIX says a null character in the pattern terminates it, so we 
+     can use strlen here in compiling the pattern.  */
+  ret = regex_compile (pattern, strlen (pattern), syntax, preg);
+  
+  /* POSIX doesn't distinguish between an unmatched open-group and an
+     unmatched close-group: both are REG_EPAREN.  */
+  if (ret == REG_ERPAREN) ret = REG_EPAREN;
+  
+  return (int) ret;
+}
+
+
+/* regexec searches for a given pattern, specified by PREG, in the
+   string STRING.
+   
+   If NMATCH is zero or REG_NOSUB was set in the cflags argument to
+   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at
+   least NMATCH elements, and we set them to the offsets of the
+   corresponding matched substrings.
+   
+   EFLAGS specifies `execution flags' which affect matching: if
+   REG_NOTBOL is set, then ^ does not match at the beginning of the
+   string; if REG_NOTEOL is set, then $ does not match at the end.
+   
+   We return 0 if we find a match and REG_NOMATCH if not.  */
+
+int
+regexec (preg, string, nmatch, pmatch, eflags)
+    const regex_t *preg;
+    const char *string; 
+    size_t nmatch; 
+    regmatch_t pmatch[]; 
+    int eflags;
+{
+  int ret;
+  struct re_registers regs;
+  regex_t private_preg;
+  int len = strlen (string);
+  boolean want_reg_info = !preg->no_sub && nmatch > 0;
+
+  private_preg = *preg;
+  
+  private_preg.not_bol = !!(eflags & REG_NOTBOL);
+  private_preg.not_eol = !!(eflags & REG_NOTEOL);
+  
+  /* The user has told us exactly how many registers to return
+     information about, via `nmatch'.  We have to pass that on to the
+     matching routines.  */
+  private_preg.regs_allocated = REGS_FIXED;
+  
+  if (want_reg_info)
+    {
+      regs.num_regs = nmatch;
+      regs.start = TALLOC (nmatch, regoff_t);
+      regs.end = TALLOC (nmatch, regoff_t);
+      if (regs.start == NULL || regs.end == NULL)
+        return (int) REG_NOMATCH;
+    }
+
+  /* Perform the searching operation.  */
+  ret = re_search (&private_preg, string, len,
+                   /* start: */ 0, /* range: */ len,
+                   want_reg_info ? &regs : (struct re_registers *) 0);
+  
+  /* Copy the register information to the POSIX structure.  */
+  if (want_reg_info)
+    {
+      if (ret >= 0)
+        {
+          unsigned r;
+
+          for (r = 0; r < nmatch; r++)
+            {
+              pmatch[r].rm_so = regs.start[r];
+              pmatch[r].rm_eo = regs.end[r];
+            }
+        }
+
+      /* If we needed the temporary register info, free the space now.  */
+      free (regs.start);
+      free (regs.end);
+    }
+
+  /* We want zero return to mean success, unlike `re_search'.  */
+  return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
+}
+
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+   from either regcomp or regexec.   We don't use PREG here.  */
+
+size_t
+regerror (errcode, preg, errbuf, errbuf_size)
+    int errcode;
+    const regex_t *preg;
+    char *errbuf;
+    size_t errbuf_size;
+{
+  const char *msg;
+  size_t msg_size;
+
+  if (errcode < 0
+      || errcode >= (sizeof (re_error_msgid) / sizeof (re_error_msgid[0])))
+    /* Only error codes returned by the rest of the code should be passed 
+       to this routine.  If we are given anything else, or if other regex
+       code generates an invalid error code, then the program has a bug.
+       Dump core so we can fix it.  */
+    abort ();
+
+  msg = gettext (re_error_msgid[errcode]);
+
+  msg_size = strlen (msg) + 1; /* Includes the null.  */
+  
+  if (errbuf_size != 0)
+    {
+      if (msg_size > errbuf_size)
+        {
+          strncpy (errbuf, msg, errbuf_size - 1);
+          errbuf[errbuf_size - 1] = 0;
+        }
+      else
+        strcpy (errbuf, msg);
+    }
+
+  return msg_size;
+}
+
+
+/* Free dynamically allocated space used by PREG.  */
+
+void
+regfree (preg)
+    regex_t *preg;
+{
+  if (preg->buffer != NULL)
+    free (preg->buffer);
+  preg->buffer = NULL;
+  
+  preg->allocated = 0;
+  preg->used = 0;
+
+  if (preg->fastmap != NULL)
+    free (preg->fastmap);
+  preg->fastmap = NULL;
+  preg->fastmap_accurate = 0;
+
+  if (preg->translate != NULL)
+    free (preg->translate);
+  preg->translate = NULL;
+}
+
+#endif /* not emacs  */
+
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
Index: /indexers/branches/3.03a/mg/lib/regex.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/regex.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/regex.h	(revision 14757)
@@ -0,0 +1,497 @@
+/* Definitions for data structures and routines for the regular
+   expression library, version 0.12.
+
+   Copyright (C) 1985, 89, 90, 91, 92, 93, 95 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 program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef __REGEXP_LIBRARY_H__
+#define __REGEXP_LIBRARY_H__
+
+/* POSIX says that <sys/types.h> must be included (by the caller) before
+   <regex.h>.  */
+
+#if !defined (_POSIX_C_SOURCE) && !defined (_POSIX_SOURCE) && defined (VMS)
+/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
+   should be there.  */
+#include <stddef.h>
+#endif
+
+
+/* The following bits are used to determine the regexp syntax we
+   recognize.  The set/not-set meanings are chosen so that Emacs syntax
+   remains the value 0.  The bits are given in alphabetical order, and
+   the definitions shifted by one from the previous bit; thus, when we
+   add or remove a bit, only one other definition need change.  */
+typedef unsigned reg_syntax_t;
+
+/* If this bit is not set, then \ inside a bracket expression is literal.
+   If set, then such a \ quotes the following character.  */
+#define RE_BACKSLASH_ESCAPE_IN_LISTS (1)
+
+/* If this bit is not set, then + and ? are operators, and \+ and \? are
+     literals. 
+   If set, then \+ and \? are operators and + and ? are literals.  */
+#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
+
+/* If this bit is set, then character classes are supported.  They are:
+     [:alpha:], [:upper:], [:lower:],  [:digit:], [:alnum:], [:xdigit:],
+     [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
+   If not set, then character classes are not supported.  */
+#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
+
+/* If this bit is set, then ^ and $ are always anchors (outside bracket
+     expressions, of course).
+   If this bit is not set, then it depends:
+        ^  is an anchor if it is at the beginning of a regular
+           expression or after an open-group or an alternation operator;
+        $  is an anchor if it is at the end of a regular expression, or
+           before a close-group or an alternation operator.  
+
+   This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
+   POSIX draft 11.2 says that * etc. in leading positions is undefined.
+   We already implemented a previous draft which made those constructs
+   invalid, though, so we haven't changed the code back.  */
+#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
+
+/* If this bit is set, then special characters are always special
+     regardless of where they are in the pattern.
+   If this bit is not set, then special characters are special only in
+     some contexts; otherwise they are ordinary.  Specifically, 
+     * + ? and intervals are only special when not after the beginning,
+     open-group, or alternation operator.  */
+#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
+
+/* If this bit is set, then *, +, ?, and { cannot be first in an re or
+     immediately after an alternation or begin-group operator.  */
+#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
+
+/* If this bit is set, then . matches newline.
+   If not set, then it doesn't.  */
+#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
+
+/* If this bit is set, then . doesn't match NUL.
+   If not set, then it does.  */
+#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
+
+/* If this bit is set, nonmatching lists [^...] do not match newline.
+   If not set, they do.  */
+#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
+
+/* If this bit is set, either \{...\} or {...} defines an
+     interval, depending on RE_NO_BK_BRACES. 
+   If not set, \{, \}, {, and } are literals.  */
+#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
+
+/* If this bit is set, +, ? and | aren't recognized as operators.
+   If not set, they are.  */
+#define RE_LIMITED_OPS (RE_INTERVALS << 1)
+
+/* If this bit is set, newline is an alternation operator.
+   If not set, newline is literal.  */
+#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
+
+/* If this bit is set, then `{...}' defines an interval, and \{ and \}
+     are literals.
+  If not set, then `\{...\}' defines an interval.  */
+#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
+
+/* If this bit is set, (...) defines a group, and \( and \) are literals.
+   If not set, \(...\) defines a group, and ( and ) are literals.  */
+#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
+
+/* If this bit is set, then \<digit> matches <digit>.
+   If not set, then \<digit> is a back-reference.  */
+#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
+
+/* If this bit is set, then | is an alternation operator, and \| is literal. 
+   If not set, then \| is an alternation operator, and | is literal.  */
+#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
+
+/* If this bit is set, then an ending range point collating higher
+     than the starting range point, as in [z-a], is invalid.
+   If not set, then when ending range point collates higher than the
+     starting range point, the range is ignored.  */
+#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
+
+/* If this bit is set, then an unmatched ) is ordinary.
+   If not set, then an unmatched ) is invalid.  */
+#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
+
+/* If this bit is set, succeed as soon as we match the whole pattern,
+   without further backtracking.  */
+#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
+
+/* This global variable defines the particular regexp syntax to use (for
+   some interfaces).  When a regexp is compiled, the syntax used is
+   stored in the pattern buffer, so changing this does not affect
+   already-compiled regexps.  */
+extern reg_syntax_t re_syntax_options;
+
+
+/* Define combinations of the above bits for the standard possibilities.
+   (The [[[ comments delimit what gets put into the Texinfo file, so
+   don't delete them!)  */ 
+/* [[[begin syntaxes]]] */
+#define RE_SYNTAX_EMACS 0
+
+#define RE_SYNTAX_AWK							\
+  (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL			\
+   | RE_NO_BK_PARENS            | RE_NO_BK_REFS				\
+   | RE_NO_BK_VBAR               | RE_NO_EMPTY_RANGES			\
+   | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+#define RE_SYNTAX_POSIX_AWK 						\
+  (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS)
+
+#define RE_SYNTAX_GREP							\
+  (RE_BK_PLUS_QM              | RE_CHAR_CLASSES				\
+   | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS				\
+   | RE_NEWLINE_ALT)
+
+#define RE_SYNTAX_EGREP							\
+  (RE_CHAR_CLASSES        | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE			\
+   | RE_NEWLINE_ALT       | RE_NO_BK_PARENS				\
+   | RE_NO_BK_VBAR)
+
+#define RE_SYNTAX_POSIX_EGREP						\
+  (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
+
+/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff.  */
+#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
+
+#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
+
+/* Syntax bits common to both basic and extended POSIX regex syntax.  */
+#define _RE_SYNTAX_POSIX_COMMON						\
+  (RE_CHAR_CLASSES | RE_DOT_NEWLINE      | RE_DOT_NOT_NULL		\
+   | RE_INTERVALS  | RE_NO_EMPTY_RANGES)
+
+#define RE_SYNTAX_POSIX_BASIC						\
+  (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
+
+/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
+   RE_LIMITED_OPS, i.e., \? \+ \| are not recognized.  Actually, this
+   isn't minimal, since other operators, such as \`, aren't disabled.  */
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC					\
+  (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
+
+#define RE_SYNTAX_POSIX_EXTENDED					\
+  (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INDEP_OPS  | RE_NO_BK_BRACES				\
+   | RE_NO_BK_PARENS       | RE_NO_BK_VBAR				\
+   | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
+   replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added.  */
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED				\
+  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES				\
+   | RE_NO_BK_PARENS        | RE_NO_BK_REFS				\
+   | RE_NO_BK_VBAR	    | RE_UNMATCHED_RIGHT_PAREN_ORD)
+/* [[[end syntaxes]]] */
+
+
+/* Maximum number of duplicates an interval can allow.  Some systems
+   (erroneously) define this in other header files, but we want our
+   value, so remove any previous define.  */
+#ifdef RE_DUP_MAX
+#undef RE_DUP_MAX
+#endif
+#define RE_DUP_MAX ((1 << 15) - 1) 
+
+
+/* POSIX `cflags' bits (i.e., information for `regcomp').  */
+
+/* If this bit is set, then use extended regular expression syntax.
+   If not set, then use basic regular expression syntax.  */
+#define REG_EXTENDED 1
+
+/* If this bit is set, then ignore case when matching.
+   If not set, then case is significant.  */
+#define REG_ICASE (REG_EXTENDED << 1)
+ 
+/* If this bit is set, then anchors do not match at newline
+     characters in the string.
+   If not set, then anchors do match at newlines.  */
+#define REG_NEWLINE (REG_ICASE << 1)
+
+/* If this bit is set, then report only success or fail in regexec.
+   If not set, then returns differ between not matching and errors.  */
+#define REG_NOSUB (REG_NEWLINE << 1)
+
+
+/* POSIX `eflags' bits (i.e., information for regexec).  */
+
+/* If this bit is set, then the beginning-of-line operator doesn't match
+     the beginning of the string (presumably because it's not the
+     beginning of a line).
+   If not set, then the beginning-of-line operator does match the
+     beginning of the string.  */
+#define REG_NOTBOL 1
+
+/* Like REG_NOTBOL, except for the end-of-line.  */
+#define REG_NOTEOL (1 << 1)
+
+
+/* If any error codes are removed, changed, or added, update the
+   `re_error_msg' table in regex.c.  */
+typedef enum
+{
+  REG_NOERROR = 0,	/* Success.  */
+  REG_NOMATCH,		/* Didn't find a match (for regexec).  */
+
+  /* POSIX regcomp return error codes.  (In the order listed in the
+     standard.)  */
+  REG_BADPAT,		/* Invalid pattern.  */
+  REG_ECOLLATE,		/* Not implemented.  */
+  REG_ECTYPE,		/* Invalid character class name.  */
+  REG_EESCAPE,		/* Trailing backslash.  */
+  REG_ESUBREG,		/* Invalid back reference.  */
+  REG_EBRACK,		/* Unmatched left bracket.  */
+  REG_EPAREN,		/* Parenthesis imbalance.  */ 
+  REG_EBRACE,		/* Unmatched \{.  */
+  REG_BADBR,		/* Invalid contents of \{\}.  */
+  REG_ERANGE,		/* Invalid range end.  */
+  REG_ESPACE,		/* Ran out of memory.  */
+  REG_BADRPT,		/* No preceding re for repetition op.  */
+
+  /* Error codes we've added.  */
+  REG_EEND,		/* Premature end.  */
+  REG_ESIZE,		/* Compiled pattern bigger than 2^16 bytes.  */
+  REG_ERPAREN		/* Unmatched ) or \); not returned from regcomp.  */
+} reg_errcode_t;
+
+
+/* This data structure represents a compiled pattern.  Before calling
+   the pattern compiler, the fields `buffer', `allocated', `fastmap',
+   `translate', and `no_sub' can be set.  After the pattern has been
+   compiled, the `re_nsub' field is available.  All other fields are
+   private to the regex routines.  */
+
+struct re_pattern_buffer
+{
+/* [[[begin pattern_buffer]]] */
+	/* Space that holds the compiled pattern.  It is declared as
+          `unsigned char *' because its elements are
+           sometimes used as array indexes.  */
+  unsigned char *buffer;
+
+	/* Number of bytes to which `buffer' points.  */
+  unsigned long allocated;
+
+	/* Number of bytes actually used in `buffer'.  */
+  unsigned long used;	
+
+        /* Syntax setting with which the pattern was compiled.  */
+  reg_syntax_t syntax;
+
+        /* Pointer to a fastmap, if any, otherwise zero.  re_search uses
+           the fastmap, if there is one, to skip over impossible
+           starting points for matches.  */
+  char *fastmap;
+
+        /* Either a translate table to apply to all characters before
+           comparing them, or zero for no translation.  The translation
+           is applied to a pattern when it is compiled and to a string
+           when it is matched.  */
+  char *translate;
+
+	/* Number of subexpressions found by the compiler.  */
+  size_t re_nsub;
+
+        /* Zero if this pattern cannot match the empty string, one else.
+           Well, in truth it's used only in `re_search_2', to see
+           whether or not we should use the fastmap, so we don't set
+           this absolutely perfectly; see `re_compile_fastmap' (the
+           `duplicate' case).  */
+  unsigned can_be_null : 1;
+
+        /* If REGS_UNALLOCATED, allocate space in the `regs' structure
+             for `max (RE_NREGS, re_nsub + 1)' groups.
+           If REGS_REALLOCATE, reallocate space if necessary.
+           If REGS_FIXED, use what's there.  */
+#define REGS_UNALLOCATED 0
+#define REGS_REALLOCATE 1
+#define REGS_FIXED 2
+  unsigned regs_allocated : 2;
+
+        /* Set to zero when `regex_compile' compiles a pattern; set to one
+           by `re_compile_fastmap' if it updates the fastmap.  */
+  unsigned fastmap_accurate : 1;
+
+        /* If set, `re_match_2' does not return information about
+           subexpressions.  */
+  unsigned no_sub : 1;
+
+        /* If set, a beginning-of-line anchor doesn't match at the
+           beginning of the string.  */ 
+  unsigned not_bol : 1;
+
+        /* Similarly for an end-of-line anchor.  */
+  unsigned not_eol : 1;
+
+        /* If true, an anchor at a newline matches.  */
+  unsigned newline_anchor : 1;
+
+/* [[[end pattern_buffer]]] */
+};
+
+typedef struct re_pattern_buffer regex_t;
+
+
+/* Type for byte offsets within the string.  POSIX mandates this.  */
+typedef int regoff_t;
+
+
+/* This is the structure we store register match data in.  See
+   regex.texinfo for a full description of what registers match.  */
+struct re_registers
+{
+  unsigned num_regs;
+  regoff_t *start;
+  regoff_t *end;
+};
+
+
+/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
+   `re_match_2' returns information about at least this many registers
+   the first time a `regs' structure is passed.  */
+#ifndef RE_NREGS
+#define RE_NREGS 30
+#endif
+
+
+/* POSIX specification for registers.  Aside from the different names than
+   `re_registers', POSIX uses an array of structures, instead of a
+   structure of arrays.  */
+typedef struct
+{
+  regoff_t rm_so;  /* Byte offset from string's start to substring's start.  */
+  regoff_t rm_eo;  /* Byte offset from string's start to substring's end.  */
+} regmatch_t;
+
+
+/* Declarations for routines.  */
+
+/* To avoid duplicating every routine declaration -- once with a
+   prototype (if we are ANSI), and once without (if we aren't) -- we
+   use the following macro to declare argument types.  This
+   unfortunately clutters up the declarations a bit, but I think it's
+   worth it.  */
+
+#if __STDC__
+
+#define _RE_ARGS(args) args
+
+#else /* not __STDC__ */
+
+#define _RE_ARGS(args) ()
+
+#endif /* not __STDC__ */
+
+/* Sets the current default syntax to SYNTAX, and return the old syntax.
+   You can also simply assign to the `re_syntax_options' variable.  */
+extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
+
+/* Compile the regular expression PATTERN, with length LENGTH
+   and syntax given by the global `re_syntax_options', into the buffer
+   BUFFER.  Return NULL if successful, and an error string if not.  */
+extern const char *re_compile_pattern
+  _RE_ARGS ((const char *pattern, int length,
+             struct re_pattern_buffer *buffer));
+
+
+/* Compile a fastmap for the compiled pattern in BUFFER; used to
+   accelerate searches.  Return 0 if successful and -2 if was an
+   internal error.  */
+extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
+
+
+/* Search in the string STRING (with length LENGTH) for the pattern
+   compiled into BUFFER.  Start searching at position START, for RANGE
+   characters.  Return the starting position of the match, -1 for no
+   match, or -2 for an internal error.  Also return register
+   information in REGS (if REGS and BUFFER->no_sub are nonzero).  */
+extern int re_search
+  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+            int length, int start, int range, struct re_registers *regs));
+
+
+/* Like `re_search', but search in the concatenation of STRING1 and
+   STRING2.  Also, stop searching at index START + STOP.  */
+extern int re_search_2
+  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+             int length1, const char *string2, int length2,
+             int start, int range, struct re_registers *regs, int stop));
+
+
+/* Like `re_search', but return how many characters in STRING the regexp
+   in BUFFER matched, starting at position START.  */
+extern int re_match
+  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+             int length, int start, struct re_registers *regs));
+
+
+/* Relates to `re_match' as `re_search_2' relates to `re_search'.  */
+extern int re_match_2 
+  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+             int length1, const char *string2, int length2,
+             int start, struct re_registers *regs, int stop));
+
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+   ENDS.  Subsequent matches using BUFFER and REGS will use this memory
+   for recording register information.  STARTS and ENDS must be
+   allocated with malloc, and must each be at least `NUM_REGS * sizeof
+   (regoff_t)' bytes long.
+
+   If NUM_REGS == 0, then subsequent matches should allocate their own
+   register data.
+
+   Unless this function is called, the first search or match using
+   PATTERN_BUFFER will allocate its own register data, without
+   freeing the old data.  */
+extern void re_set_registers
+  _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
+             unsigned num_regs, regoff_t *starts, regoff_t *ends));
+
+#ifdef _REGEX_RE_COMP
+/* 4.2 bsd compatibility.  */
+extern char *re_comp _RE_ARGS ((const char *));
+extern int re_exec _RE_ARGS ((const char *));
+#endif
+
+/* POSIX compatibility.  */
+extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags));
+extern int regexec
+  _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch,
+             regmatch_t pmatch[], int eflags));
+extern size_t regerror
+  _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf,
+             size_t errbuf_size));
+extern void regfree _RE_ARGS ((regex_t *preg));
+
+#endif /* not __REGEXP_LIBRARY_H__ */
+
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
Index: /indexers/branches/3.03a/mg/lib/rx.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/rx.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/rx.c	(revision 14757)
@@ -0,0 +1,7272 @@
+
+/*	Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the librx library.
+
+Librx is free software; you can redistribute it and/or modify it under
+the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+Librx 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 Library General Public
+License along with this software; see the file COPYING.LIB.  If not,
+write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA
+02139, USA.  */
+
+/* NOTE!!!  AIX is so losing it requires this to be the first thing in the 
+ * file. 
+ * Do not put ANYTHING before it!  
+ */
+#if !defined (__GNUC__) && defined (_AIX)
+ #pragma alloca
+#endif
+
+/* To make linux happy? */
+#ifndef	_GNU_SOURCE
+#define	_GNU_SOURCE
+#endif
+
+#if HAVE_CONFIG_H
+# ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+#  include <win32cfg.h>
+#  include <malloc.h>
+# else
+#  include <sysfuncs.h>
+# endif
+#endif
+
+
+
+char rx_version_string[] = "GNU Rx version 0.07.1";
+
+			/* ``Too hard!''
+			 *	    -- anon.
+			 */
+
+
+
+#include <stdio.h>
+#include <ctype.h>
+#ifndef isgraph
+#define isgraph(c) (isprint (c) && !isspace (c))
+#endif
+#ifndef isblank
+#define isblank(c) ((c) == ' ' || (c) == '\t')
+#endif
+
+#include <sys/types.h>
+
+#undef MAX
+#undef MIN
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+typedef char boolean;
+#define false 0
+#define true 1
+
+#ifndef __GCC__
+#undef __inline__
+#define __inline__
+#endif
+
+/* Emacs already defines alloca, sometimes.  */
+#ifndef alloca
+
+/* Make alloca work the best possible way.  */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#else /* not __GNUC__ or HAVE_ALLOCA_H */
+#ifndef _AIX /* Already did AIX, up at the top.  */
+char *alloca ();
+#endif /* not _AIX */
+#endif /* not HAVE_ALLOCA_H */ 
+#endif /* not __GNUC__ */
+
+#endif /* not alloca */
+
+/* Memory management and stuff for emacs. */
+
+#define CHARBITS 8
+#define remalloc(M, S) (M ? realloc (M, S) : malloc (S))
+
+
+/* Should we use malloc or alloca?  If REGEX_MALLOC is not defined, we
+ * use `alloca' instead of `malloc' for the backtracking stack.
+ *
+ * Emacs will die miserably if we don't do this.
+ */
+
+#ifdef REGEX_MALLOC
+#define REGEX_ALLOCATE malloc
+#else /* not REGEX_MALLOC  */
+#ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+#define REGEX_ALLOCATE _alloca
+#else
+#define REGEX_ALLOCATE alloca
+#endif /* __WIN32__ */
+#endif /* not REGEX_MALLOC */
+
+
+#ifdef RX_WANT_RX_DEFS
+#define RX_DECL extern
+#define RX_DEF_QUAL 
+#else
+#define RX_WANT_RX_DEFS
+#define RX_DECL static
+#define RX_DEF_QUAL static
+#endif
+#include "rx.h"
+#undef RX_DECL
+#define RX_DECL RX_DEF_QUAL
+
+
+#ifndef emacs
+
+#ifdef SYNTAX_TABLE
+extern char *re_syntax_table;
+#else /* not SYNTAX_TABLE */
+
+#ifdef __STDC__
+static void
+init_syntax_once (void)
+#else
+static void
+init_syntax_once ()
+#endif
+{
+   register int c;
+   static int done = 0;
+
+   if (done)
+     return;
+
+   bzero (re_syntax_table, sizeof re_syntax_table);
+
+   for (c = 'a'; c <= 'z'; c++)
+     re_syntax_table[c] = Sword;
+
+   for (c = 'A'; c <= 'Z'; c++)
+     re_syntax_table[c] = Sword;
+
+   for (c = '0'; c <= '9'; c++)
+     re_syntax_table[c] = Sword;
+
+   re_syntax_table['_'] = Sword;
+
+   done = 1;
+}
+#endif /* not SYNTAX_TABLE */
+#endif /* not emacs */
+
+
+/* Compile with `-DRX_DEBUG' and use the following flags.
+ *
+ * Debugging flags:
+ *   	rx_debug - print information as a regexp is compiled
+ * 	rx_debug_trace - print information as a regexp is executed
+ */
+
+#ifdef RX_DEBUG
+
+int rx_debug_compile = 0;
+int rx_debug_trace = 0;
+static struct re_pattern_buffer * dbug_rxb = 0;
+
+#ifdef __STDC__
+typedef void (*side_effect_printer) (struct rx *, void *, FILE *);
+#else
+typedef void (*side_effect_printer) ();
+#endif
+
+#ifdef __STDC__
+static void print_cset (struct rx *rx, rx_Bitset cset, FILE * fp);
+#else
+static void print_cset ();
+#endif
+
+#ifdef __STDC__
+static void
+print_rexp (struct rx *rx,
+	    struct rexp_node *node, int depth,
+	    side_effect_printer seprint, FILE * fp)
+#else
+static void
+print_rexp (rx, node, depth, seprint, fp)
+     struct rx *rx;
+     struct rexp_node *node;
+     int depth;
+     side_effect_printer seprint;
+     FILE * fp;
+#endif
+{
+  if (!node)
+    return;
+  else
+    {
+      switch (node->type)
+	{
+	case r_cset:
+	  {
+	    fprintf (fp, "%*s", depth, "");
+	    print_cset (rx, node->params.cset, fp);
+	    fputc ('\n', fp);
+	    break;
+	  }
+
+ 	case r_opt:
+	case r_star:
+	  fprintf (fp, "%*s%s\n", depth, "",
+		   node->type == r_opt ? "opt" : "star");
+	  print_rexp (rx, node->params.pair.left, depth + 3, seprint, fp);
+	  break;
+
+	case r_2phase_star:
+	  fprintf (fp, "%*s2phase star\n", depth, "");
+	  print_rexp (rx, node->params.pair.right, depth + 3, seprint, fp);
+	  print_rexp (rx, node->params.pair.left, depth + 3, seprint, fp);
+	  break;
+
+
+	case r_alternate:
+	case r_concat:
+	  fprintf (fp, "%*s%s\n", depth, "",
+		   node->type == r_alternate ? "alt" : "concat");
+	  print_rexp (rx, node->params.pair.left, depth + 3, seprint, fp);
+	  print_rexp (rx, node->params.pair.right, depth + 3, seprint, fp);
+	  break;
+	case r_side_effect:
+	  fprintf (fp, "%*sSide effect: ", depth, "");
+	  seprint (rx, node->params.side_effect, fp);
+	  fputc ('\n', fp);
+	}
+    }
+}
+
+#ifdef __STDC__
+static void
+print_nfa (struct rx * rx,
+	   struct rx_nfa_state * n,
+	   side_effect_printer seprint, FILE * fp)
+#else
+static void
+print_nfa (rx, n, seprint, fp)
+     struct rx * rx;
+     struct rx_nfa_state * n;
+     side_effect_printer seprint;
+     FILE * fp;
+#endif
+{
+  while (n)
+    {
+      struct rx_nfa_edge *e = n->edges;
+      struct rx_possible_future *ec = n->futures;
+      fprintf (fp, "node %d %s\n", n->id,
+	       n->is_final ? "final" : (n->is_start ? "start" : ""));
+      while (e)
+	{
+	  fprintf (fp, "   edge to %d, ", e->dest->id);
+	  switch (e->type)
+	    {
+	    case ne_epsilon:
+	      fprintf (fp, "epsilon\n");
+	      break;
+	    case ne_side_effect:
+	      fprintf (fp, "side effect ");
+	      seprint (rx, e->params.side_effect, fp);
+	      fputc ('\n', fp);
+	      break;
+	    case ne_cset:
+	      fprintf (fp, "cset ");
+	      print_cset (rx, e->params.cset, fp);
+	      fputc ('\n', fp);
+	      break;
+	    }
+	  e = e->next;
+	}
+
+      while (ec)
+	{
+	  int x;
+	  struct rx_nfa_state_set * s;
+	  struct rx_se_list * l;
+	  fprintf (fp, "   eclosure to {");
+	  for (s = ec->destset; s; s = s->cdr)
+	    fprintf (fp, "%d ", s->car->id);
+	  fprintf (fp, "} (");
+	  for (l = ec->effects; l; l = l->cdr)
+	    {
+	      seprint (rx, l->car, fp);
+	      fputc (' ', fp);
+	    }
+	  fprintf (fp, ")\n");
+	  ec = ec->next;
+	}
+      n = n->next;
+    }
+}
+
+static char * efnames [] =
+{
+  "bogon",
+  "re_se_try",
+  "re_se_pushback",
+  "re_se_push0",
+  "re_se_pushpos",
+  "re_se_chkpos",
+  "re_se_poppos",
+  "re_se_at_dot",
+  "re_se_syntax",
+  "re_se_not_syntax",
+  "re_se_begbuf",
+  "re_se_hat",
+  "re_se_wordbeg",
+  "re_se_wordbound",
+  "re_se_notwordbound",
+  "re_se_wordend",
+  "re_se_endbuf",
+  "re_se_dollar",
+  "re_se_fail",
+};
+
+static char * efnames2[] =
+{
+  "re_se_win",
+  "re_se_lparen",
+  "re_se_rparen",
+  "re_se_backref",
+  "re_se_iter",
+  "re_se_end_iter",
+  "re_se_tv"
+};
+
+static char * inx_names[] = 
+{
+  "rx_backtrack_point",
+  "rx_do_side_effects",
+  "rx_cache_miss",
+  "rx_next_char",
+  "rx_backtrack",
+  "rx_error_inx",
+  "rx_num_instructions"
+};
+
+
+#ifdef __STDC__
+static void
+re_seprint (struct rx * rx, void * effect, FILE * fp)
+#else
+static void
+re_seprint (rx, effect, fp)
+     struct rx * rx;
+     void * effect;
+     FILE * fp;
+#endif
+{
+  if ((int)effect < 0)
+    fputs (efnames[-(int)effect], fp);
+  else if (dbug_rxb)
+    {
+      struct re_se_params * p = &dbug_rxb->se_params[(int)effect];
+      fprintf (fp, "%s(%d,%d)", efnames2[p->se], p->op1, p->op2);
+    }
+  else
+    fprintf (fp, "[complex op # %d]", (int)effect);
+}
+
+
+/* These are so the regex.c regression tests will compile. */
+void
+print_compiled_pattern (rxb)
+     struct re_pattern_buffer * rxb;
+{
+}
+
+void
+print_fastmap (fm)
+     char * fm;
+{
+}
+
+#endif /* RX_DEBUG */
+
+
+
+
+/* This page: Bitsets.  Completely unintersting. */
+
+#ifdef __STDC__
+RX_DECL int
+rx_bitset_is_equal (int size, rx_Bitset a, rx_Bitset b)
+#else
+RX_DECL int
+rx_bitset_is_equal (size, a, b)
+     int size;
+     rx_Bitset a;
+     rx_Bitset b;
+#endif
+{
+  int x;
+  RX_subset s = b[0];
+  b[0] = ~a[0];
+
+  for (x = rx_bitset_numb_subsets(size) - 1; a[x] == b[x]; --x)
+    ;
+
+  b[0] = s;
+  return !x && s == a[0];
+}
+
+#ifdef __STDC__
+RX_DECL int
+rx_bitset_is_subset (int size, rx_Bitset a, rx_Bitset b)
+#else
+RX_DECL int
+rx_bitset_is_subset (size, a, b)
+     int size;
+     rx_Bitset a;
+     rx_Bitset b;
+#endif
+{
+  int x = rx_bitset_numb_subsets(size) - 1;
+  while (x-- && (a[x] & b[x]) == a[x]);
+  return x == -1;
+}
+
+
+#ifdef __STDC__
+RX_DECL int
+rx_bitset_empty (int size, rx_Bitset set)
+#else
+RX_DECL int
+rx_bitset_empty (size, set)
+     int size;
+     rx_Bitset set;
+#endif
+{
+  int x;
+  RX_subset s = set[0];
+  set[0] = 1;
+  for (x = rx_bitset_numb_subsets(size) - 1; !set[x]; --x)
+    ;
+  set[0] = s;
+  return !s;
+}
+
+#ifdef __STDC__
+RX_DECL void
+rx_bitset_null (int size, rx_Bitset b)
+#else
+RX_DECL void
+rx_bitset_null (size, b)
+     int size;
+     rx_Bitset b;
+#endif
+{
+  bzero (b, rx_sizeof_bitset(size));
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_bitset_universe (int size, rx_Bitset b)
+#else
+RX_DECL void
+rx_bitset_universe (size, b)
+     int size;
+     rx_Bitset b;
+#endif
+{
+  int x = rx_bitset_numb_subsets (size);
+  while (x--)
+    *b++ = ~(RX_subset)0;
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_bitset_complement (int size, rx_Bitset b)
+#else
+RX_DECL void
+rx_bitset_complement (size, b)
+     int size;
+     rx_Bitset b;
+#endif
+{
+  int x = rx_bitset_numb_subsets (size);
+  while (x--)
+    {
+      *b = ~*b;
+      ++b;
+    }
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_bitset_assign (int size, rx_Bitset a, rx_Bitset b)
+#else
+RX_DECL void
+rx_bitset_assign (size, a, b)
+     int size;
+     rx_Bitset a;
+     rx_Bitset b;
+#endif
+{
+  int x;
+  for (x = rx_bitset_numb_subsets(size) - 1; x >=0; --x)
+    a[x] = b[x];
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_bitset_union (int size, rx_Bitset a, rx_Bitset b)
+#else
+RX_DECL void
+rx_bitset_union (size, a, b)
+     int size;
+     rx_Bitset a;
+     rx_Bitset b;
+#endif
+{
+  int x;
+  for (x = rx_bitset_numb_subsets(size) - 1; x >=0; --x)
+    a[x] |= b[x];
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_bitset_intersection (int size,
+			rx_Bitset a, rx_Bitset b)
+#else
+RX_DECL void
+rx_bitset_intersection (size, a, b)
+     int size;
+     rx_Bitset a;
+     rx_Bitset b;
+#endif
+{
+  int x;
+  for (x = rx_bitset_numb_subsets(size) - 1; x >=0; --x)
+    a[x] &= b[x];
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_bitset_difference (int size, rx_Bitset a, rx_Bitset b)
+#else
+RX_DECL void
+rx_bitset_difference (size, a, b)
+     int size;
+     rx_Bitset a;
+     rx_Bitset b;
+#endif
+{
+  int x;
+  for (x = rx_bitset_numb_subsets(size) - 1; x >=0; --x)
+    a[x] &=  ~ b[x];
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_bitset_revdifference (int size,
+			 rx_Bitset a, rx_Bitset b)
+#else
+RX_DECL void
+rx_bitset_revdifference (size, a, b)
+     int size;
+     rx_Bitset a;
+     rx_Bitset b;
+#endif
+{
+  int x;
+  for (x = rx_bitset_numb_subsets(size) - 1; x >=0; --x)
+    a[x] = ~a[x] & b[x];
+}
+
+#ifdef __STDC__
+RX_DECL void
+rx_bitset_xor (int size, rx_Bitset a, rx_Bitset b)
+#else
+RX_DECL void
+rx_bitset_xor (size, a, b)
+     int size;
+     rx_Bitset a;
+     rx_Bitset b;
+#endif
+{
+  int x;
+  for (x = rx_bitset_numb_subsets(size) - 1; x >=0; --x)
+    a[x] ^= b[x];
+}
+
+
+#ifdef __STDC__
+RX_DECL unsigned long
+rx_bitset_hash (int size, rx_Bitset b)
+#else
+RX_DECL unsigned long
+rx_bitset_hash (size, b)
+     int size;
+     rx_Bitset b;
+#endif
+{
+  int x;
+  unsigned long hash = (unsigned long)rx_bitset_hash;
+
+  for (x = rx_bitset_numb_subsets(size) - 1; x >= 0; --x)
+    hash ^= rx_bitset_subset_val(b, x);
+
+  return hash;
+}
+
+
+RX_DECL RX_subset rx_subset_singletons [RX_subset_bits] = 
+{
+  0x1,
+  0x2,
+  0x4,
+  0x8,
+  0x10,
+  0x20,
+  0x40,
+  0x80,
+  0x100,
+  0x200,
+  0x400,
+  0x800,
+  0x1000,
+  0x2000,
+  0x4000,
+  0x8000,
+  0x10000,
+  0x20000,
+  0x40000,
+  0x80000,
+  0x100000,
+  0x200000,
+  0x400000,
+  0x800000,
+  0x1000000,
+  0x2000000,
+  0x4000000,
+  0x8000000,
+  0x10000000,
+  0x20000000,
+  0x40000000,
+  0x80000000
+};
+
+#ifdef RX_DEBUG
+
+#ifdef __STDC__
+static void
+print_cset (struct rx *rx, rx_Bitset cset, FILE * fp)
+#else
+static void
+print_cset (rx, cset, fp)
+     struct rx *rx;
+     rx_Bitset cset;
+     FILE * fp;
+#endif
+{
+  int x;
+  fputc ('[', fp);
+  for (x = 0; x < rx->local_cset_size; ++x)
+    if (RX_bitset_member (cset, x))
+      {
+	if (isprint(x))
+	  fputc (x, fp);
+	else
+	  fprintf (fp, "\\0%o ", x);
+      }
+  fputc (']', fp);
+}
+
+#endif /*  RX_DEBUG */
+
+
+
+
+static unsigned long rx_hash_masks[4] =
+{
+  0x12488421,
+  0x96699669,
+  0xbe7dd7eb,
+  0xffffffff
+};
+
+
+/* Hash tables */
+#ifdef __STDC__
+RX_DECL struct rx_hash_item * 
+rx_hash_find (struct rx_hash * table,
+	      unsigned long hash,
+	      void * value,
+	      struct rx_hash_rules * rules)
+#else
+RX_DECL struct rx_hash_item * 
+rx_hash_find (table, hash, value, rules)
+     struct rx_hash * table;
+     unsigned long hash;
+     void * value;
+     struct rx_hash_rules * rules;
+#endif
+{
+  rx_hash_eq eq = rules->eq;
+  int maskc = 0;
+  long mask = rx_hash_masks [0];
+  int bucket = (hash & mask) % 13;
+
+  while (table->children [bucket])
+    {
+      table = table->children [bucket];
+      ++maskc;
+      mask = rx_hash_masks[maskc];
+      bucket = (hash & mask) % 13;
+    }
+
+  {
+    struct rx_hash_item * it = table->buckets[bucket];
+    while (it)
+      if (eq (it->data, value))
+	return it;
+      else
+	it = it->next_same_hash;
+  }
+
+  return 0;
+}
+
+
+#ifdef __STDC__
+RX_DECL struct rx_hash_item *
+rx_hash_store (struct rx_hash * table,
+	       unsigned long hash,
+	       void * value,
+	       struct rx_hash_rules * rules)
+#else
+RX_DECL struct rx_hash_item *
+rx_hash_store (table, hash, value, rules)
+     struct rx_hash * table;
+     unsigned long hash;
+     void * value;
+     struct rx_hash_rules * rules;
+#endif
+{
+  rx_hash_eq eq = rules->eq;
+  int maskc = 0;
+  long mask = rx_hash_masks[0];
+  int bucket = (hash & mask) % 13;
+  int depth = 0;
+  
+  while (table->children [bucket])
+    {
+      table = table->children [bucket];
+      ++maskc;
+      mask = rx_hash_masks[maskc];
+      bucket = (hash & mask) % 13;
+      ++depth;
+    }
+  
+  {
+    struct rx_hash_item * it = table->buckets[bucket];
+    while (it)
+      if (eq (it->data, value))
+	return it;
+      else
+	it = it->next_same_hash;
+  }
+  
+  {
+    if (   (depth < 3)
+	&& (table->bucket_size [bucket] >= 4))
+      {
+	struct rx_hash * newtab = ((struct rx_hash *)
+				   rules->hash_alloc (rules));
+	if (!newtab)
+	  goto add_to_bucket;
+	bzero (newtab, sizeof (*newtab));
+	newtab->parent = table;
+	{
+	  struct rx_hash_item * them = table->buckets[bucket];
+	  unsigned long newmask = rx_hash_masks[maskc + 1];
+	  while (them)
+	    {
+	      struct rx_hash_item * save = them->next_same_hash;
+	      int new_buck = (them->hash & newmask) % 13;
+	      them->next_same_hash = newtab->buckets[new_buck];
+	      newtab->buckets[new_buck] = them;
+	      them->table = newtab;
+	      them = save;
+	      ++newtab->bucket_size[new_buck];
+	      ++newtab->refs;
+	    }
+	  table->refs = (table->refs - table->bucket_size[bucket] + 1);
+	  table->bucket_size[bucket] = 0;
+	  table->buckets[bucket] = 0;
+	  table->children[bucket] = newtab;
+	  table = newtab;
+	  bucket = (hash & newmask) % 13;
+	}
+      }
+  }
+ add_to_bucket:
+  {
+    struct rx_hash_item  * it = ((struct rx_hash_item *)
+				 rules->hash_item_alloc (rules, value));
+    if (!it)
+      return 0;
+    it->hash = hash;
+    it->table = table;
+    /* DATA and BINDING are to be set in hash_item_alloc */
+    it->next_same_hash = table->buckets [bucket];
+    table->buckets[bucket] = it;
+    ++table->bucket_size [bucket];
+    ++table->refs;
+    return it;
+  }
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_hash_free (struct rx_hash_item * it, struct rx_hash_rules * rules)
+#else
+RX_DECL void
+rx_hash_free (it, rules)
+     struct rx_hash_item * it;
+     struct rx_hash_rules * rules;
+#endif
+{
+  if (it)
+    {
+      struct rx_hash * table = it->table;
+      unsigned long hash = it->hash;
+      int depth = (table->parent
+		   ? (table->parent->parent
+		      ? (table->parent->parent->parent
+			 ? 3
+			 : 2)
+		      : 1)
+		   : 0);
+      int bucket = (hash & rx_hash_masks [depth]) % 13;
+      struct rx_hash_item ** pos = &table->buckets [bucket];
+      
+      while (*pos != it)
+	pos = &(*pos)->next_same_hash;
+      *pos = it->next_same_hash;
+      rules->free_hash_item (it, rules);
+      --table->bucket_size[bucket];
+      --table->refs;
+      while (!table->refs && depth)
+	{
+	  struct rx_hash * save = table;
+	  table = table->parent;
+	  --depth;
+	  bucket = (hash & rx_hash_masks [depth]) % 13;
+	  --table->refs;
+	  table->children[bucket] = 0;
+	  rules->free_hash (save, rules);
+	}
+    }
+}
+
+#ifdef __STDC__
+RX_DECL void
+rx_free_hash_table (struct rx_hash * tab, rx_hash_freefn freefn,
+		    struct rx_hash_rules * rules)
+#else
+RX_DECL void
+rx_free_hash_table (tab, freefn, rules)
+     struct rx_hash * tab;
+     rx_hash_freefn freefn;
+     struct rx_hash_rules * rules;
+#endif
+{
+  int x;
+
+  for (x = 0; x < 13; ++x)
+    if (tab->children[x])
+      {
+	rx_free_hash_table (tab->children[x], freefn, rules);
+	rules->free_hash (tab->children[x], rules);
+      }
+    else
+      {
+	struct rx_hash_item * them = tab->buckets[x];
+	while (them)
+	  {
+	    struct rx_hash_item * that = them;
+	    them = that->next_same_hash;
+	    freefn (that);
+	    rules->free_hash_item (that, rules);
+	  }
+      }
+}
+
+
+
+
+/* Utilities for manipulating bitset represntations of characters sets. */
+
+#ifdef __STDC__
+RX_DECL rx_Bitset
+rx_cset (struct rx *rx)
+#else
+RX_DECL rx_Bitset
+rx_cset (rx)
+     struct rx *rx;
+#endif
+{
+  rx_Bitset b = (rx_Bitset) malloc (rx_sizeof_bitset (rx->local_cset_size));
+  if (b)
+    rx_bitset_null (rx->local_cset_size, b);
+  return b;
+}
+
+
+#ifdef __STDC__
+RX_DECL rx_Bitset
+rx_copy_cset (struct rx *rx, rx_Bitset a)
+#else
+RX_DECL rx_Bitset
+rx_copy_cset (rx, a)
+     struct rx *rx;
+     rx_Bitset a;
+#endif
+{
+  rx_Bitset cs = rx_cset (rx);
+
+  if (cs)
+    rx_bitset_union (rx->local_cset_size, cs, a);
+
+  return cs;
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_free_cset (struct rx * rx, rx_Bitset c)
+#else
+RX_DECL void
+rx_free_cset (rx, c)
+     struct rx * rx;
+     rx_Bitset c;
+#endif
+{
+  if (c)
+    free ((char *)c);
+}
+
+
+
+/* Hash table memory allocation policy for the regexp compiler */
+
+#ifdef __STDC__
+static struct rx_hash *
+compiler_hash_alloc (struct rx_hash_rules * rules)
+#else
+static struct rx_hash *
+compiler_hash_alloc (rules)
+     struct rx_hash_rules * rules;
+#endif
+{
+  return (struct rx_hash *)malloc (sizeof (struct rx_hash));
+}
+
+
+#ifdef __STDC__
+static struct rx_hash_item *
+compiler_hash_item_alloc (struct rx_hash_rules * rules, void * value)
+#else
+static struct rx_hash_item *
+compiler_hash_item_alloc (rules, value)
+     struct rx_hash_rules * rules;
+     void * value;
+#endif
+{
+  struct rx_hash_item * it;
+  it = (struct rx_hash_item *)malloc (sizeof (*it));
+  if (it)
+    {
+      it->data = value;
+      it->binding = 0;
+    }
+  return it;
+}
+
+
+#ifdef __STDC__
+static void
+compiler_free_hash (struct rx_hash * tab,
+		    struct rx_hash_rules * rules)
+#else
+static void
+compiler_free_hash (tab, rules)
+     struct rx_hash * tab;
+     struct rx_hash_rules * rules;
+#endif
+{
+  free ((char *)tab);
+}
+
+
+#ifdef __STDC__
+static void
+compiler_free_hash_item (struct rx_hash_item * item,
+			 struct rx_hash_rules * rules)
+#else
+static void
+compiler_free_hash_item (item, rules)
+     struct rx_hash_item * item;
+     struct rx_hash_rules * rules;
+#endif
+{
+  free ((char *)item);
+}
+
+
+
+/* This page: REXP_NODE (expression tree) structures. */
+
+#ifdef __STDC__
+RX_DECL struct rexp_node *
+rexp_node (struct rx *rx,
+	   enum rexp_node_type type)
+#else
+RX_DECL struct rexp_node *
+rexp_node (rx, type)
+     struct rx *rx;
+     enum rexp_node_type type;
+#endif
+{
+  struct rexp_node *n;
+
+  n = (struct rexp_node *)malloc (sizeof (*n));
+  bzero (n, sizeof (*n));
+  if (n)
+    n->type = type;
+  return n;
+}
+
+
+/* free_rexp_node assumes that the bitset passed to rx_mk_r_cset
+ * can be freed using rx_free_cset.
+ */
+#ifdef __STDC__
+RX_DECL struct rexp_node *
+rx_mk_r_cset (struct rx * rx,
+	      rx_Bitset b)
+#else
+RX_DECL struct rexp_node *
+rx_mk_r_cset (rx, b)
+     struct rx * rx;
+     rx_Bitset b;
+#endif
+{
+  struct rexp_node * n = rexp_node (rx, r_cset);
+  if (n)
+    n->params.cset = b;
+  return n;
+}
+
+
+#ifdef __STDC__
+RX_DECL struct rexp_node *
+rx_mk_r_concat (struct rx * rx,
+		struct rexp_node * a,
+		struct rexp_node * b)
+#else
+RX_DECL struct rexp_node *
+rx_mk_r_concat (rx, a, b)
+     struct rx * rx;
+     struct rexp_node * a;
+     struct rexp_node * b;
+#endif
+{
+  struct rexp_node * n = rexp_node (rx, r_concat);
+  if (n)
+    {
+      n->params.pair.left = a;
+      n->params.pair.right = b;
+    }
+  return n;
+}
+
+
+#ifdef __STDC__
+RX_DECL struct rexp_node *
+rx_mk_r_alternate (struct rx * rx,
+		   struct rexp_node * a,
+		   struct rexp_node * b)
+#else
+RX_DECL struct rexp_node *
+rx_mk_r_alternate (rx, a, b)
+     struct rx * rx;
+     struct rexp_node * a;
+     struct rexp_node * b;
+#endif
+{
+  struct rexp_node * n = rexp_node (rx, r_alternate);
+  if (n)
+    {
+      n->params.pair.left = a;
+      n->params.pair.right = b;
+    }
+  return n;
+}
+
+
+#ifdef __STDC__
+RX_DECL struct rexp_node *
+rx_mk_r_opt (struct rx * rx,
+	     struct rexp_node * a)
+#else
+RX_DECL struct rexp_node *
+rx_mk_r_opt (rx, a)
+     struct rx * rx;
+     struct rexp_node * a;
+#endif
+{
+  struct rexp_node * n = rexp_node (rx, r_opt);
+  if (n)
+    {
+      n->params.pair.left = a;
+      n->params.pair.right = 0;
+    }
+  return n;
+}
+
+
+#ifdef __STDC__
+RX_DECL struct rexp_node *
+rx_mk_r_star (struct rx * rx,
+	      struct rexp_node * a)
+#else
+RX_DECL struct rexp_node *
+rx_mk_r_star (rx, a)
+     struct rx * rx;
+     struct rexp_node * a;
+#endif
+{
+  struct rexp_node * n = rexp_node (rx, r_star);
+  if (n)
+    {
+      n->params.pair.left = a;
+      n->params.pair.right = 0;
+    }
+  return n;
+}
+
+
+#ifdef __STDC__
+RX_DECL struct rexp_node *
+rx_mk_r_2phase_star (struct rx * rx,
+		     struct rexp_node * a,
+		     struct rexp_node * b)
+#else
+RX_DECL struct rexp_node *
+rx_mk_r_2phase_star (rx, a, b)
+     struct rx * rx;
+     struct rexp_node * a;
+     struct rexp_node * b;
+#endif
+{
+  struct rexp_node * n = rexp_node (rx, r_2phase_star);
+  if (n)
+    {
+      n->params.pair.left = a;
+      n->params.pair.right = b;
+    }
+  return n;
+}
+
+
+#ifdef __STDC__
+RX_DECL struct rexp_node *
+rx_mk_r_side_effect (struct rx * rx,
+		     rx_side_effect a)
+#else
+RX_DECL struct rexp_node *
+rx_mk_r_side_effect (rx, a)
+     struct rx * rx;
+     rx_side_effect a;
+#endif
+{
+  struct rexp_node * n = rexp_node (rx, r_side_effect);
+  if (n)
+    {
+      n->params.side_effect = a;
+      n->params.pair.right = 0;
+    }
+  return n;
+}
+
+
+#ifdef __STDC__
+RX_DECL struct rexp_node *
+rx_mk_r_data  (struct rx * rx,
+	       void * a)
+#else
+RX_DECL struct rexp_node *
+rx_mk_r_data  (rx, a)
+     struct rx * rx;
+     void * a;
+#endif
+{
+  struct rexp_node * n = rexp_node (rx, r_data);
+  if (n)
+    {
+      n->params.pair.left = a;
+      n->params.pair.right = 0;
+    }
+  return n;
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_free_rexp (struct rx * rx, struct rexp_node * node)
+#else
+RX_DECL void
+rx_free_rexp (rx, node)
+     struct rx * rx;
+     struct rexp_node * node;
+#endif
+{
+  if (node)
+    {
+      switch (node->type)
+	{
+	case r_cset:
+	  if (node->params.cset)
+	    rx_free_cset (rx, node->params.cset);
+
+	case r_side_effect:
+	  break;
+	  
+	case r_concat:
+	case r_alternate:
+	case r_2phase_star:
+	case r_opt:
+	case r_star:
+	  rx_free_rexp (rx, node->params.pair.left);
+	  rx_free_rexp (rx, node->params.pair.right);
+	  break;
+
+	case r_data:
+	  /* This shouldn't occur. */
+	  break;
+	}
+      free ((char *)node);
+    }
+}
+
+
+#ifdef __STDC__
+RX_DECL struct rexp_node * 
+rx_copy_rexp (struct rx *rx,
+	   struct rexp_node *node)
+#else
+RX_DECL struct rexp_node * 
+rx_copy_rexp (rx, node)
+     struct rx *rx;
+     struct rexp_node *node;
+#endif
+{
+  if (!node)
+    return 0;
+  else
+    {
+      struct rexp_node *n = rexp_node (rx, node->type);
+      if (!n)
+	return 0;
+      switch (node->type)
+	{
+	case r_cset:
+	  n->params.cset = rx_copy_cset (rx, node->params.cset);
+	  if (!n->params.cset)
+	    {
+	      rx_free_rexp (rx, n);
+	      return 0;
+	    }
+	  break;
+
+	case r_side_effect:
+	  n->params.side_effect = node->params.side_effect;
+	  break;
+
+	case r_concat:
+	case r_alternate:
+	case r_opt:
+	case r_2phase_star:
+	case r_star:
+	  n->params.pair.left =
+	    rx_copy_rexp (rx, node->params.pair.left);
+	  n->params.pair.right =
+	    rx_copy_rexp (rx, node->params.pair.right);
+	  if (   (node->params.pair.left && !n->params.pair.left)
+	      || (node->params.pair.right && !n->params.pair.right))
+	    {
+	      rx_free_rexp  (rx, n);
+	      return 0;
+	    }
+	  break;
+	case r_data:
+	  /* shouldn't happen */
+	  break;
+	}
+      return n;
+    }
+}
+
+
+
+
+/* This page: functions to build and destroy graphs that describe nfa's */
+
+/* Constructs a new nfa node. */
+#ifdef __STDC__
+RX_DECL struct rx_nfa_state *
+rx_nfa_state (struct rx *rx)
+#else
+RX_DECL struct rx_nfa_state *
+rx_nfa_state (rx)
+     struct rx *rx;
+#endif
+{
+  struct rx_nfa_state * n = (struct rx_nfa_state *)malloc (sizeof (*n));
+  if (!n)
+    return 0;
+  bzero (n, sizeof (*n));
+  n->next = rx->nfa_states;
+  rx->nfa_states = n;
+  return n;
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_free_nfa_state (struct rx_nfa_state * n)
+#else
+RX_DECL void
+rx_free_nfa_state (n)
+  struct rx_nfa_state * n;
+#endif
+{
+  free ((char *)n);
+}
+
+
+/* This looks up an nfa node, given a numeric id.  Numeric id's are
+ * assigned after the nfa has been built.
+ */
+#ifdef __STDC__
+RX_DECL struct rx_nfa_state * 
+rx_id_to_nfa_state (struct rx * rx,
+		    int id)
+#else
+RX_DECL struct rx_nfa_state * 
+rx_id_to_nfa_state (rx, id)
+     struct rx * rx;
+     int id;
+#endif
+{
+  struct rx_nfa_state * n;
+  for (n = rx->nfa_states; n; n = n->next)
+    if (n->id == id)
+      return n;
+  return 0;
+}
+
+
+/* This adds an edge between two nodes, but doesn't initialize the 
+ * edge label.
+ */
+
+#ifdef __STDC__
+RX_DECL struct rx_nfa_edge * 
+rx_nfa_edge (struct rx *rx,
+	     enum rx_nfa_etype type,
+	     struct rx_nfa_state *start,
+	     struct rx_nfa_state *dest)
+#else
+RX_DECL struct rx_nfa_edge * 
+rx_nfa_edge (rx, type, start, dest)
+     struct rx *rx;
+     enum rx_nfa_etype type;
+     struct rx_nfa_state *start;
+     struct rx_nfa_state *dest;
+#endif
+{
+  struct rx_nfa_edge *e;
+  e = (struct rx_nfa_edge *)malloc (sizeof (*e));
+  if (!e)
+    return 0;
+  e->next = start->edges;
+  start->edges = e;
+  e->type = type;
+  e->dest = dest;
+  return e;
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_free_nfa_edge (struct rx_nfa_edge * e)
+#else
+RX_DECL void
+rx_free_nfa_edge (e)
+     struct rx_nfa_edge * e;
+#endif
+{
+  free ((char *)e);
+}
+
+
+/* This constructs a POSSIBLE_FUTURE, which is a kind epsilon-closure
+ * of an NFA.  These are added to an nfa automaticly by eclose_nfa.
+ */  
+
+#ifdef __STDC__
+static struct rx_possible_future * 
+rx_possible_future (struct rx * rx,
+		 struct rx_se_list * effects)
+#else
+static struct rx_possible_future * 
+rx_possible_future (rx, effects)
+     struct rx * rx;
+     struct rx_se_list * effects;
+#endif
+{
+  struct rx_possible_future *ec;
+  ec = (struct rx_possible_future *) malloc (sizeof (*ec));
+  if (!ec)
+    return 0;
+  ec->destset = 0;
+  ec->next = 0;
+  ec->effects = effects;
+  return ec;
+}
+
+
+#ifdef __STDC__
+static void
+rx_free_possible_future (struct rx_possible_future * pf)
+#else
+static void
+rx_free_possible_future (pf)
+     struct rx_possible_future * pf;
+#endif
+{
+  free ((char *)pf);
+}
+
+
+#ifdef __STDC__
+RX_DECL void
+rx_free_nfa (struct rx *rx)
+#else
+RX_DECL void
+rx_free_nfa (rx)
+     struct rx *rx;
+#endif
+{
+  while (rx->nfa_states)
+    {
+      while (rx->nfa_states->edges)
+	{
+	  switch (rx->nfa_states->edges->type)
+	    {
+	    case ne_cset:
+	      rx_free_cset (rx, rx->nfa_states->edges->params.cset);
+	      break;
+	    default:
+	      break;
+	    }
+	  {
+	    struct rx_nfa_edge * e;
+	    e = rx->nfa_states->edges;
+	    rx->nfa_states->edges = rx->nfa_states->edges->next;
+	    rx_free_nfa_edge (e);
+	  }
+	} /* while (rx->nfa_states->edges) */
+      {
+	/* Iterate over the partial epsilon closures of rx->nfa_states */
+	struct rx_possible_future * pf = rx->nfa_states->futures;
+	while (pf)
+	  {
+	    struct rx_possible_future * pft = pf;
+	    pf = pf->next;
+	    rx_free_possible_future (pft);
+	  }
+      }
+      {
+	struct rx_nfa_state *n;
+	n = rx->nfa_states;
+	rx->nfa_states = rx->nfa_states->next;
+	rx_free_nfa_state (n);
+      }
+    }
+}
+
+
+
+
+/* This page: translating a pattern expression into an nfa and doing the 
+ * static part of the nfa->super-nfa translation.
+ */
+
+/* This is the thompson regexp->nfa algorithm. 
+ * It is modified to allow for `side-effect epsilons.'  Those are
+ * edges that are taken whenever a similar epsilon edge would be,
+ * but which imply that some side effect occurs when the edge 
+ * is taken.
+ *
+ * Side effects are used to model parts of the pattern langauge 
+ * that are not regular (in the formal sense).
+ */
+
+#ifdef __STDC__
+RX_DECL int
+rx_build_nfa (struct rx *rx,
+	      struct rexp_node *rexp,
+	      struct rx_nfa_state **start,
+	      struct rx_nfa_state **end)
+#else
+RX_DECL int
+rx_build_nfa (rx, rexp, start, end)
+     struct rx *rx;
+     struct rexp_node *rexp;
+     struct rx_nfa_state **start;
+     struct rx_nfa_state **end;
+#endif
+{
+  struct rx_nfa_edge *edge;
+
+  /* Start & end nodes may have been allocated by the caller. */
+  *start = *start ? *start : rx_nfa_state (rx);
+
+  if (!*start)
+    return 0;
+
+  if (!rexp)
+    {
+      *end = *start;
+      return 1;
+    }
+
+  *end = *end ? *end : rx_nfa_state (rx);
+
+  if (!*end)
+    {
+      rx_free_nfa_state (*start);
+      return 0;
+    }
+
+  switch (rexp->type)
+    {
+    case r_data:
+      return 0;
+
+    case r_cset:
+      edge = rx_nfa_edge (rx, ne_cset, *start, *end);
+      if (!edge)
+	return 0;
+      edge->params.cset = rx_copy_cset (rx, rexp->params.cset);
+      if (!edge->params.cset)
+	{
+	  rx_free_nfa_edge (edge);
+	  return 0;
+	}
+      return 1;
+ 
+    case r_opt:
+      return (rx_build_nfa (rx, rexp->params.pair.left, start, end)
+	      && rx_nfa_edge (rx, ne_epsilon, *start, *end));
+
+    case r_star:
+      {
+	struct rx_nfa_state * star_start = 0;
+	struct rx_nfa_state * star_end = 0;
+	return (rx_build_nfa (rx, rexp->params.pair.left,
+			      &star_start, &star_end)
+		&& star_start
+		&& star_end
+		&& rx_nfa_edge (rx, ne_epsilon, star_start, star_end)
+		&& rx_nfa_edge (rx, ne_epsilon, *start, star_start)
+		&& rx_nfa_edge (rx, ne_epsilon, star_end, *end)
+
+		&& rx_nfa_edge (rx, ne_epsilon, star_end, star_start));
+      }
+
+    case r_2phase_star:
+      {
+	struct rx_nfa_state * star_start = 0;
+	struct rx_nfa_state * star_end = 0;
+	struct rx_nfa_state * loop_exp_start = 0;
+	struct rx_nfa_state * loop_exp_end = 0;
+
+	return (rx_build_nfa (rx, rexp->params.pair.left,
+			      &star_start, &star_end)
+		&& rx_build_nfa (rx, rexp->params.pair.right,
+				 &loop_exp_start, &loop_exp_end)
+		&& star_start
+		&& star_end
+		&& loop_exp_end
+		&& loop_exp_start
+		&& rx_nfa_edge (rx, ne_epsilon, star_start, *end)
+		&& rx_nfa_edge (rx, ne_epsilon, *start, star_start)
+		&& rx_nfa_edge (rx, ne_epsilon, star_end, *end)
+
+		&& rx_nfa_edge (rx, ne_epsilon, star_end, loop_exp_start)
+		&& rx_nfa_edge (rx, ne_epsilon, loop_exp_end, star_start));
+      }
+
+
+    case r_concat:
+      {
+	struct rx_nfa_state *shared = 0;
+	return
+	  (rx_build_nfa (rx, rexp->params.pair.left, start, &shared)
+	   && rx_build_nfa (rx, rexp->params.pair.right, &shared, end));
+      }
+
+    case r_alternate:
+      {
+	struct rx_nfa_state *ls = 0;
+	struct rx_nfa_state *le = 0;
+	struct rx_nfa_state *rs = 0;
+	struct rx_nfa_state *re = 0;
+	return (rx_build_nfa (rx, rexp->params.pair.left, &ls, &le)
+		&& rx_build_nfa (rx, rexp->params.pair.right, &rs, &re)
+		&& rx_nfa_edge (rx, ne_epsilon, *start, ls)
+		&& rx_nfa_edge (rx, ne_epsilon, *start, rs)
+		&& rx_nfa_edge (rx, ne_epsilon, le, *end)
+		&& rx_nfa_edge (rx, ne_epsilon, re, *end));
+      }
+
+    case r_side_effect:
+      edge = rx_nfa_edge (rx, ne_side_effect, *start, *end);
+      if (!edge)
+	return 0;
+      edge->params.side_effect = rexp->params.side_effect;
+      return 1;
+    }
+
+  /* this should never happen */
+  return 0;
+}
+
+
+/* RX_NAME_NFA_STATES identifies all nodes with outgoing non-epsilon
+ * transitions.  Only these nodes can occur in super-states.  
+ * All nodes are given an integer id. 
+ * The id is non-negative if the node has non-epsilon out-transitions, negative
+ * otherwise (this is because we want the non-negative ids to be used as 
+ * array indexes in a few places).
+ */
+
+#ifdef __STDC__
+RX_DECL void
+rx_name_nfa_states (struct rx *rx)
+#else
+RX_DECL void
+rx_name_nfa_states (rx)
+     struct rx *rx;
+#endif
+{
+  struct rx_nfa_state *n = rx->nfa_states;
+
+  rx->nodec = 0;
+  rx->epsnodec = -1;
+
+  while (n)
+    {
+      struct rx_nfa_edge *e = n->edges;
+
+      if (n->is_start)
+	n->eclosure_needed = 1;
+
+      while (e)
+	{
+	  switch (e->type)
+	    {
+	    case ne_epsilon:
+	    case ne_side_effect:
+	      break;
+
+	    case ne_cset:
+	      n->id = rx->nodec++;
+	      {
+		struct rx_nfa_edge *from_n = n->edges;
+		while (from_n)
+		  {
+		    from_n->dest->eclosure_needed = 1;
+		    from_n = from_n->next;
+		  }
+	      }
+	      goto cont;
+	    }
+	  e = e->next;
+	}
+      n->id = rx->epsnodec--;
+    cont:
+      n = n->next;
+    }
+  rx->epsnodec = -rx->epsnodec;
+}
+
+
+
+/* This page: data structures for the static part of the nfa->supernfa
+ * translation.
+ *
+ * There are side effect lists -- lists of side effects occuring
+ * along an uninterrupted, acyclic path of side-effect epsilon edges.
+ * Such paths are collapsed to single edges in the course of computing
+ * epsilon closures.  Such single edges are labled with a list of all
+ * the side effects entailed in crossing them.  Like lists of side
+ * effects are made == by the constructors below.
+ *
+ * There are also nfa state sets.  These are used to hold a list of all
+ * states reachable from a starting state for a given type of transition
+ * and side effect list.   These are also hash-consed.
+ */
+
+/* The next several functions compare, construct, etc. lists of side
+ * effects.  See ECLOSE_NFA (below) for details.
+ */
+
+/* Ordering of rx_se_list
+ * (-1, 0, 1 return value convention).
+ */
+
+#ifdef __STDC__
+static int 
+se_list_cmp (void * va, void * vb)
+#else
+static int 
+se_list_cmp (va, vb)
+     void * va;
+     void * vb;
+#endif
+{
+  struct rx_se_list * a = (struct rx_se_list *)va;
+  struct rx_se_list * b = (struct rx_se_list *)vb;
+
+  return ((va == vb)
+	  ? 0
+	  : (!va
+	     ? -1
+	     : (!vb
+		? 1
+		: ((long)a->car < (long)b->car
+		   ? 1
+		   : ((long)a->car > (long)b->car
+		      ? -1
+		      : se_list_cmp ((void *)a->cdr, (void *)b->cdr))))));
+}
+
+
+#ifdef __STDC__
+static int 
+se_list_equal (void * va, void * vb)
+#else
+static int 
+se_list_equal (va, vb)
+     void * va;
+     void * vb;
+#endif
+{
+  return !(se_list_cmp (va, vb));
+}
+
+static struct rx_hash_rules se_list_hash_rules =
+{
+  se_list_equal,
+  compiler_hash_alloc,
+  compiler_free_hash,
+  compiler_hash_item_alloc,
+  compiler_free_hash_item
+};
+
+
+#ifdef __STDC__
+static struct rx_se_list * 
+side_effect_cons (struct rx * rx,
+		  void * se, struct rx_se_list * list)
+#else
+static struct rx_se_list * 
+side_effect_cons (rx, se, list)
+     struct rx * rx;
+     void * se;
+     struct rx_se_list * list;
+#endif
+{
+  struct rx_se_list * l;
+  l = ((struct rx_se_list *) malloc (sizeof (*l)));
+  if (!l)
+    return 0;
+  l->car = se;
+  l->cdr = list;
+  return l;
+}
+
+
+#ifdef __STDC__
+static struct rx_se_list *
+hash_cons_se_prog (struct rx * rx,
+		   struct rx_hash * memo,
+		   void * car, struct rx_se_list * cdr)
+#else
+static struct rx_se_list *
+hash_cons_se_prog (rx, memo, car, cdr)
+     struct rx * rx;
+     struct rx_hash * memo;
+     void * car;
+     struct rx_se_list * cdr;
+#endif
+{
+  long hash = (long)car ^ (long)cdr;
+  struct rx_se_list template;
+
+  template.car = car;
+  template.cdr = cdr;
+  {
+    struct rx_hash_item * it = rx_hash_store (memo, hash,
+					      (void *)&template,
+					      &se_list_hash_rules);
+    if (!it)
+      return 0;
+    if (it->data == (void *)&template)
+      {
+	struct rx_se_list * consed;
+	consed = (struct rx_se_list *) malloc (sizeof (*consed));
+	*consed = template;
+	it->data = (void *)consed;
+      }
+    return (struct rx_se_list *)it->data;
+  }
+}
+     
+
+#ifdef __STDC__
+static struct rx_se_list *
+hash_se_prog (struct rx * rx, struct rx_hash * memo, struct rx_se_list * prog)
+#else
+static struct rx_se_list *
+hash_se_prog (rx, memo, prog)
+     struct rx * rx;
+     struct rx_hash * memo;
+     struct rx_se_list * prog;
+#endif
+{
+  struct rx_se_list * answer = 0;
+  while (prog)
+    {
+      answer = hash_cons_se_prog (rx, memo, prog->car, answer);
+      if (!answer)
+	return 0;
+      prog = prog->cdr;
+    }
+  return answer;
+}
+
+#ifdef __STDC__
+static int 
+nfa_set_cmp (void * va, void * vb)
+#else
+static int 
+nfa_set_cmp (va, vb)
+     void * va;
+     void * vb;
+#endif
+{
+  struct rx_nfa_state_set * a = (struct rx_nfa_state_set *)va;
+  struct rx_nfa_state_set * b = (struct rx_nfa_state_set *)vb;
+
+  return ((va == vb)
+	  ? 0
+	  : (!va
+	     ? -1
+	     : (!vb
+		? 1
+		: (a->car->id < b->car->id
+		   ? 1
+		   : (a->car->id > b->car->id
+		      ? -1
+		      : nfa_set_cmp ((void *)a->cdr, (void *)b->cdr))))));
+}
+
+#ifdef __STDC__
+static int 
+nfa_set_equal (void * va, void * vb)
+#else
+static int 
+nfa_set_equal (va, vb)
+     void * va;
+     void * vb;
+#endif
+{
+  return !nfa_set_cmp (va, vb);
+}
+
+static struct rx_hash_rules nfa_set_hash_rules =
+{
+  nfa_set_equal,
+  compiler_hash_alloc,
+  compiler_free_hash,
+  compiler_hash_item_alloc,
+  compiler_free_hash_item
+};
+
+
+#ifdef __STDC__
+static struct rx_nfa_state_set * 
+nfa_set_cons (struct rx * rx,
+	      struct rx_hash * memo, struct rx_nfa_state * state,
+	      struct rx_nfa_state_set * set)
+#else
+static struct rx_nfa_state_set * 
+nfa_set_cons (rx, memo, state, set)
+     struct rx * rx;
+     struct rx_hash * memo;
+     struct rx_nfa_state * state;
+     struct rx_nfa_state_set * set;
+#endif
+{
+  struct rx_nfa_state_set template;
+  struct rx_hash_item * node;
+  template.car = state;
+  template.cdr = set;
+  node = rx_hash_store (memo,
+			(((long)state) >> 8) ^ (long)set,
+			&template, &nfa_set_hash_rules);
+  if (!node)
+    return 0;
+  if (node->data == &template)
+    {
+      struct rx_nfa_state_set * l;
+      l = (struct rx_nfa_state_set *) malloc (sizeof (*l));
+      node->data = (void *) l;
+      if (!l)
+	return 0;
+      *l = template;
+    }
+  return (struct rx_nfa_state_set *)node->data;
+}
+
+
+#ifdef __STDC__
+static struct rx_nfa_state_set * 
+nfa_set_enjoin (struct rx * rx,
+		struct rx_hash * memo, struct rx_nfa_state * state,
+		struct rx_nfa_state_set * set)
+#else
+static struct rx_nfa_state_set * 
+nfa_set_enjoin (rx, memo, state, set)
+     struct rx * rx;
+     struct rx_hash * memo;
+     struct rx_nfa_state * state;
+     struct rx_nfa_state_set * set;
+#endif
+{
+  if (!set || state->id < set->car->id)
+    return nfa_set_cons (rx, memo, state, set);
+  if (state->id == set->car->id)
+    return set;
+  else
+    {
+      struct rx_nfa_state_set * newcdr
+	= nfa_set_enjoin (rx, memo, state, set->cdr);
+      if (newcdr != set->cdr)
+	set = nfa_set_cons (rx, memo, set->car, newcdr);
+      return set;
+    }
+}
+
+
+
+
+/* This page: computing epsilon closures.  The closures aren't total.
+ * Each node's closures are partitioned according to the side effects entailed
+ * along the epsilon edges.  Return true on success.
+ */ 
+
+struct eclose_frame
+{
+  struct rx_se_list *prog_backwards;
+};
+
+
+#ifdef __STDC__
+static int 
+eclose_node (struct rx *rx, struct rx_nfa_state *outnode,
+	     struct rx_nfa_state *node, struct eclose_frame *frame)
+#else
+static int 
+eclose_node (rx, outnode, node, frame)
+     struct rx *rx;
+     struct rx_nfa_state *outnode;
+     struct rx_nfa_state *node;
+     struct eclose_frame *frame;
+#endif
+{
+  struct rx_nfa_edge *e = node->edges;
+
+  /* For each node, we follow all epsilon paths to build the closure.
+   * The closure omits nodes that have only epsilon edges.
+   * The closure is split into partial closures -- all the states in
+   * a partial closure are reached by crossing the same list of
+   * of side effects (though not necessarily the same path).
+   */
+  if (node->mark)
+    return 1;
+  node->mark = 1;
+
+  if (node->id >= 0 || node->is_final)
+    {
+      struct rx_possible_future **ec;
+      struct rx_se_list * prog_in_order
+	= ((struct rx_se_list *)hash_se_prog (rx,
+					      &rx->se_list_memo,
+					      frame->prog_backwards));
+      int cmp;
+
+      ec = &outnode->futures;
+
+      while (*ec)
+	{
+	  cmp = se_list_cmp ((void *)(*ec)->effects, (void *)prog_in_order);
+	  if (cmp <= 0)
+	    break;
+	  ec = &(*ec)->next;
+	}
+      if (!*ec || (cmp < 0))
+	{
+	  struct rx_possible_future * saved = *ec;
+	  *ec = rx_possible_future (rx, prog_in_order);
+	  (*ec)->next = saved;
+	  if (!*ec)
+	    return 0;
+	}
+      if (node->id >= 0)
+	{
+	  (*ec)->destset = nfa_set_enjoin (rx, &rx->set_list_memo,
+					   node, (*ec)->destset);
+	  if (!(*ec)->destset)
+	    return 0;
+	}
+    }
+
+  while (e)
+    {
+      switch (e->type)
+	{
+	case ne_epsilon:
+	  if (!eclose_node (rx, outnode, e->dest, frame))
+	    return 0;
+	  break;
+	case ne_side_effect:
+	  {
+	    frame->prog_backwards = side_effect_cons (rx, 
+						      e->params.side_effect,
+						      frame->prog_backwards);
+	    if (!frame->prog_backwards)
+	      return 0;
+	    if (!eclose_node (rx, outnode, e->dest, frame))
+	      return 0;
+	    {
+	      struct rx_se_list * dying = frame->prog_backwards;
+	      frame->prog_backwards = frame->prog_backwards->cdr;
+	      free ((char *)dying);
+	    }
+	    break;
+	  }
+	default:
+	  break;
+	}
+      e = e->next;
+    }
+  node->mark = 0;
+  return 1;
+}
+
+
+#ifdef __STDC__
+RX_DECL int 
+rx_eclose_nfa (struct rx *rx)
+#else
+RX_DECL int 
+rx_eclose_nfa (rx)
+     struct rx *rx;
+#endif
+{
+  struct rx_nfa_state *n = rx->nfa_states;
+  struct eclose_frame frame;
+  static int rx_id = 0;
+  
+  frame.prog_backwards = 0;
+  rx->rx_id = rx_id++;
+  bzero (&rx->se_list_memo, sizeof (rx->se_list_memo));
+  bzero (&rx->set_list_memo, sizeof (rx->set_list_memo));
+  while (n)
+    {
+      n->futures = 0;
+      if (n->eclosure_needed && !eclose_node (rx, n, n, &frame))
+	return 0;
+      /* clear_marks (rx); */
+      n = n->next;
+    }
+  return 1;
+}
+
+
+/* This deletes epsilon edges from an NFA.  After running eclose_node,
+ * we have no more need for these edges.  They are removed to simplify
+ * further operations on the NFA.
+ */
+
+#ifdef __STDC__
+RX_DECL void 
+rx_delete_epsilon_transitions (struct rx *rx)
+#else
+RX_DECL void 
+rx_delete_epsilon_transitions (rx)
+     struct rx *rx;
+#endif
+{
+  struct rx_nfa_state *n = rx->nfa_states;
+  struct rx_nfa_edge **e;
+
+  while (n)
+    {
+      e = &n->edges;
+      while (*e)
+	{
+	  struct rx_nfa_edge *t;
+	  switch ((*e)->type)
+	    {
+	    case ne_epsilon:
+	    case ne_side_effect:
+	      t = *e;
+	      *e = t->next;
+	      rx_free_nfa_edge (t);
+	      break;
+
+	    default:
+	      e = &(*e)->next;
+	      break;
+	    }
+	}
+      n = n->next;
+    }
+}
+
+
+
+/* This page: storing the nfa in a contiguous region of memory for
+ * subsequent conversion to a super-nfa.
+ */
+
+/* This is for qsort on an array of nfa_states. The order
+ * is based on state ids and goes 
+ *		[0...MAX][MIN..-1] where (MAX>=0) and (MIN<0)
+ * This way, positive ids double as array indices.
+ */
+
+#ifdef __STDC__
+static int 
+nfacmp (void * va, void * vb)
+#else
+static int 
+nfacmp (va, vb)
+     void * va;
+     void * vb;
+#endif
+{
+  struct rx_nfa_state **a = (struct rx_nfa_state **)va;
+  struct rx_nfa_state **b = (struct rx_nfa_state **)vb;
+  return (*a == *b		/* &&&& 3.18 */
+	  ? 0
+	  : (((*a)->id < 0) == ((*b)->id < 0)
+	     ? (((*a)->id  < (*b)->id) ? -1 : 1)
+	     : (((*a)->id < 0)
+		? 1 : -1)));
+}
+
+#ifdef __STDC__
+static int 
+count_hash_nodes (struct rx_hash * st)
+#else
+static int 
+count_hash_nodes (st)
+     struct rx_hash * st;
+#endif
+{
+  int x;
+  int count = 0;
+  for (x = 0; x < 13; ++x)
+    count += ((st->children[x])
+	      ? count_hash_nodes (st->children[x])
+	      : st->bucket_size[x]);
+  
+  return count;
+}
+
+
+#ifdef __STDC__
+static void 
+se_memo_freer (struct rx_hash_item * node)
+#else
+static void 
+se_memo_freer (node)
+     struct rx_hash_item * node;
+#endif
+{
+  free ((char *)node->data);
+}
+
+
+#ifdef __STDC__
+static void 
+nfa_set_freer (struct rx_hash_item * node)
+#else
+static void 
+nfa_set_freer (node)
+     struct rx_hash_item * node;
+#endif
+{
+  free ((char *)node->data);
+}
+
+
+/* This copies an entire NFA into a single malloced block of memory.
+ * Mostly this is for compatability with regex.c, though it is convenient
+ * to have the nfa nodes in an array.
+ */
+
+#ifdef __STDC__
+RX_DECL int 
+rx_compactify_nfa (struct rx *rx,
+		   void **mem, unsigned long *size)
+#else
+RX_DECL int 
+rx_compactify_nfa (rx, mem, size)
+     struct rx *rx;
+     void **mem;
+     unsigned long *size;
+#endif
+{
+  int total_nodec;
+  struct rx_nfa_state *n;
+  int edgec = 0;
+  int eclosec = 0;
+  int se_list_consc = count_hash_nodes (&rx->se_list_memo);
+  int nfa_setc = count_hash_nodes (&rx->set_list_memo);
+  unsigned long total_size;
+
+  /* This takes place in two stages.   First, the total size of the
+   * nfa is computed, then structures are copied.  
+   */   
+  n = rx->nfa_states;
+  total_nodec = 0;
+  while (n)
+    {
+      struct rx_nfa_edge *e = n->edges;
+      struct rx_possible_future *ec = n->futures;
+      ++total_nodec;
+      while (e)
+	{
+	  ++edgec;
+	  e = e->next;
+	}
+      while (ec)
+	{
+	  ++eclosec;
+	  ec = ec->next;
+	}
+      n = n->next;
+    }
+
+  total_size = (total_nodec * sizeof (struct rx_nfa_state)
+		+ edgec * rx_sizeof_bitset (rx->local_cset_size)
+		+ edgec * sizeof (struct rx_nfa_edge)
+		+ nfa_setc * sizeof (struct rx_nfa_state_set)
+		+ eclosec * sizeof (struct rx_possible_future)
+		+ se_list_consc * sizeof (struct rx_se_list)
+		+ rx->reserved);
+
+  if (total_size > *size)
+    {
+      *mem = remalloc (*mem, total_size);
+      if (*mem)
+	*size = total_size;
+      else
+	return 0;
+    }
+  /* Now we've allocated the memory; this copies the NFA. */
+  {
+    static struct rx_nfa_state **scratch = 0;
+    static int scratch_alloc = 0;
+    struct rx_nfa_state *state_base = (struct rx_nfa_state *) * mem;
+    struct rx_nfa_state *new_state = state_base;
+    struct rx_nfa_edge *new_edge =
+      (struct rx_nfa_edge *)
+	((char *) state_base + total_nodec * sizeof (struct rx_nfa_state));
+    struct rx_se_list * new_se_list =
+      (struct rx_se_list *)
+	((char *)new_edge + edgec * sizeof (struct rx_nfa_edge));
+    struct rx_possible_future *new_close =
+      ((struct rx_possible_future *)
+       ((char *) new_se_list
+	+ se_list_consc * sizeof (struct rx_se_list)));
+    struct rx_nfa_state_set * new_nfa_set =
+      ((struct rx_nfa_state_set *)
+       ((char *)new_close + eclosec * sizeof (struct rx_possible_future)));
+    char *new_bitset =
+      ((char *) new_nfa_set + nfa_setc * sizeof (struct rx_nfa_state_set));
+    int x;
+    struct rx_nfa_state *n;
+
+    if (scratch_alloc < total_nodec)
+      {
+	scratch = ((struct rx_nfa_state **)
+		   remalloc (scratch, total_nodec * sizeof (*scratch)));
+	if (scratch)
+	  scratch_alloc = total_nodec;
+	else
+	  {
+	    scratch_alloc = 0;
+	    return 0;
+	  }
+      }
+
+    for (x = 0, n = rx->nfa_states; n; n = n->next)
+      scratch[x++] = n;
+
+    qsort (scratch, total_nodec,
+	   sizeof (struct rx_nfa_state *), (int (*)())nfacmp);
+
+    for (x = 0; x < total_nodec; ++x)
+      {
+	struct rx_possible_future *eclose = scratch[x]->futures;
+	struct rx_nfa_edge *edge = scratch[x]->edges;
+	struct rx_nfa_state *cn = new_state++;
+	cn->futures = 0;
+	cn->edges = 0;
+	cn->next = (x == total_nodec - 1) ? 0 : (cn + 1);
+	cn->id = scratch[x]->id;
+	cn->is_final = scratch[x]->is_final;
+	cn->is_start = scratch[x]->is_start;
+	cn->mark = 0;
+	while (edge)
+	  {
+	    int indx = (edge->dest->id < 0
+			 ? (total_nodec + edge->dest->id)
+			 : edge->dest->id);
+	    struct rx_nfa_edge *e = new_edge++;
+	    rx_Bitset cset = (rx_Bitset) new_bitset;
+	    new_bitset += rx_sizeof_bitset (rx->local_cset_size);
+	    rx_bitset_null (rx->local_cset_size, cset);
+	    rx_bitset_union (rx->local_cset_size, cset, edge->params.cset);
+	    e->next = cn->edges;
+	    cn->edges = e;
+	    e->type = edge->type;
+	    e->dest = state_base + indx;
+	    e->params.cset = cset;
+	    edge = edge->next;
+	  }
+	while (eclose)
+	  {
+	    struct rx_possible_future *ec = new_close++;
+	    struct rx_hash_item * sp;
+	    struct rx_se_list ** sepos;
+	    struct rx_se_list * sesrc;
+	    struct rx_nfa_state_set * destlst;
+	    struct rx_nfa_state_set ** destpos;
+	    ec->next = cn->futures;
+	    cn->futures = ec;
+	    for (sepos = &ec->effects, sesrc = eclose->effects;
+		 sesrc;
+		 sesrc = sesrc->cdr, sepos = &(*sepos)->cdr)
+	      {
+		sp = rx_hash_find (&rx->se_list_memo,
+				   (long)sesrc->car ^ (long)sesrc->cdr,
+				   sesrc, &se_list_hash_rules);
+		if (sp->binding)
+		  {
+		    sesrc = (struct rx_se_list *)sp->binding;
+		    break;
+		  }
+		*new_se_list = *sesrc;
+		sp->binding = (void *)new_se_list;
+		*sepos = new_se_list;
+		++new_se_list;
+	      }
+	    *sepos = sesrc;
+	    for (destpos = &ec->destset, destlst = eclose->destset;
+		 destlst;
+		 destpos = &(*destpos)->cdr, destlst = destlst->cdr)
+	      {
+		sp = rx_hash_find (&rx->set_list_memo,
+				   ((((long)destlst->car) >> 8)
+				    ^ (long)destlst->cdr),
+				   destlst, &nfa_set_hash_rules);
+		if (sp->binding)
+		  {
+		    destlst = (struct rx_nfa_state_set *)sp->binding;
+		    break;
+		  }
+		*new_nfa_set = *destlst;
+		new_nfa_set->car = state_base + destlst->car->id;
+		sp->binding = (void *)new_nfa_set;
+		*destpos = new_nfa_set;
+		++new_nfa_set;
+	      }
+	    *destpos = destlst;
+	    eclose = eclose->next;
+	  }
+      }
+  }
+  rx_free_hash_table (&rx->se_list_memo, se_memo_freer, &se_list_hash_rules);
+  bzero (&rx->se_list_memo, sizeof (rx->se_list_memo));
+  rx_free_hash_table (&rx->set_list_memo, nfa_set_freer, &nfa_set_hash_rules);
+  bzero (&rx->set_list_memo, sizeof (rx->set_list_memo));
+
+  rx_free_nfa (rx);
+  rx->nfa_states = (struct rx_nfa_state *)*mem;
+  return 1;
+}
+
+
+
+/* The functions in the next several pages define the lazy-NFA-conversion used
+ * by matchers.  The input to this construction is an NFA such as 
+ * is built by compactify_nfa (rx.c).  The output is the superNFA.
+ */
+
+/* Match engines can use arbitrary values for opcodes.  So, the parse tree 
+ * is built using instructions names (enum rx_opcode), but the superstate
+ * nfa is populated with mystery opcodes (void *).
+ *
+ * For convenience, here is an id table.  The opcodes are == to their inxs
+ *
+ * The lables in re_search_2 would make good values for instructions.
+ */
+
+void * rx_id_instruction_table[rx_num_instructions] =
+{
+  (void *) rx_backtrack_point,
+  (void *) rx_do_side_effects,
+  (void *) rx_cache_miss,
+  (void *) rx_next_char,
+  (void *) rx_backtrack,
+  (void *) rx_error_inx
+};
+
+
+
+
+/* Memory mgt. for superstate graphs. */
+
+#ifdef __STDC__
+static char *
+rx_cache_malloc (struct rx_cache * cache, int bytes)
+#else
+static char *
+rx_cache_malloc (cache, bytes)
+     struct rx_cache * cache;
+     int bytes;
+#endif
+{
+  while (cache->bytes_left < bytes)
+    {
+      if (cache->memory_pos)
+	cache->memory_pos = cache->memory_pos->next;
+      if (!cache->memory_pos)
+	{
+	  cache->morecore (cache);
+	  if (!cache->memory_pos)
+	    return 0;
+	}
+      cache->bytes_left = cache->memory_pos->bytes;
+      cache->memory_addr = ((char *)cache->memory_pos
+			    + sizeof (struct rx_blocklist));
+    }
+  cache->bytes_left -= bytes;
+  {
+    char * addr = cache->memory_addr;
+    cache->memory_addr += bytes;
+    return addr;
+  }
+}
+
+#ifdef __STDC__
+static void
+rx_cache_free (struct rx_cache * cache,
+	       struct rx_freelist ** freelist, char * mem)
+#else
+static void
+rx_cache_free (cache, freelist, mem)
+     struct rx_cache * cache;
+     struct rx_freelist ** freelist;
+     char * mem;
+#endif
+{
+  struct rx_freelist * it = (struct rx_freelist *)mem;
+  it->next = *freelist;
+  *freelist = it;
+}
+
+
+/* The partially instantiated superstate graph has a transition 
+ * table at every node.  There is one entry for every character.
+ * This fills in the transition for a set.
+ */
+#ifdef __STDC__
+static void 
+install_transition (struct rx_superstate *super,
+		    struct rx_inx *answer, rx_Bitset trcset) 
+#else
+static void 
+install_transition (super, answer, trcset)
+     struct rx_superstate *super;
+     struct rx_inx *answer;
+     rx_Bitset trcset;
+#endif
+{
+  struct rx_inx * transitions = super->transitions;
+  int chr;
+  for (chr = 0; chr < 256; )
+    if (!*trcset)
+      {
+	++trcset;
+	chr += 32;
+      }
+    else
+      {
+	RX_subset sub = *trcset;
+	RX_subset mask = 1;
+	int bound = chr + 32;
+	while (chr < bound)
+	  {
+	    if (sub & mask)
+	      transitions [chr] = *answer;
+	    ++chr;
+	    mask <<= 1;
+	  }
+	++trcset;
+      }
+}
+
+
+#ifdef __STDC__
+static int
+qlen (struct rx_superstate * q)
+#else
+static int
+qlen (q)
+     struct rx_superstate * q;
+#endif
+{
+  int count = 1;
+  struct rx_superstate * it;
+  if (!q)
+    return 0;
+  for (it = q->next_recyclable; it != q; it = it->next_recyclable)
+    ++count;
+  return count;
+}
+
+#ifdef __STDC__
+static void
+check_cache (struct rx_cache * cache)
+#else
+static void
+check_cache (cache)
+     struct rx_cache * cache;
+#endif
+{
+  struct rx_cache * you_fucked_up = 0;
+  int total = cache->superstates;
+  int semi = cache->semifree_superstates;
+  if (semi != qlen (cache->semifree_superstate))
+    check_cache (you_fucked_up);
+  if ((total - semi) != qlen (cache->lru_superstate))
+    check_cache (you_fucked_up);
+}
+
+/* When a superstate is old and neglected, it can enter a 
+ * semi-free state.  A semi-free state is slated to die.
+ * Incoming transitions to a semi-free state are re-written
+ * to cause an (interpreted) fault when they are taken.
+ * The fault handler revives the semi-free state, patches
+ * incoming transitions back to normal, and continues.
+ *
+ * The idea is basicly to free in two stages, aborting 
+ * between the two if the state turns out to be useful again.
+ * When a free is aborted, the rescued superstate is placed
+ * in the most-favored slot to maximize the time until it
+ * is next semi-freed.
+ */
+
+#ifdef __STDC__
+static void
+semifree_superstate (struct rx_cache * cache)
+#else
+static void
+semifree_superstate (cache)
+     struct rx_cache * cache;
+#endif
+{
+  int disqualified = cache->semifree_superstates;
+  if (disqualified == cache->superstates)
+    return;
+  while (cache->lru_superstate->locks)
+    {
+      cache->lru_superstate = cache->lru_superstate->next_recyclable;
+      ++disqualified;
+      if (disqualified == cache->superstates)
+	return;
+    }
+  {
+    struct rx_superstate * it = cache->lru_superstate;
+    it->next_recyclable->prev_recyclable = it->prev_recyclable;
+    it->prev_recyclable->next_recyclable = it->next_recyclable;
+    cache->lru_superstate = (it == it->next_recyclable
+			     ? 0
+			     : it->next_recyclable);
+    if (!cache->semifree_superstate)
+      {
+	cache->semifree_superstate = it;
+	it->next_recyclable = it;
+	it->prev_recyclable = it;
+      }
+    else
+      {
+	it->prev_recyclable = cache->semifree_superstate->prev_recyclable;
+	it->next_recyclable = cache->semifree_superstate;
+	it->prev_recyclable->next_recyclable = it;
+	it->next_recyclable->prev_recyclable = it;
+      }
+    {
+      struct rx_distinct_future *df;
+      it->is_semifree = 1;
+      ++cache->semifree_superstates;
+      df = it->transition_refs;
+      if (df)
+	{
+	  df->prev_same_dest->next_same_dest = 0;
+	  for (df = it->transition_refs; df; df = df->next_same_dest)
+	    {
+	      df->future_frame.inx = cache->instruction_table[rx_cache_miss];
+	      df->future_frame.data = 0;
+	      df->future_frame.data_2 = (void *) df;
+	      /* If there are any NEXT-CHAR instruction frames that
+	       * refer to this state, we convert them to CACHE-MISS frames.
+	       */
+	      if (!df->effects
+		  && (df->edge->options->next_same_super_edge[0]
+		      == df->edge->options))
+		install_transition (df->present, &df->future_frame,
+				    df->edge->cset);
+	    }
+	  df = it->transition_refs;
+	  df->prev_same_dest->next_same_dest = df;
+	}
+    }
+  }
+}
+
+
+#ifdef __STDC__
+static void 
+refresh_semifree_superstate (struct rx_cache * cache,
+			     struct rx_superstate * super)
+#else
+static void 
+refresh_semifree_superstate (cache, super)
+     struct rx_cache * cache;
+     struct rx_superstate * super;
+#endif
+{
+  struct rx_distinct_future *df;
+
+  if (super->transition_refs)
+    {
+      super->transition_refs->prev_same_dest->next_same_dest = 0; 
+      for (df = super->transition_refs; df; df = df->next_same_dest)
+	{
+	  df->future_frame.inx = cache->instruction_table[rx_next_char];
+	  df->future_frame.data = (void *) super->transitions;
+	  /* CACHE-MISS instruction frames that refer to this state,
+	   * must be converted to NEXT-CHAR frames.
+	   */
+	  if (!df->effects
+	      && (df->edge->options->next_same_super_edge[0]
+		  == df->edge->options))
+	    install_transition (df->present, &df->future_frame,
+				df->edge->cset);
+	}
+      super->transition_refs->prev_same_dest->next_same_dest
+	= super->transition_refs;
+    }
+  if (cache->semifree_superstate == super)
+    cache->semifree_superstate = (super->prev_recyclable == super
+				  ? 0
+				  : super->prev_recyclable);
+  super->next_recyclable->prev_recyclable = super->prev_recyclable;
+  super->prev_recyclable->next_recyclable = super->next_recyclable;
+
+  if (!cache->lru_superstate)
+    (cache->lru_superstate
+     = super->next_recyclable
+     = super->prev_recyclable
+     = super);
+  else
+    {
+      super->next_recyclable = cache->lru_superstate;
+      super->prev_recyclable = cache->lru_superstate->prev_recyclable;
+      super->next_recyclable->prev_recyclable = super;
+      super->prev_recyclable->next_recyclable = super;
+    }
+  super->is_semifree = 0;
+  --cache->semifree_superstates;
+}
+
+#ifdef __STDC__
+static void
+rx_refresh_this_superstate (struct rx_cache * cache, struct rx_superstate * superstate)
+#else
+static void
+rx_refresh_this_superstate (cache, superstate)
+     struct rx_cache * cache;
+     struct rx_superstate * superstate;
+#endif
+{
+  if (superstate->is_semifree)
+    refresh_semifree_superstate (cache, superstate);
+  else if (cache->lru_superstate == superstate)
+    cache->lru_superstate = superstate->next_recyclable;
+  else if (superstate != cache->lru_superstate->prev_recyclable)
+    {
+      superstate->next_recyclable->prev_recyclable
+	= superstate->prev_recyclable;
+      superstate->prev_recyclable->next_recyclable
+	= superstate->next_recyclable;
+      superstate->next_recyclable = cache->lru_superstate;
+      superstate->prev_recyclable = cache->lru_superstate->prev_recyclable;
+      superstate->next_recyclable->prev_recyclable = superstate;
+      superstate->prev_recyclable->next_recyclable = superstate;
+    }
+}
+
+#ifdef __STDC__
+static void 
+release_superset_low (struct rx_cache * cache,
+		     struct rx_superset *set)
+#else
+static void 
+release_superset_low (cache, set)
+     struct rx_cache * cache;
+     struct rx_superset *set;
+#endif
+{
+  if (!--set->refs)
+    {
+      if (set->cdr)
+	release_superset_low (cache, set->cdr);
+
+      set->starts_for = 0;
+
+      rx_hash_free
+	(rx_hash_find
+	 (&cache->superset_table,
+	  (unsigned long)set->car ^ set->id ^ (unsigned long)set->cdr,
+	  (void *)set,
+	  &cache->superset_hash_rules),
+	 &cache->superset_hash_rules);
+      rx_cache_free (cache, &cache->free_supersets, (char *)set);
+    }
+}
+
+#ifdef __STDC__
+RX_DECL void 
+rx_release_superset (struct rx *rx,
+		     struct rx_superset *set)
+#else
+RX_DECL void 
+rx_release_superset (rx, set)
+     struct rx *rx;
+     struct rx_superset *set;
+#endif
+{
+  release_superset_low (rx->cache, set);
+}
+
+/* This tries to add a new superstate to the superstate freelist.
+ * It might, as a result, free some edge pieces or hash tables.
+ * If nothing can be freed because too many locks are being held, fail.
+ */
+
+#ifdef __STDC__
+static int
+rx_really_free_superstate (struct rx_cache * cache)
+#else
+static int
+rx_really_free_superstate (cache)
+     struct rx_cache * cache;
+#endif
+{
+  int locked_superstates = 0;
+  struct rx_superstate * it;
+
+  if (!cache->superstates)
+    return 0;
+
+  {
+    /* This is a total guess.  The idea is that we should expect as
+     * many misses as we've recently experienced.  I.e., cache->misses
+     * should be the same as cache->semifree_superstates.
+     */
+    while ((cache->hits + cache->misses) > cache->superstates_allowed)
+      {
+	cache->hits >>= 1;
+	cache->misses >>= 1;
+      }
+    if (  ((cache->hits + cache->misses) * cache->semifree_superstates)
+	< (cache->superstates		 * cache->misses))
+      {
+	semifree_superstate (cache);
+	semifree_superstate (cache);
+      }
+  }
+
+  while (cache->semifree_superstate && cache->semifree_superstate->locks)
+    {
+      refresh_semifree_superstate (cache, cache->semifree_superstate);
+      ++locked_superstates;
+      if (locked_superstates == cache->superstates)
+	return 0;
+    }
+
+  if (cache->semifree_superstate)
+    {
+      it = cache->semifree_superstate;
+      it->next_recyclable->prev_recyclable = it->prev_recyclable;
+      it->prev_recyclable->next_recyclable = it->next_recyclable;
+      cache->semifree_superstate = ((it == it->next_recyclable)
+				    ? 0
+				    : it->next_recyclable);
+      --cache->semifree_superstates;
+    }
+  else
+    {
+      while (cache->lru_superstate->locks)
+	{
+	  cache->lru_superstate = cache->lru_superstate->next_recyclable;
+	  ++locked_superstates;
+	  if (locked_superstates == cache->superstates)
+	    return 0;
+	}
+      it = cache->lru_superstate;
+      it->next_recyclable->prev_recyclable = it->prev_recyclable;
+      it->prev_recyclable->next_recyclable = it->next_recyclable;
+      cache->lru_superstate = ((it == it->next_recyclable)
+				    ? 0
+				    : it->next_recyclable);
+    }
+
+  if (it->transition_refs)
+    {
+      struct rx_distinct_future *df;
+      for (df = it->transition_refs,
+	   df->prev_same_dest->next_same_dest = 0;
+	   df;
+	   df = df->next_same_dest)
+	{
+	  df->future_frame.inx = cache->instruction_table[rx_cache_miss];
+	  df->future_frame.data = 0;
+	  df->future_frame.data_2 = (void *) df;
+	  df->future = 0;
+	}
+      it->transition_refs->prev_same_dest->next_same_dest =
+	it->transition_refs;
+    }
+  {
+    struct rx_super_edge *tc = it->edges;
+    while (tc)
+      {
+	struct rx_distinct_future * df;
+	struct rx_super_edge *tct = tc->next;
+	df = tc->options;
+	df->next_same_super_edge[1]->next_same_super_edge[0] = 0;
+	while (df)
+	  {
+	    struct rx_distinct_future *dft = df;
+	    df = df->next_same_super_edge[0];
+	    
+	    
+	    if (dft->future && dft->future->transition_refs == dft)
+	      {
+		dft->future->transition_refs = dft->next_same_dest;
+		if (dft->future->transition_refs == dft)
+		  dft->future->transition_refs = 0;
+	      }
+	    dft->next_same_dest->prev_same_dest = dft->prev_same_dest;
+	    dft->prev_same_dest->next_same_dest = dft->next_same_dest;
+	    rx_cache_free (cache, &cache->free_discernable_futures,
+			   (char *)dft);
+	  }
+	rx_cache_free (cache, &cache->free_transition_classes, (char *)tc);
+	tc = tct;
+      }
+  }
+  
+  if (it->contents->superstate == it)
+    it->contents->superstate = 0;
+  release_superset_low (cache, it->contents);
+  rx_cache_free (cache, &cache->free_superstates, (char *)it);
+  --cache->superstates;
+  return 1;
+}
+
+#ifdef __STDC__
+static char *
+rx_cache_get (struct rx_cache * cache,
+	      struct rx_freelist ** freelist)
+#else
+static char *
+rx_cache_get (cache, freelist)
+     struct rx_cache * cache;
+     struct rx_freelist ** freelist;
+#endif
+{
+  while (!*freelist && rx_really_free_superstate (cache))
+    ;
+  if (!*freelist)
+    return 0;
+  {
+    struct rx_freelist * it = *freelist;
+    *freelist = it->next;
+    return (char *)it;
+  }
+}
+
+#ifdef __STDC__
+static char *
+rx_cache_malloc_or_get (struct rx_cache * cache,
+			struct rx_freelist ** freelist, int bytes)
+#else
+static char *
+rx_cache_malloc_or_get (cache, freelist, bytes)
+     struct rx_cache * cache;
+     struct rx_freelist ** freelist;
+     int bytes;
+#endif
+{
+  if (!*freelist)
+    {
+      char * answer = rx_cache_malloc (cache, bytes);
+      if (answer)
+	return answer;
+    }
+
+  return rx_cache_get (cache, freelist);
+}
+
+#ifdef __STDC__
+static char *
+rx_cache_get_superstate (struct rx_cache * cache)
+#else
+static char *
+rx_cache_get_superstate (cache)
+	  struct rx_cache * cache;
+#endif
+{
+  char * answer;
+  int bytes = (   sizeof (struct rx_superstate)
+	       +  cache->local_cset_size * sizeof (struct rx_inx));
+  if (!cache->free_superstates
+      && (cache->superstates < cache->superstates_allowed))
+    {
+      answer = rx_cache_malloc (cache, bytes);
+      if (answer)
+	{
+	  ++cache->superstates;
+	  return answer;
+	}
+    }
+  answer = rx_cache_get (cache, &cache->free_superstates);
+  if (!answer)
+    {
+      answer = rx_cache_malloc (cache, bytes);
+      if (answer)
+	++cache->superstates_allowed;
+    }
+  ++cache->superstates;
+  return answer;
+}
+
+
+
+
+#ifdef __STDC__
+static int
+supersetcmp (void * va, void * vb)
+#else
+static int
+supersetcmp (va, vb)
+     void * va;
+     void * vb;
+#endif
+{
+  struct rx_superset * a = (struct rx_superset *)va;
+  struct rx_superset * b = (struct rx_superset *)vb;
+  return (   (a == b)
+	  || (a && b && (a->car == b->car) && (a->cdr == b->cdr)));
+}
+
+#ifdef __STDC__
+static struct rx_hash_item *
+superset_allocator (struct rx_hash_rules * rules, void * val)
+#else
+static struct rx_hash_item *
+superset_allocator (rules, val)
+     struct rx_hash_rules * rules;
+     void * val;
+#endif
+{
+  struct rx_cache * cache
+    = ((struct rx_cache *)
+       ((char *)rules
+	- (unsigned long)(&((struct rx_cache *)0)->superset_hash_rules)));
+  struct rx_superset * template = (struct rx_superset *)val;
+  struct rx_superset * newset
+    = ((struct rx_superset *)
+       rx_cache_malloc_or_get (cache,
+			       &cache->free_supersets,
+			       sizeof (*template)));
+  if (!newset)
+    return 0;
+  newset->refs = 0;
+  newset->car = template->car;
+  newset->id = template->car->id;
+  newset->cdr = template->cdr;
+  newset->superstate = 0;
+  rx_protect_superset (rx, template->cdr);
+  newset->hash_item.data = (void *)newset;
+  newset->hash_item.binding = 0;
+  return &newset->hash_item;
+}
+
+#ifdef __STDC__
+static struct rx_hash * 
+super_hash_allocator (struct rx_hash_rules * rules)
+#else
+static struct rx_hash * 
+super_hash_allocator (rules)
+     struct rx_hash_rules * rules;
+#endif
+{
+  struct rx_cache * cache
+    = ((struct rx_cache *)
+       ((char *)rules
+	- (unsigned long)(&((struct rx_cache *)0)->superset_hash_rules)));
+  return ((struct rx_hash *)
+	  rx_cache_malloc_or_get (cache,
+				  &cache->free_hash, sizeof (struct rx_hash)));
+}
+
+
+#ifdef __STDC__
+static void
+super_hash_liberator (struct rx_hash * hash, struct rx_hash_rules * rules)
+#else
+static void
+super_hash_liberator (hash, rules)
+     struct rx_hash * hash;
+     struct rx_hash_rules * rules;
+#endif
+{
+  struct rx_cache * cache
+    = ((struct rx_cache *)
+       (char *)rules - (long)(&((struct rx_cache *)0)->superset_hash_rules));
+  rx_cache_free (cache, &cache->free_hash, (char *)hash);
+}
+
+#ifdef __STDC__
+static void
+superset_hash_item_liberator (struct rx_hash_item * it,
+			      struct rx_hash_rules * rules)
+#else
+static void
+superset_hash_item_liberator (it, rules) /* Well, it does ya know. */
+     struct rx_hash_item * it;
+     struct rx_hash_rules * rules;
+#endif
+{
+}
+
+int rx_cache_bound = 128;
+static int rx_default_cache_got = 0;
+
+#ifdef __STDC__
+static int
+bytes_for_cache_size (int supers, int cset_size)
+#else
+static int
+bytes_for_cache_size (supers, cset_size)
+     int supers;
+     int cset_size;
+#endif
+{
+  /* What the hell is this? !!!*/
+  return (int)
+    ((float)supers *
+     (  (1.03 * (float) (  rx_sizeof_bitset (cset_size)
+			 + sizeof (struct rx_super_edge)))
+      + (1.80 * (float) sizeof (struct rx_possible_future))
+      + (float) (  sizeof (struct rx_superstate)
+		 + cset_size * sizeof (struct rx_inx))));
+}
+
+#ifdef __STDC__
+static void
+rx_morecore (struct rx_cache * cache)
+#else
+static void
+rx_morecore (cache)
+     struct rx_cache * cache;
+#endif
+{
+  if (rx_default_cache_got >= rx_cache_bound)
+    return;
+
+  rx_default_cache_got += 16;
+  cache->superstates_allowed = rx_cache_bound;
+  {
+    struct rx_blocklist ** pos = &cache->memory;
+    int size = bytes_for_cache_size (16, cache->local_cset_size);
+    while (*pos)
+      pos = &(*pos)->next;
+    *pos = ((struct rx_blocklist *)
+	    malloc (size + sizeof (struct rx_blocklist))); 
+    if (!*pos)
+      return;
+
+    (*pos)->next = 0;
+    (*pos)->bytes = size;
+    cache->memory_pos = *pos;
+    cache->memory_addr = (char *)*pos + sizeof (**pos);
+    cache->bytes_left = size;
+  }
+}
+
+static struct rx_cache default_cache = 
+{
+  {
+    supersetcmp,
+    super_hash_allocator,
+    super_hash_liberator,
+    superset_allocator,
+    superset_hash_item_liberator,
+  },
+  0,
+  0,
+  0,
+  0,
+  rx_morecore,
+
+  0,
+  0,
+  0,
+  0,
+  0,
+
+  0,
+  0,
+
+  0,
+
+  0,
+  0,
+  0,
+  0,
+  128,
+
+  256,
+  rx_id_instruction_table,
+
+  {
+    0,
+    0,
+    {0},
+    {0},
+    {0}
+  }
+};
+
+/* This adds an element to a superstate set.  These sets are lists, such
+ * that lists with == elements are ==.  The empty set is returned by
+ * superset_cons (rx, 0, 0) and is NOT equivelent to 
+ * (struct rx_superset)0.
+ */
+
+#ifdef __STDC__
+RX_DECL struct rx_superset *
+rx_superset_cons (struct rx * rx,
+		  struct rx_nfa_state *car, struct rx_superset *cdr)
+#else
+RX_DECL struct rx_superset *
+rx_superset_cons (rx, car, cdr)
+     struct rx * rx;
+     struct rx_nfa_state *car;
+     struct rx_superset *cdr;
+#endif
+{
+  struct rx_cache * cache = rx->cache;
+  if (!car && !cdr)
+    {
+      if (!cache->empty_superset)
+	{
+	  cache->empty_superset
+	    = ((struct rx_superset *)
+	       rx_cache_malloc_or_get (cache, &cache->free_supersets,
+				       sizeof (struct rx_superset)));
+	  if (!cache->empty_superset)
+	    return 0;
+	  bzero (cache->empty_superset, sizeof (struct rx_superset));
+	  cache->empty_superset->refs = 1000;
+	}
+      return cache->empty_superset;
+    }
+  {
+    struct rx_superset template;
+    struct rx_hash_item * hit;
+    template.car = car;
+    template.cdr = cdr;
+    template.id = car->id;
+    hit = rx_hash_store (&cache->superset_table,
+			 (unsigned long)car ^ car->id ^ (unsigned long)cdr,
+			 (void *)&template,
+			 &cache->superset_hash_rules);
+    return (hit
+	    ?  (struct rx_superset *)hit->data
+	    : 0);
+  }
+}
+
+/* This computes a union of two NFA state sets.  The sets do not have the
+ * same representation though.  One is a RX_SUPERSET structure (part
+ * of the superstate NFA) and the other is an NFA_STATE_SET (part of the NFA).
+ */
+
+#ifdef __STDC__
+RX_DECL struct rx_superset *
+rx_superstate_eclosure_union
+  (struct rx * rx, struct rx_superset *set, struct rx_nfa_state_set *ecl) 
+#else
+RX_DECL struct rx_superset *
+rx_superstate_eclosure_union (rx, set, ecl)
+     struct rx * rx;
+     struct rx_superset *set;
+     struct rx_nfa_state_set *ecl;
+#endif
+{
+  if (!ecl)
+    return set;
+
+  if (!set->car)
+    return rx_superset_cons (rx, ecl->car,
+			     rx_superstate_eclosure_union (rx, set, ecl->cdr));
+  if (set->car == ecl->car)
+    return rx_superstate_eclosure_union (rx, set, ecl->cdr);
+
+  {
+    struct rx_superset * tail;
+    struct rx_nfa_state * first;
+
+    if (set->car > ecl->car)
+      {
+	tail = rx_superstate_eclosure_union (rx, set->cdr, ecl);
+	first = set->car;
+      }
+    else
+      {
+	tail = rx_superstate_eclosure_union (rx, set, ecl->cdr);
+	first = ecl->car;
+      }
+    if (!tail)
+      return 0;
+    else
+      {
+	struct rx_superset * answer;
+	answer = rx_superset_cons (rx, first, tail);
+	if (!answer)
+	  {
+	    rx_protect_superset (rx, tail);
+	    rx_release_superset (rx, tail);
+	    return 0;
+	  }
+	else
+	  return answer;
+      }
+  }
+}
+
+
+
+
+
+/*
+ * This makes sure that a list of rx_distinct_futures contains
+ * a future for each possible set of side effects in the eclosure
+ * of a given state.  This is some of the work of filling in a
+ * superstate transition. 
+ */
+
+#ifdef __STDC__
+static struct rx_distinct_future *
+include_futures (struct rx *rx,
+		 struct rx_distinct_future *df, struct rx_nfa_state
+		 *state, struct rx_superstate *superstate) 
+#else
+static struct rx_distinct_future *
+include_futures (rx, df, state, superstate)
+     struct rx *rx;
+     struct rx_distinct_future *df;
+     struct rx_nfa_state *state;
+     struct rx_superstate *superstate;
+#endif
+{
+  struct rx_possible_future *future;
+  struct rx_cache * cache = rx->cache;
+  for (future = state->futures; future; future = future->next)
+    {
+      struct rx_distinct_future *dfp;
+      struct rx_distinct_future *insert_before = 0;
+      if (df)
+	df->next_same_super_edge[1]->next_same_super_edge[0] = 0;
+      for (dfp = df; dfp; dfp = dfp->next_same_super_edge[0])
+	if (dfp->effects == future->effects)
+	  break;
+	else
+	  {
+	    int order = rx->se_list_cmp (rx, dfp->effects, future->effects);
+	    if (order > 0)
+	      {
+		insert_before = dfp;
+		dfp = 0;
+		break;
+	      }
+	  }
+      if (df)
+	df->next_same_super_edge[1]->next_same_super_edge[0] = df;
+      if (!dfp)
+	{
+	  dfp
+	    = ((struct rx_distinct_future *)
+	       rx_cache_malloc_or_get (cache, &cache->free_discernable_futures,
+				       sizeof (struct rx_distinct_future)));
+	  if (!dfp)
+	    return 0;
+	  if (!df)
+	    {
+	      df = insert_before = dfp;
+	      df->next_same_super_edge[0] = df->next_same_super_edge[1] = df;
+	    }
+	  else if (!insert_before)
+	    insert_before = df;
+	  else if (insert_before == df)
+	    df = dfp;
+
+	  dfp->next_same_super_edge[0] = insert_before;
+	  dfp->next_same_super_edge[1]
+	    = insert_before->next_same_super_edge[1];
+	  dfp->next_same_super_edge[1]->next_same_super_edge[0] = dfp;
+	  dfp->next_same_super_edge[0]->next_same_super_edge[1] = dfp;
+	  dfp->next_same_dest = dfp->prev_same_dest = dfp;
+	  dfp->future = 0;
+	  dfp->present = superstate;
+	  dfp->future_frame.inx = rx->instruction_table[rx_cache_miss];
+	  dfp->future_frame.data = 0;
+	  dfp->future_frame.data_2 = (void *) dfp;
+	  dfp->side_effects_frame.inx
+	    = rx->instruction_table[rx_do_side_effects];
+	  dfp->side_effects_frame.data = 0;
+	  dfp->side_effects_frame.data_2 = (void *) dfp;
+	  dfp->effects = future->effects;
+	}
+    }
+  return df;
+}
+
+
+
+
+/* This constructs a new superstate from its state set.  The only 
+ * complexity here is memory management.
+ */
+#ifdef __STDC__
+RX_DECL struct rx_superstate *
+rx_superstate (struct rx *rx,
+	       struct rx_superset *set)
+#else
+RX_DECL struct rx_superstate *
+rx_superstate (rx, set)
+     struct rx *rx;
+     struct rx_superset *set;
+#endif
+{
+  struct rx_cache * cache = rx->cache;
+  struct rx_superstate * superstate = 0;
+
+  /* Does the superstate already exist in the cache? */
+  if (set->superstate)
+    {
+      if (set->superstate->rx_id != rx->rx_id)
+	{
+	  /* Aha.  It is in the cache, but belongs to a superstate
+	   * that refers to an NFA that no longer exists.
+	   * (We know it no longer exists because it was evidently
+	   *  stored in the same region of memory as the current nfa
+	   *  yet it has a different id.)
+	   */
+	  superstate = set->superstate;
+	  if (!superstate->is_semifree)
+	    {
+	      if (cache->lru_superstate == superstate)
+		{
+		  cache->lru_superstate = superstate->next_recyclable;
+		  if (cache->lru_superstate == superstate)
+		    cache->lru_superstate = 0;
+		}
+	      {
+		superstate->next_recyclable->prev_recyclable
+		  = superstate->prev_recyclable;
+		superstate->prev_recyclable->next_recyclable
+		  = superstate->next_recyclable;
+		if (!cache->semifree_superstate)
+		  {
+		    (cache->semifree_superstate
+		     = superstate->next_recyclable
+		     = superstate->prev_recyclable
+		     = superstate);
+		  }
+		else
+		  {
+		    superstate->next_recyclable = cache->semifree_superstate;
+		    superstate->prev_recyclable
+		      = cache->semifree_superstate->prev_recyclable;
+		    superstate->next_recyclable->prev_recyclable
+		      = superstate;
+		    superstate->prev_recyclable->next_recyclable
+		      = superstate;
+		    cache->semifree_superstate = superstate;
+		  }
+		++cache->semifree_superstates;
+	      }
+	    }
+	  set->superstate = 0;
+	  goto handle_cache_miss;
+	}
+      ++cache->hits;
+      superstate = set->superstate;
+
+      rx_refresh_this_superstate (cache, superstate);
+      return superstate;
+    }
+
+ handle_cache_miss:
+
+  /* This point reached only for cache misses. */
+  ++cache->misses;
+#if RX_DEBUG
+  if (rx_debug_trace > 1)
+    {
+      struct rx_superset * setp = set;
+      fprintf (stderr, "Building a superstet %d(%d): ", rx->rx_id, set);
+      while (setp)
+	{
+	  fprintf (stderr, "%d ", setp->id);
+	  setp = setp->cdr;
+	}
+      fprintf (stderr, "(%d)\n", set);
+    }
+#endif
+  superstate = (struct rx_superstate *)rx_cache_get_superstate (cache);
+  if (!superstate)
+    return 0;
+
+  if (!cache->lru_superstate)
+    (cache->lru_superstate
+     = superstate->next_recyclable
+     = superstate->prev_recyclable
+     = superstate);
+  else
+    {
+      superstate->next_recyclable = cache->lru_superstate;
+      superstate->prev_recyclable = cache->lru_superstate->prev_recyclable;
+      (  superstate->prev_recyclable->next_recyclable
+       = superstate->next_recyclable->prev_recyclable
+       = superstate);
+    }
+  superstate->rx_id = rx->rx_id;
+  superstate->transition_refs = 0;
+  superstate->locks = 0;
+  superstate->is_semifree = 0;
+  set->superstate = superstate;
+  superstate->contents = set;
+  rx_protect_superset (rx, set);
+  superstate->edges = 0;
+  {
+    int x;
+    /* None of the transitions from this superstate are known yet. */
+    for (x = 0; x < rx->local_cset_size; ++x) /* &&&&& 3.8 % */
+      {
+	struct rx_inx * ifr = &superstate->transitions[x];
+	ifr->inx = rx->instruction_table [rx_cache_miss];
+	ifr->data = ifr->data_2 = 0;
+      }
+  }
+  return superstate;
+}
+
+
+
+/* This computes the destination set of one edge of the superstate NFA.
+ * Note that a RX_DISTINCT_FUTURE is a superstate edge.
+ * Returns 0 on an allocation failure.
+ */
+
+#ifdef __STDC__
+static int 
+solve_destination (struct rx *rx, struct rx_distinct_future *df)
+#else
+static int 
+solve_destination (rx, df)
+     struct rx *rx;
+     struct rx_distinct_future *df;
+#endif
+{
+  struct rx_super_edge *tc = df->edge;
+  struct rx_superset *nfa_state;
+  struct rx_superset *nil_set = rx_superset_cons (rx, 0, 0);
+  struct rx_superset *solution = nil_set;
+  struct rx_superstate *dest;
+
+  rx_protect_superset (rx, solution);
+  /* Iterate over all NFA states in the state set of this superstate. */
+  for (nfa_state = df->present->contents;
+       nfa_state->car;
+       nfa_state = nfa_state->cdr)
+    {
+      struct rx_nfa_edge *e;
+      /* Iterate over all edges of each NFA state. */
+      for (e = nfa_state->car->edges; e; e = e->next)
+        /* If we find an edge that is labeled with 
+	 * the characters we are solving for.....
+	 */
+	if (rx_bitset_is_subset (rx->local_cset_size,
+				 tc->cset, e->params.cset))
+	  {
+	    struct rx_nfa_state *n = e->dest;
+	    struct rx_possible_future *pf;
+	    /* ....search the partial epsilon closures of the destination
+	     * of that edge for a path that involves the same set of
+	     * side effects we are solving for.
+	     * If we find such a RX_POSSIBLE_FUTURE, we add members to the
+	     * stateset we are computing.
+	     */
+	    for (pf = n->futures; pf; pf = pf->next)
+	      if (pf->effects == df->effects)
+		{
+		  struct rx_superset * old_sol;
+		  old_sol = solution;
+		  solution = rx_superstate_eclosure_union (rx, solution,
+							   pf->destset);
+		  if (!solution)
+		    return 0;
+		  rx_protect_superset (rx, solution);
+		  rx_release_superset (rx, old_sol);
+		}
+	  }
+    }
+  /* It is possible that the RX_DISTINCT_FUTURE we are working on has 
+   * the empty set of NFA states as its definition.  In that case, this
+   * is a failure point.
+   */
+  if (solution == nil_set)
+    {
+      df->future_frame.inx = (void *) rx_backtrack;
+      df->future_frame.data = 0;
+      df->future_frame.data_2 = 0;
+      return 1;
+    }
+  dest = rx_superstate (rx, solution);
+  rx_release_superset (rx, solution);
+  if (!dest)
+    return 0;
+
+  {
+    struct rx_distinct_future *dft;
+    dft = df;
+    df->prev_same_dest->next_same_dest = 0;
+    while (dft)
+      {
+	dft->future = dest;
+	dft->future_frame.inx = rx->instruction_table[rx_next_char];
+	dft->future_frame.data = (void *) dest->transitions;
+	dft = dft->next_same_dest;
+      }
+    df->prev_same_dest->next_same_dest = df;
+  }
+  if (!dest->transition_refs)
+    dest->transition_refs = df;
+  else
+    {
+      struct rx_distinct_future *dft = dest->transition_refs->next_same_dest;
+      dest->transition_refs->next_same_dest = df->next_same_dest;
+      df->next_same_dest->prev_same_dest = dest->transition_refs;
+      df->next_same_dest = dft;
+      dft->prev_same_dest = df;
+    }
+  return 1;
+}
+
+
+/* This takes a superstate and a character, and computes some edges
+ * from the superstate NFA.  In particular, this computes all edges
+ * that lead from SUPERSTATE given CHR.   This function also 
+ * computes the set of characters that share this edge set.
+ * This returns 0 on allocation error.
+ * The character set and list of edges are returned through 
+ * the paramters CSETOUT and DFOUT.
+} */
+
+#ifdef __STDC__
+static int 
+compute_super_edge (struct rx *rx, struct rx_distinct_future **dfout,
+			  rx_Bitset csetout, struct rx_superstate *superstate,
+			  unsigned char chr)  
+#else
+static int 
+compute_super_edge (rx, dfout, csetout, superstate, chr)
+     struct rx *rx;
+     struct rx_distinct_future **dfout;
+     rx_Bitset csetout;
+     struct rx_superstate *superstate;
+     unsigned char chr;
+#endif
+{
+  struct rx_superset *stateset = superstate->contents;
+
+  /* To compute the set of characters that share edges with CHR, 
+   * we start with the full character set, and subtract.
+   */
+  rx_bitset_universe (rx->local_cset_size, csetout);
+  *dfout = 0;
+
+  /* Iterate over the NFA states in the superstate state-set. */
+  while (stateset->car)
+    {
+      struct rx_nfa_edge *e;
+      for (e = stateset->car->edges; e; e = e->next)
+	if (RX_bitset_member (e->params.cset, chr))
+	  {
+	    /* If we find an NFA edge that applies, we make sure there
+	     * are corresponding edges in the superstate NFA.
+	     */
+	    {
+	      struct rx_distinct_future * saved;
+	      saved = *dfout;
+	      *dfout = include_futures (rx, *dfout, e->dest, superstate);
+	      if (!*dfout)
+		{
+		  struct rx_distinct_future * df;
+		  df = saved;
+		  df->next_same_super_edge[1]->next_same_super_edge[0] = 0;
+		  while (df)
+		    {
+		      struct rx_distinct_future *dft;
+		      dft = df;
+		      df = df->next_same_super_edge[0];
+
+		      if (dft->future && dft->future->transition_refs == dft)
+			{
+			  dft->future->transition_refs = dft->next_same_dest;
+			  if (dft->future->transition_refs == dft)
+			    dft->future->transition_refs = 0;
+			}
+		      dft->next_same_dest->prev_same_dest = dft->prev_same_dest;
+		      dft->prev_same_dest->next_same_dest = dft->next_same_dest;
+		      rx_cache_free (rx->cache,
+				     &rx->cache->free_discernable_futures,
+				     (char *)dft);
+		    }
+		  return 0;
+		}
+	    }
+	    /* We also trim the character set a bit. */
+	    rx_bitset_intersection (rx->local_cset_size,
+				    csetout, e->params.cset);
+	  }
+	else
+	  /* An edge that doesn't apply at least tells us some characters
+	   * that don't share the same edge set as CHR.
+	   */
+	  rx_bitset_difference (rx->local_cset_size, csetout, e->params.cset);
+      stateset = stateset->cdr;
+    }
+  return 1;
+}
+
+
+
+/* This is a constructor for RX_SUPER_EDGE structures.  These are
+ * wrappers for lists of superstate NFA edges that share character sets labels.
+ * If a transition class contains more than one rx_distinct_future (superstate
+ * edge), then it represents a non-determinism in the superstate NFA.
+ */
+
+#ifdef __STDC__
+static struct rx_super_edge *
+rx_super_edge (struct rx *rx,
+	       struct rx_superstate *super, rx_Bitset cset,
+	       struct rx_distinct_future *df) 
+#else
+static struct rx_super_edge *
+rx_super_edge (rx, super, cset, df)
+     struct rx *rx;
+     struct rx_superstate *super;
+     rx_Bitset cset;
+     struct rx_distinct_future *df;
+#endif
+{
+  struct rx_super_edge *tc =
+    (struct rx_super_edge *)rx_cache_malloc_or_get
+      (rx->cache, &rx->cache->free_transition_classes,
+       sizeof (struct rx_super_edge) + rx_sizeof_bitset (rx->local_cset_size));
+
+  if (!tc)
+    return 0;
+  tc->next = super->edges;
+  super->edges = tc;
+  tc->rx_backtrack_frame.inx = rx->instruction_table[rx_backtrack_point];
+  tc->rx_backtrack_frame.data = 0;
+  tc->rx_backtrack_frame.data_2 = (void *) tc;
+  tc->options = df;
+  tc->cset = (rx_Bitset) ((char *) tc + sizeof (*tc));
+  rx_bitset_assign (rx->local_cset_size, tc->cset, cset);
+  if (df)
+    {
+      struct rx_distinct_future * dfp = df;
+      df->next_same_super_edge[1]->next_same_super_edge[0] = 0;
+      while (dfp)
+	{
+	  dfp->edge = tc;
+	  dfp = dfp->next_same_super_edge[0];
+	}
+      df->next_same_super_edge[1]->next_same_super_edge[0] = df;
+    }
+  return tc;
+}
+
+
+/* There are three kinds of cache miss.  The first occurs when a
+ * transition is taken that has never been computed during the
+ * lifetime of the source superstate.  That cache miss is handled by
+ * calling COMPUTE_SUPER_EDGE.  The second kind of cache miss
+ * occurs when the destination superstate of a transition doesn't
+ * exist.  SOLVE_DESTINATION is used to construct the destination superstate.
+ * Finally, the third kind of cache miss occurs when the destination
+ * superstate of a transition is in a `semi-free state'.  That case is
+ * handled by UNFREE_SUPERSTATE.
+ *
+ * The function of HANDLE_CACHE_MISS is to figure out which of these
+ * cases applies.
+ */
+
+#ifdef __STDC__
+static void
+install_partial_transition  (struct rx_superstate *super,
+			     struct rx_inx *answer,
+			     RX_subset set, int offset)
+#else
+static void
+install_partial_transition  (super, answer, set, offset)
+     struct rx_superstate *super;
+     struct rx_inx *answer;
+     RX_subset set;
+     int offset;
+#endif
+{
+  int start = offset;
+  int end = start + 32;
+  RX_subset pos = 1;
+  struct rx_inx * transitions = super->transitions;
+  
+  while (start < end)
+    {
+      if (set & pos)
+	transitions[start] = *answer;
+      pos <<= 1;
+      ++start;
+    }
+}
+
+
+#ifdef __STDC__
+RX_DECL struct rx_inx *
+rx_handle_cache_miss
+  (struct rx *rx, struct rx_superstate *super, unsigned char chr, void *data) 
+#else
+RX_DECL struct rx_inx *
+rx_handle_cache_miss (rx, super, chr, data)
+     struct rx *rx;
+     struct rx_superstate *super;
+     unsigned char chr;
+     void *data;
+#endif
+{
+  int offset = chr / RX_subset_bits;
+  struct rx_distinct_future *df = data;
+
+  if (!df)			/* must be the shared_cache_miss_frame */
+    {
+      /* Perhaps this is just a transition waiting to be filled. */
+      struct rx_super_edge *tc;
+      RX_subset mask = rx_subset_singletons [chr % RX_subset_bits];
+
+      for (tc = super->edges; tc; tc = tc->next)
+	if (tc->cset[offset] & mask)
+	  {
+	    struct rx_inx * answer;
+	    df = tc->options;
+	    answer = ((tc->options->next_same_super_edge[0] != tc->options)
+		      ? &tc->rx_backtrack_frame
+		      : (df->effects
+			 ? &df->side_effects_frame
+			 : &df->future_frame));
+	    install_partial_transition (super, answer,
+					tc->cset [offset], offset * 32);
+	    return answer;
+	  }
+      /* Otherwise, it's a flushed or  newly encountered edge. */
+      {
+	char cset_space[1024];	/* this limit is far from unreasonable */
+	rx_Bitset trcset;
+	struct rx_inx *answer;
+
+	if (rx_sizeof_bitset (rx->local_cset_size) > sizeof (cset_space))
+	  return 0;		/* If the arbitrary limit is hit, always fail */
+				/* cleanly. */
+	trcset = (rx_Bitset)cset_space;
+	rx_lock_superstate (rx, super);
+	if (!compute_super_edge (rx, &df, trcset, super, chr))
+	  {
+	    rx_unlock_superstate (rx, super);
+	    return 0;
+	  }
+	if (!df)		/* We just computed the fail transition. */
+	  {
+	    static struct rx_inx
+	      shared_fail_frame = { 0, 0, (void *)rx_backtrack, 0 };
+	    answer = &shared_fail_frame;
+	  }
+	else
+	  {
+	    tc = rx_super_edge (rx, super, trcset, df);
+	    if (!tc)
+	      {
+		rx_unlock_superstate (rx, super);
+		return 0;
+	      }
+	    answer = ((tc->options->next_same_super_edge[0] != tc->options)
+		      ? &tc->rx_backtrack_frame
+		      : (df->effects
+			 ? &df->side_effects_frame
+			 : &df->future_frame));
+	  }
+	install_partial_transition (super, answer,
+				    trcset[offset], offset * 32);
+	rx_unlock_superstate (rx, super);
+	return answer;
+      }
+    }
+  else if (df->future) /* A cache miss on an edge with a future? Must be
+			* a semi-free destination. */
+    {				
+      if (df->future->is_semifree)
+	refresh_semifree_superstate (rx->cache, df->future);
+      return &df->future_frame;
+    }
+  else
+    /* no future superstate on an existing edge */
+    {
+      rx_lock_superstate (rx, super);
+      if (!solve_destination (rx, df))
+	{
+	  rx_unlock_superstate (rx, super);
+	  return 0;
+	}
+      if (!df->effects
+	  && (df->edge->options->next_same_super_edge[0] == df->edge->options))
+	install_partial_transition (super, &df->future_frame,
+				    df->edge->cset[offset], offset * 32);
+      rx_unlock_superstate (rx, super);
+      return &df->future_frame;
+    }
+}
+
+
+
+
+
+/* The rest of the code provides a regex.c compatable interface. */
+
+
+__const__ char *re_error_msg[] =
+{
+  0,						/* REG_NOUT */
+  "No match",					/* REG_NOMATCH */
+  "Invalid regular expression",			/* REG_BADPAT */
+  "Invalid collation character",		/* REG_ECOLLATE */
+  "Invalid character class name",		/* REG_ECTYPE */
+  "Trailing backslash",				/* REG_EESCAPE */
+  "Invalid back reference",			/* REG_ESUBREG */
+  "Unmatched [ or [^",				/* REG_EBRACK */
+  "Unmatched ( or \\(",				/* REG_EPAREN */
+  "Unmatched \\{",				/* REG_EBRACE */
+  "Invalid content of \\{\\}",			/* REG_BADBR */
+  "Invalid range end",				/* REG_ERANGE */
+  "Memory exhausted",				/* REG_ESPACE */
+  "Invalid preceding regular expression",	/* REG_BADRPT */
+  "Premature end of regular expression",	/* REG_EEND */
+  "Regular expression too big",			/* REG_ESIZE */
+  "Unmatched ) or \\)",				/* REG_ERPAREN */
+};
+
+
+
+
+/* 
+ * Macros used while compiling patterns.
+ *
+ * By convention, PEND points just past the end of the uncompiled pattern,
+ * P points to the read position in the pattern.  `translate' is the name
+ * of the translation table (`TRANSLATE' is the name of a macro that looks
+ * things up in `translate').
+ */
+
+
+/*
+ * Fetch the next character in the uncompiled pattern---translating it 
+ * if necessary. *Also cast from a signed character in the constant
+ * string passed to us by the user to an unsigned char that we can use
+ * as an array index (in, e.g., `translate').
+ */
+#define PATFETCH(c)							\
+ do {if (p == pend) return REG_EEND;					\
+    c = (unsigned char) *p++;						\
+    c = translate[c];		 					\
+ } while (0)
+
+/* 
+ * Fetch the next character in the uncompiled pattern, with no
+ * translation.
+ */
+#define PATFETCH_RAW(c)							\
+  do {if (p == pend) return REG_EEND;					\
+    c = (unsigned char) *p++; 						\
+  } while (0)
+
+/* Go backwards one character in the pattern.  */
+#define PATUNFETCH p--
+
+
+#define TRANSLATE(d) translate[(unsigned char) (d)]
+
+typedef unsigned regnum_t;
+
+/* Since offsets can go either forwards or backwards, this type needs to
+ * be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1.
+ */
+typedef int pattern_offset_t;
+
+typedef struct
+{
+  struct rexp_node ** top_expression; /* was begalt */
+  struct rexp_node ** last_expression; /* was laststart */
+  pattern_offset_t inner_group_offset;
+  regnum_t regnum;
+} compile_stack_elt_t;
+
+typedef struct
+{
+  compile_stack_elt_t *stack;
+  unsigned size;
+  unsigned avail;			/* Offset of next open position.  */
+} compile_stack_type;
+
+
+#define INIT_COMPILE_STACK_SIZE 32
+
+#define COMPILE_STACK_EMPTY  (compile_stack.avail == 0)
+#define COMPILE_STACK_FULL  (compile_stack.avail == compile_stack.size)
+
+/* The next available element.  */
+#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
+
+
+/* Set the bit for character C in a list.  */
+#define SET_LIST_BIT(c)                               \
+  (b[((unsigned char) (c)) / CHARBITS]               \
+   |= 1 << (((unsigned char) c) % CHARBITS))
+
+/* Get the next unsigned number in the uncompiled pattern.  */
+#define GET_UNSIGNED_NUMBER(num) 					\
+  { if (p != pend)							\
+     {									\
+       PATFETCH (c); 							\
+       while (isdigit (c)) 						\
+         { 								\
+           if (num < 0)							\
+              num = 0;							\
+           num = num * 10 + c - '0'; 					\
+           if (p == pend) 						\
+              break; 							\
+           PATFETCH (c);						\
+         } 								\
+       } 								\
+    }		
+
+#define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
+
+#define IS_CHAR_CLASS(string)						\
+   (!strcmp (string, "alpha") || !strcmp (string, "upper")		\
+    || !strcmp (string, "lower") || !strcmp (string, "digit")		\
+    || !strcmp (string, "alnum") || !strcmp (string, "xdigit")		\
+    || !strcmp (string, "space") || !strcmp (string, "print")		\
+    || !strcmp (string, "punct") || !strcmp (string, "graph")		\
+    || !strcmp (string, "cntrl") || !strcmp (string, "blank"))
+
+
+
+/* These predicates are used in regex_compile. */
+
+/* P points to just after a ^ in PATTERN.  Return true if that ^ comes
+ * after an alternative or a begin-subexpression.  We assume there is at
+ * least one character before the ^.  
+ */
+
+#ifdef __STDC__
+static boolean
+at_begline_loc_p (__const__ char *pattern, __const__ char * p, reg_syntax_t syntax)
+#else
+static boolean
+at_begline_loc_p (pattern, p, syntax)
+     __const__ char *pattern;
+     __const__ char * p;
+     reg_syntax_t syntax;
+#endif
+{
+  __const__ char *prev = p - 2;
+  boolean prev_prev_backslash = ((prev > pattern) && (prev[-1] == '\\'));
+  
+    return
+      
+      (/* After a subexpression?  */
+       ((*prev == '(') && ((syntax & RE_NO_BK_PARENS) || prev_prev_backslash))
+       ||
+       /* After an alternative?  */
+       ((*prev == '|') && ((syntax & RE_NO_BK_VBAR) || prev_prev_backslash))
+       );
+}
+
+/* The dual of at_begline_loc_p.  This one is for $.  We assume there is
+ * at least one character after the $, i.e., `P < PEND'.
+ */
+
+#ifdef __STDC__
+static boolean
+at_endline_loc_p (__const__ char *p, __const__ char *pend, int syntax)
+#else
+static boolean
+at_endline_loc_p (p, pend, syntax)
+     __const__ char *p;
+     __const__ char *pend;
+     int syntax;
+#endif
+{
+  __const__ char *next = p;
+  boolean next_backslash = (*next == '\\');
+  __const__ char *next_next = (p + 1 < pend) ? (p + 1) : 0;
+  
+  return
+    (
+     /* Before a subexpression?  */
+     ((syntax & RE_NO_BK_PARENS)
+      ? (*next == ')')
+      : (next_backslash && next_next && (*next_next == ')')))
+    ||
+     /* Before an alternative?  */
+     ((syntax & RE_NO_BK_VBAR)
+      ? (*next == '|')
+      : (next_backslash && next_next && (*next_next == '|')))
+     );
+}
+
+
+
+unsigned char rx_id_translation[256] =
+{
+  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
+ 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
+ 250, 251, 252, 253, 254, 255
+};
+
+/* The compiler keeps an inverted translation table.
+ * This looks up/inititalize elements.
+ * VALID is an array of booleans that validate CACHE.
+ */
+
+#ifdef __STDC__
+static rx_Bitset
+inverse_translation (struct re_pattern_buffer * rxb,
+		     char * valid, rx_Bitset cache,
+		     unsigned char * translate, int c)
+#else
+static rx_Bitset
+inverse_translation (rxb, valid, cache, translate, c)
+     struct re_pattern_buffer * rxb;
+     char * valid;
+     rx_Bitset cache;
+     unsigned char * translate;
+     int c;
+#endif
+{
+  rx_Bitset cs
+    = cache + c * rx_bitset_numb_subsets (rxb->rx.local_cset_size); 
+
+  if (!valid[c])
+    {
+      int x;
+      int c_tr = TRANSLATE(c);
+      rx_bitset_null (rxb->rx.local_cset_size, cs);
+      for (x = 0; x < 256; ++x)	/* &&&& 13.37 */
+	if (TRANSLATE(x) == c_tr)
+	  RX_bitset_enjoin (cs, x);
+      valid[c] = 1;
+    }
+  return cs;
+}
+
+
+
+
+
+/* More subroutine declarations and macros for regex_compile.  */
+
+/* Returns true if REGNUM is in one of COMPILE_STACK's elements and 
+   false if it's not.  */
+
+#ifdef __STDC__
+static boolean
+group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum)
+#else
+static boolean
+group_in_compile_stack (compile_stack, regnum)
+    compile_stack_type compile_stack;
+    regnum_t regnum;
+#endif
+{
+  int this_element;
+
+  for (this_element = compile_stack.avail - 1;  
+       this_element >= 0; 
+       this_element--)
+    if (compile_stack.stack[this_element].regnum == regnum)
+      return true;
+
+  return false;
+}
+
+
+/*
+ * Read the ending character of a range (in a bracket expression) from the
+ * uncompiled pattern *P_PTR (which ends at PEND).  We assume the
+ * starting character is in `P[-2]'.  (`P[-1]' is the character `-'.)
+ * Then we set the translation of all bits between the starting and
+ * ending characters (inclusive) in the compiled pattern B.
+ * 
+ * Return an error code.
+ * 
+ * We use these short variable names so we can use the same macros as
+ * `regex_compile' itself.  
+ */
+
+#ifdef __STDC__
+static reg_errcode_t
+compile_range (struct re_pattern_buffer * rxb, rx_Bitset cs,
+	       __const__ char ** p_ptr, __const__ char * pend,
+	       unsigned char * translate, reg_syntax_t syntax,
+	       rx_Bitset inv_tr,  char * valid_inv_tr)
+#else
+static reg_errcode_t
+compile_range (rxb, cs, p_ptr, pend, translate, syntax, inv_tr, valid_inv_tr)
+     struct re_pattern_buffer * rxb;
+     rx_Bitset cs;
+     __const__ char ** p_ptr;
+     __const__ char * pend;
+     unsigned char * translate;
+     reg_syntax_t syntax;
+     rx_Bitset inv_tr;
+     char * valid_inv_tr;
+#endif
+{
+  unsigned this_char;
+
+  __const__ char *p = *p_ptr;
+
+  unsigned char range_end;
+  unsigned char range_start = TRANSLATE(p[-2]);
+
+  if (p == pend)
+    return REG_ERANGE;
+
+  PATFETCH (range_end);
+
+  (*p_ptr)++;
+
+  if (range_start > range_end)
+    return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
+
+  for (this_char = range_start; this_char <= range_end; this_char++)
+    {
+      rx_Bitset it =
+	inverse_translation (rxb, valid_inv_tr, inv_tr, translate, this_char);
+      rx_bitset_union (rxb->rx.local_cset_size, cs, it);
+    }
+  
+  return REG_NOERROR;
+}
+
+
+
+/* This searches a regexp for backreference side effects.
+ * It fills in the array OUT with 1 at the index of every register pair
+ * referenced by a backreference.
+ *
+ * This is used to help optimize patterns for searching.  The information is
+ * useful because, if the caller doesn't want register values, backreferenced
+ * registers are the only registers for which we need rx_backtrack.
+ */
+
+#ifdef __STDC__
+static void
+find_backrefs (char * out, struct rexp_node * rexp,
+	       struct re_se_params * params)
+#else
+static void
+find_backrefs (out, rexp, params)
+     char * out;
+     struct rexp_node * rexp;
+     struct re_se_params * params;
+#endif
+{
+  if (rexp)
+    switch (rexp->type)
+      {
+      case r_cset:
+      case r_data:
+	return;
+      case r_alternate:
+      case r_concat:
+      case r_opt:
+      case r_star:
+      case r_2phase_star:
+	find_backrefs (out, rexp->params.pair.left, params);
+	find_backrefs (out, rexp->params.pair.right, params);
+	return;
+      case r_side_effect:
+	if (   ((long)rexp->params.side_effect >= 0)
+	    && (params [(long)rexp->params.side_effect].se == re_se_backref))
+	  out[ params [(long)rexp->params.side_effect].op1] = 1;
+	return;
+      }
+}
+
+
+
+
+/* Returns 0 unless the pattern can match the empty string. */
+
+#ifdef __STDC__
+static int
+compute_fastset (struct re_pattern_buffer * rxb, struct rexp_node * rexp)
+#else
+static int
+compute_fastset (rxb, rexp)
+     struct re_pattern_buffer * rxb;
+     struct rexp_node * rexp;
+#endif
+{
+  if (!rexp)
+    return 1;
+  switch (rexp->type)
+    {
+    case r_data:
+      return 1;
+    case r_cset:
+      {
+	rx_bitset_union (rxb->rx.local_cset_size,
+			 rxb->fastset, rexp->params.cset);
+      }
+      return 0;
+    case r_concat:
+      return (compute_fastset (rxb, rexp->params.pair.left)
+	      && compute_fastset (rxb, rexp->params.pair.right));
+    case r_2phase_star:
+      compute_fastset (rxb, rexp->params.pair.left);
+      /* compute_fastset (rxb, rexp->params.pair.right);  nope... */
+      return 1;
+    case r_alternate:
+      return !!(compute_fastset (rxb, rexp->params.pair.left)
+		+ compute_fastset (rxb, rexp->params.pair.right));
+    case r_opt:
+    case r_star:
+      compute_fastset (rxb, rexp->params.pair.left);
+      return 1;
+    case r_side_effect:
+      return 1;
+    }
+
+  /* this should never happen */
+  return 0;
+}
+
+
+
+/* returns
+ *  1 -- yes, definately anchored by the given side effect.
+ *  2 -- maybe anchored, maybe the empty string.
+ *  0 -- definately not anchored
+ *  There is simply no other possibility.
+ */
+
+#ifdef __STDC__
+static int
+is_anchored (struct rexp_node * rexp, rx_side_effect se)
+#else
+static int
+is_anchored (rexp, se)
+     struct rexp_node * rexp;
+     rx_side_effect se;
+#endif
+{
+  if (!rexp)
+    return 2;
+  switch (rexp->type)
+    {
+    case r_cset:
+    case r_data:
+      return 0;
+    case r_concat:
+    case r_2phase_star:
+      {
+	int l = is_anchored (rexp->params.pair.left, se);
+	return (l == 2 ? is_anchored (rexp->params.pair.right, se) : l);
+      }
+    case r_alternate:
+      {
+	int l = is_anchored (rexp->params.pair.left, se);
+	int r = l ? is_anchored (rexp->params.pair.right, se) : 0;
+
+	if (l == r)
+	  return l;
+	else if ((l == 0) || (r == 0))
+	  return 0;
+	else
+	  return 2;
+      }
+    case r_opt:
+    case r_star:
+      return is_anchored (rexp->params.pair.left, se) ? 2 : 0;
+      
+    case r_side_effect:
+      return ((rexp->params.side_effect == se)
+	      ? 1 : 2);
+    }
+
+  /* this should never happen */
+  return 0;
+}
+
+
+
+/* This removes register assignments that aren't required by backreferencing.
+ * This can speed up explore_future, especially if it eliminates
+ * non-determinism in the superstate NFA.
+ * 
+ * NEEDED is an array of characters, presumably filled in by FIND_BACKREFS.
+ * The non-zero elements of the array indicate which register assignments
+ * can NOT be removed from the expression.
+ */
+
+#ifdef __STDC__
+static struct rexp_node *
+remove_unecessary_side_effects (struct rx * rx, char * needed,
+				struct rexp_node * rexp,
+				struct re_se_params * params)
+#else
+static struct rexp_node *
+remove_unecessary_side_effects (rx, needed, rexp, params)
+     struct rx * rx;
+     char * needed;
+     struct rexp_node * rexp;
+     struct re_se_params * params;
+#endif
+{
+  struct rexp_node * l;
+  struct rexp_node * r;
+  if (!rexp)
+    return 0;
+  else
+    switch (rexp->type)
+      {
+      case r_cset:
+      case r_data:
+	return rexp;
+      case r_alternate:
+      case r_concat:
+      case r_2phase_star:
+	l = remove_unecessary_side_effects (rx, needed,
+					    rexp->params.pair.left, params);
+	r = remove_unecessary_side_effects (rx, needed,
+					    rexp->params.pair.right, params);
+	if ((l && r) || (rexp->type != r_concat))
+	  {
+	    rexp->params.pair.left = l;
+	    rexp->params.pair.right = r;
+	    return rexp;
+	  }
+	else
+	  {
+	    rexp->params.pair.left = rexp->params.pair.right = 0;
+	    rx_free_rexp (rx, rexp);
+	    return l ? l : r;
+	  }
+      case r_opt:
+      case r_star:
+	l = remove_unecessary_side_effects (rx, needed,
+					    rexp->params.pair.left, params);
+	if (l)
+	  {
+	    rexp->params.pair.left = l;
+	    return rexp;
+	  }
+	else
+	  {
+	    rexp->params.pair.left = 0;
+	    rx_free_rexp (rx, rexp);
+	    return 0;
+	  }
+      case r_side_effect:
+	{
+	  int se = (long)rexp->params.side_effect;
+	  if (   (se >= 0)
+	      && (   ((enum re_side_effects)params[se].se == re_se_lparen)
+		  || ((enum re_side_effects)params[se].se == re_se_rparen))
+	      && (params [se].op1 > 0)
+	      && (!needed [params [se].op1]))
+	    {
+	      rx_free_rexp (rx, rexp);
+	      return 0;
+	    }
+	  else
+	    return rexp;
+	}
+      }
+
+  /* this should never happen */
+  return 0;
+}
+
+
+
+
+#ifdef __STDC__
+static int
+pointless_if_repeated (struct rexp_node * node, struct re_se_params * params)
+#else
+static int
+pointless_if_repeated (node, params)
+     struct rexp_node * node;
+     struct re_se_params * params;
+#endif
+{
+  if (!node)
+    return 1;
+  switch (node->type)
+    {
+    case r_cset:
+      return 0;
+    case r_alternate:
+    case r_concat:
+    case r_2phase_star:
+      return (pointless_if_repeated (node->params.pair.left, params)
+	      && pointless_if_repeated (node->params.pair.right, params));
+    case r_opt:
+    case r_star:
+      return pointless_if_repeated (node->params.pair.left, params);
+    case r_side_effect:
+      switch ((enum re_side_effects) (((long)node->params.side_effect < 0)
+	      ? (enum re_side_effects) (long) node->params.side_effect
+	      : (enum re_side_effects)params[(long)node->params.side_effect].se))
+	{
+	case re_se_try:
+	case re_se_at_dot:
+	case re_se_begbuf:
+	case re_se_hat:
+	case re_se_wordbeg:
+	case re_se_wordbound:
+	case re_se_notwordbound:
+	case re_se_wordend:
+	case re_se_endbuf:
+	case re_se_dollar:
+	case re_se_fail:
+	case re_se_win:
+	  return 1;
+	case re_se_lparen:
+	case re_se_rparen:
+	case re_se_iter:
+	case re_se_end_iter:
+	case re_se_syntax:
+	case re_se_not_syntax:
+	case re_se_backref:
+	  return 0;
+	}
+    case r_data:
+    default:
+      return 0;
+    }
+}
+
+
+
+
+#ifdef __STDC__
+static int
+registers_on_stack (struct re_pattern_buffer * rxb,
+		    struct rexp_node * rexp, int in_danger,
+		    struct re_se_params * params)
+#else
+static int
+registers_on_stack (rxb, rexp, in_danger, params)
+     struct re_pattern_buffer * rxb;
+     struct rexp_node * rexp;
+     int in_danger;
+     struct re_se_params * params;
+#endif
+{
+  if (!rexp)
+    return 0;
+  else
+    switch (rexp->type)
+      {
+      case r_cset:
+      case r_data:
+	return 0;
+      case r_alternate:
+      case r_concat:
+	return (   registers_on_stack (rxb, rexp->params.pair.left,
+				       in_danger, params)
+		|| (registers_on_stack
+		    (rxb, rexp->params.pair.right,
+		     in_danger, params)));
+      case r_opt:
+	return registers_on_stack (rxb, rexp->params.pair.left, 0, params);
+      case r_star:
+	return registers_on_stack (rxb, rexp->params.pair.left, 1, params);
+      case r_2phase_star:
+	return
+	  (   registers_on_stack (rxb, rexp->params.pair.left, 1, params)
+	   || registers_on_stack (rxb, rexp->params.pair.right, 1, params));
+      case r_side_effect:
+	{
+	  int se = (long)rexp->params.side_effect;
+	  if (   in_danger
+	      && (se >= 0)
+	      && (params [se].op1 > 0)
+	      && (   ((enum re_side_effects)params[se].se == re_se_lparen)
+		  || ((enum re_side_effects)params[se].se == re_se_rparen)))
+	    return 1;
+	  else
+	    return 0;
+	}
+      }
+
+  /* this should never happen */
+  return 0;
+}
+
+
+
+
+static char idempotent_complex_se[] =
+{
+#define RX_WANT_SE_DEFS 1
+#undef RX_DEF_SE
+#undef RX_DEF_CPLX_SE
+#define RX_DEF_SE(IDEM, NAME, VALUE)	      
+#define RX_DEF_CPLX_SE(IDEM, NAME, VALUE)     IDEM,
+#include "rx.h"
+#undef RX_DEF_SE
+#undef RX_DEF_CPLX_SE
+#undef RX_WANT_SE_DEFS
+  23
+};
+
+static char idempotent_se[] =
+{
+  13,
+#define RX_WANT_SE_DEFS 1
+#undef RX_DEF_SE
+#undef RX_DEF_CPLX_SE
+#define RX_DEF_SE(IDEM, NAME, VALUE)	      IDEM,
+#define RX_DEF_CPLX_SE(IDEM, NAME, VALUE)     
+#include "rx.h"
+#undef RX_DEF_SE
+#undef RX_DEF_CPLX_SE
+#undef RX_WANT_SE_DEFS
+  42
+};
+
+
+
+
+
+#ifdef __STDC__
+static int
+has_any_se (struct rx * rx,
+	    struct rexp_node * rexp)
+#else
+static int
+has_any_se (rx, rexp)
+     struct rx * rx;
+     struct rexp_node * rexp;
+#endif
+{
+  if (!rexp)
+    return 0;
+
+  switch (rexp->type)
+    {
+    case r_cset:
+    case r_data:
+      return 0;
+
+    case r_side_effect:
+      return 1;
+      
+    case r_2phase_star:
+    case r_concat:
+    case r_alternate:
+      return
+	(   has_any_se (rx, rexp->params.pair.left)
+	 || has_any_se (rx, rexp->params.pair.right));
+
+    case r_opt:
+    case r_star:
+      return has_any_se (rx, rexp->params.pair.left);
+    }
+
+  /* this should never happen */
+  return 0;
+}
+
+
+
+
+/* This must be called AFTER `convert_hard_loops' for a given REXP. */
+#ifdef __STDC__
+static int
+has_non_idempotent_epsilon_path (struct rx * rx,
+				 struct rexp_node * rexp,
+				 struct re_se_params * params)
+#else
+static int
+has_non_idempotent_epsilon_path (rx, rexp, params)
+     struct rx * rx;
+     struct rexp_node * rexp;
+     struct re_se_params * params;
+#endif
+{
+  if (!rexp)
+    return 0;
+
+  switch (rexp->type)
+    {
+    case r_cset:
+    case r_data:
+    case r_star:
+      return 0;
+
+    case r_side_effect:
+      return
+	!((long)rexp->params.side_effect > 0
+	  ? idempotent_complex_se [ params [(long)rexp->params.side_effect].se ]
+	  : idempotent_se [-(long)rexp->params.side_effect]);
+      
+    case r_alternate:
+      return
+	(   has_non_idempotent_epsilon_path (rx,
+					     rexp->params.pair.left, params)
+	 || has_non_idempotent_epsilon_path (rx,
+					     rexp->params.pair.right, params));
+
+    case r_2phase_star:
+    case r_concat:
+      return
+	(   has_non_idempotent_epsilon_path (rx,
+					     rexp->params.pair.left, params)
+	 && has_non_idempotent_epsilon_path (rx,
+					     rexp->params.pair.right, params));
+
+    case r_opt:
+      return has_non_idempotent_epsilon_path (rx,
+					      rexp->params.pair.left, params);
+    }
+
+  /* this should never happen */
+  return 0;
+}
+
+
+
+
+/* This computes rougly what it's name suggests.   It can (and does) go wrong 
+ * in the direction of returning spurious 0 without causing disasters.
+ */
+#ifdef __STDC__
+static int
+begins_with_complex_se (struct rx * rx, struct rexp_node * rexp)
+#else
+static int
+begins_with_complex_se (rx, rexp)
+     struct rx * rx;
+     struct rexp_node * rexp;
+#endif
+{
+  if (!rexp)
+    return 0;
+
+  switch (rexp->type)
+    {
+    case r_cset:
+    case r_data:
+      return 0;
+
+    case r_side_effect:
+      return ((long)rexp->params.side_effect >= 0);
+      
+    case r_alternate:
+      return
+	(   begins_with_complex_se (rx, rexp->params.pair.left)
+	 && begins_with_complex_se (rx, rexp->params.pair.right));
+
+
+    case r_concat:
+      return has_any_se (rx, rexp->params.pair.left);
+    case r_opt:
+    case r_star:
+    case r_2phase_star:
+      return 0;
+    }
+
+  /* this should never happen */
+  return 0;
+}
+
+
+
+/* This destructively removes some of the re_se_tv side effects from 
+ * a rexp tree.  In particular, during parsing re_se_tv was inserted on the
+ * right half of every | to guarantee that posix path preference could be 
+ * honored.  This function removes some which it can be determined aren't 
+ * needed.  
+ */
+
+#ifdef __STDC__
+static void
+speed_up_alt (struct rx * rx,
+	      struct rexp_node * rexp,
+	      int unposix)
+#else
+static void
+speed_up_alt (rx, rexp, unposix)
+     struct rx * rx;
+     struct rexp_node * rexp;
+     int unposix;
+#endif
+{
+  if (!rexp)
+    return;
+
+  switch (rexp->type)
+    {
+    case r_cset:
+    case r_data:
+    case r_side_effect:
+      return;
+
+    case r_opt:
+    case r_star:
+      speed_up_alt (rx, rexp->params.pair.left, unposix);
+      return;
+
+    case r_2phase_star:
+    case r_concat:
+      speed_up_alt (rx, rexp->params.pair.left, unposix);
+      speed_up_alt (rx, rexp->params.pair.right, unposix);
+      return;
+
+    case r_alternate:
+      /* the right child is guaranteed to be (concat re_se_tv <subexp>) */
+
+      speed_up_alt (rx, rexp->params.pair.left, unposix);
+      speed_up_alt (rx, rexp->params.pair.right->params.pair.right, unposix);
+      
+      if (   unposix
+	  || (begins_with_complex_se
+	      (rx, rexp->params.pair.right->params.pair.right))
+	  || !(   has_any_se (rx, rexp->params.pair.right->params.pair.right)
+	       || has_any_se (rx, rexp->params.pair.left)))
+	{
+	  struct rexp_node * conc = rexp->params.pair.right;
+	  rexp->params.pair.right = conc->params.pair.right;
+	  conc->params.pair.right = 0;
+	  rx_free_rexp (rx, conc);
+	}
+    }
+}
+
+
+
+
+
+
+/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
+   Returns one of error codes defined in `regex.h', or zero for success.
+
+   Assumes the `allocated' (and perhaps `buffer') and `translate'
+   fields are set in BUFP on entry.
+
+   If it succeeds, results are put in BUFP (if it returns an error, the
+   contents of BUFP are undefined):
+     `buffer' is the compiled pattern;
+     `syntax' is set to SYNTAX;
+     `used' is set to the length of the compiled pattern;
+     `fastmap_accurate' is set to zero;
+     `re_nsub' is set to the number of groups in PATTERN;
+     `not_bol' and `not_eol' are set to zero.
+   
+   The `fastmap' and `newline_anchor' fields are neither
+   examined nor set.  */
+
+
+
+#ifdef __STDC__
+RX_DECL reg_errcode_t
+rx_compile (__const__ char *pattern, int size,
+	    reg_syntax_t syntax,
+	    struct re_pattern_buffer * rxb) 
+#else
+RX_DECL reg_errcode_t
+rx_compile (pattern, size, syntax, rxb)
+     __const__ char *pattern;
+     int size;
+     reg_syntax_t syntax;
+     struct re_pattern_buffer * rxb;
+#endif
+{
+  RX_subset
+    inverse_translate [CHAR_SET_SIZE * rx_bitset_numb_subsets(CHAR_SET_SIZE)];
+  char
+    validate_inv_tr [CHAR_SET_SIZE * rx_bitset_numb_subsets(CHAR_SET_SIZE)];
+
+  /* We fetch characters from PATTERN here.  Even though PATTERN is
+     `char *' (i.e., signed), we declare these variables as unsigned, so
+     they can be reliably used as array indices.  */
+  register unsigned char c, c1;
+  
+  /* A random tempory spot in PATTERN.  */
+  __const__ char *p1;
+  
+  /* Keeps track of unclosed groups.  */
+  compile_stack_type compile_stack;
+
+  /* Points to the current (ending) position in the pattern.  */
+  __const__ char *p = pattern;
+  __const__ char *pend = pattern + size;
+  
+  /* How to translate the characters in the pattern.  */
+  unsigned char *translate = (rxb->translate
+			      ? rxb->translate
+			      : rx_id_translation);
+
+  /* When parsing is done, this will hold the expression tree. */
+  struct rexp_node * rexp = 0;
+
+  /* In the midst of compilation, this holds onto the regexp 
+   * first parst while rexp goes on to aquire additional constructs.
+   */
+  struct rexp_node * orig_rexp = 0;
+  struct rexp_node * fewer_side_effects = 0;
+
+  /* This and top_expression are saved on the compile stack. */
+  struct rexp_node ** top_expression = &rexp;
+  struct rexp_node ** last_expression = top_expression;
+  
+  /* Parameter to `goto append_node' */
+  struct rexp_node * append;
+
+  /* Counts open-groups as they are encountered.  This is the index of the
+   * innermost group being compiled.
+   */
+  regnum_t regnum = 0;
+
+  /* Place in the uncompiled pattern (i.e., the {) to
+   * which to go back if the interval is invalid.  
+   */
+  __const__ char *beg_interval;
+
+  struct re_se_params * params = 0;
+  int paramc = 0;		/* How many complex side effects so far? */
+
+  rx_side_effect side;		/* param to `goto add_side_effect' */
+
+  bzero (validate_inv_tr, sizeof (validate_inv_tr));
+
+  rxb->rx.instruction_table = rx_id_instruction_table;
+
+
+  /* Initialize the compile stack.  */
+  compile_stack.stack =  (( compile_stack_elt_t *) malloc ((INIT_COMPILE_STACK_SIZE) * sizeof ( compile_stack_elt_t)));
+  if (compile_stack.stack == 0)
+    return REG_ESPACE;
+
+  compile_stack.size = INIT_COMPILE_STACK_SIZE;
+  compile_stack.avail = 0;
+
+  /* Initialize the pattern buffer.  */
+  rxb->rx.cache = &default_cache;
+  rxb->syntax = syntax;
+  rxb->fastmap_accurate = 0;
+  rxb->not_bol = rxb->not_eol = 0;
+  rxb->least_subs = 0;
+  
+  /* Always count groups, whether or not rxb->no_sub is set.  
+   * The whole pattern is implicitly group 0, so counting begins
+   * with 1.
+   */
+  rxb->re_nsub = 0;
+
+#if !defined (emacs) && !defined (SYNTAX_TABLE)
+  /* Initialize the syntax table.  */
+   init_syntax_once ();
+#endif
+
+  /* Loop through the uncompiled pattern until we're at the end.  */
+  while (p != pend)
+    {
+      PATFETCH (c);
+
+      switch (c)
+        {
+        case '^':
+          {
+            if (   /* If at start of pattern, it's an operator.  */
+                   p == pattern + 1
+                   /* If context independent, it's an operator.  */
+                || syntax & RE_CONTEXT_INDEP_ANCHORS
+                   /* Otherwise, depends on what's come before.  */
+                || at_begline_loc_p (pattern, p, syntax))
+	      {
+		struct rexp_node * n
+		  = rx_mk_r_side_effect (&rxb->rx, (rx_side_effect)re_se_hat);
+		if (!n)
+		  return REG_ESPACE;
+		append = n;
+		goto append_node;
+	      }
+            else
+              goto normal_char;
+          }
+          break;
+
+
+        case '$':
+          {
+            if (   /* If at end of pattern, it's an operator.  */
+                   p == pend 
+                   /* If context independent, it's an operator.  */
+                || syntax & RE_CONTEXT_INDEP_ANCHORS
+                   /* Otherwise, depends on what's next.  */
+                || at_endline_loc_p (p, pend, syntax))
+	      {
+		struct rexp_node * n
+		  = rx_mk_r_side_effect (&rxb->rx, (rx_side_effect)re_se_dollar);
+		if (!n)
+		  return REG_ESPACE;
+		append = n;
+		goto append_node;
+	      }
+             else
+               goto normal_char;
+           }
+           break;
+
+
+	case '+':
+        case '?':
+          if ((syntax & RE_BK_PLUS_QM)
+              || (syntax & RE_LIMITED_OPS))
+            goto normal_char;
+
+        handle_plus:
+        case '*':
+          /* If there is no previous pattern... */
+          if (pointless_if_repeated (*last_expression, params))
+            {
+              if (syntax & RE_CONTEXT_INVALID_OPS)
+                return REG_BADRPT;
+              else if (!(syntax & RE_CONTEXT_INDEP_OPS))
+                goto normal_char;
+            }
+
+          {
+            /* 1 means zero (many) matches is allowed.  */
+            char zero_times_ok = 0, many_times_ok = 0;
+
+            /* If there is a sequence of repetition chars, collapse it
+               down to just one (the right one).  We can't combine
+               interval operators with these because of, e.g., `a{2}*',
+               which should only match an even number of `a's.  */
+
+            for (;;)
+              {
+                zero_times_ok |= c != '+';
+                many_times_ok |= c != '?';
+
+                if (p == pend)
+                  break;
+
+                PATFETCH (c);
+
+                if (c == '*'
+                    || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
+                  ;
+
+                else if (syntax & RE_BK_PLUS_QM  &&  c == '\\')
+                  {
+                    if (p == pend) return REG_EESCAPE;
+
+                    PATFETCH (c1);
+                    if (!(c1 == '+' || c1 == '?'))
+                      {
+                        PATUNFETCH;
+                        PATUNFETCH;
+                        break;
+                      }
+
+                    c = c1;
+                  }
+                else
+                  {
+                    PATUNFETCH;
+                    break;
+                  }
+
+                /* If we get here, we found another repeat character.  */
+               }
+
+            /* Star, etc. applied to an empty pattern is equivalent
+               to an empty pattern.  */
+            if (!last_expression)
+              break;
+
+	    /* Now we know whether or not zero matches is allowed
+	     * and also whether or not two or more matches is allowed.
+	     */
+
+	    {
+	      struct rexp_node * inner_exp = *last_expression;
+	      int need_sync = 0;
+
+	      if (many_times_ok
+		  && has_non_idempotent_epsilon_path (&rxb->rx,
+						      inner_exp, params))
+		{
+		  struct rexp_node * pusher
+		    = rx_mk_r_side_effect (&rxb->rx,
+					   (rx_side_effect)re_se_pushpos);
+		  struct rexp_node * checker
+		    = rx_mk_r_side_effect (&rxb->rx,
+					   (rx_side_effect)re_se_chkpos);
+		  struct rexp_node * pushback
+		    = rx_mk_r_side_effect (&rxb->rx,
+					   (rx_side_effect)re_se_pushback);
+		  rx_Bitset cs = rx_cset (&rxb->rx);
+		  struct rexp_node * lit_t = rx_mk_r_cset (&rxb->rx, cs);
+		  struct rexp_node * fake_state
+		    = rx_mk_r_concat (&rxb->rx, pushback, lit_t);
+		  struct rexp_node * phase2
+		    = rx_mk_r_concat (&rxb->rx, checker, fake_state);
+		  struct rexp_node * popper
+		    = rx_mk_r_side_effect (&rxb->rx,
+					   (rx_side_effect)re_se_poppos);
+		  struct rexp_node * star
+		    = rx_mk_r_2phase_star (&rxb->rx, inner_exp, phase2);
+		  struct rexp_node * a
+		    = rx_mk_r_concat (&rxb->rx, pusher, star);
+		  struct rexp_node * whole_thing
+		    = rx_mk_r_concat (&rxb->rx, a, popper);
+		  if (!(pusher && star && pushback && lit_t && fake_state
+			&& lit_t && phase2 && checker && popper
+			&& a && whole_thing))
+		    return REG_ESPACE;
+		  RX_bitset_enjoin (cs, 't');
+		  *last_expression = whole_thing;
+		}
+	      else
+		{
+		  struct rexp_node * star =
+		    (many_times_ok ? rx_mk_r_star : rx_mk_r_opt)
+		      (&rxb->rx, *last_expression);
+		  if (!star)
+		    return REG_ESPACE;
+		  *last_expression = star;
+		  need_sync = has_any_se (&rxb->rx, *last_expression);
+		}
+	      if (!zero_times_ok)
+		{
+		  struct rexp_node * concat
+		    = rx_mk_r_concat (&rxb->rx, inner_exp,
+				      rx_copy_rexp (&rxb->rx,
+						    *last_expression));
+		  if (!concat)
+		    return REG_ESPACE;
+		  *last_expression = concat;
+		}
+	      if (need_sync)
+		{
+		  int sync_se = paramc;
+		  params = (params
+			    ? ((struct re_se_params *)
+			       realloc (params,
+					sizeof (*params) * (1 + paramc)))
+			    : ((struct re_se_params *)
+			       malloc (sizeof (*params))));
+		  if (!params)
+		    return REG_ESPACE;
+		  ++paramc;
+		  params [sync_se].se = re_se_tv;
+		  side = (rx_side_effect)sync_se;
+		  goto add_side_effect;
+		}
+	    }
+	    /* The old regex.c used to optimize `.*\n'.  
+	     * Maybe rx should too?
+	     */
+	  }
+	  break;
+
+
+	case '.':
+	  {
+	    rx_Bitset cs = rx_cset (&rxb->rx);
+	    struct rexp_node * n = rx_mk_r_cset (&rxb->rx, cs);
+	    if (!(cs && n))
+	      return REG_ESPACE;
+
+	    rx_bitset_universe (rxb->rx.local_cset_size, cs);
+	    if (!(rxb->syntax & RE_DOT_NEWLINE))
+	      RX_bitset_remove (cs, '\n');
+	    if (!(rxb->syntax & RE_DOT_NOT_NULL))
+	      RX_bitset_remove (cs, 0);
+
+	    append = n;
+	    goto append_node;
+	    break;
+	  }
+
+
+        case '[':
+	  if (p == pend) return REG_EBRACK;
+          {
+            boolean had_char_class = false;
+	    rx_Bitset cs = rx_cset (&rxb->rx);
+	    struct rexp_node * node = rx_mk_r_cset (&rxb->rx, cs);
+	    int is_inverted = *p == '^';
+	    
+	    if (!(node && cs))
+	      return REG_ESPACE;
+	    
+	    /* This branch of the switch is normally exited with
+	     *`goto append_node'
+	     */
+	    append = node;
+	    
+            if (is_inverted)
+	      p++;
+	    
+            /* Remember the first position in the bracket expression.  */
+            p1 = p;
+	    
+            /* Read in characters and ranges, setting map bits.  */
+            for (;;)
+              {
+                if (p == pend) return REG_EBRACK;
+		
+                PATFETCH (c);
+		
+                /* \ might escape characters inside [...] and [^...].  */
+                if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+                  {
+                    if (p == pend) return REG_EESCAPE;
+		    
+                    PATFETCH (c1);
+		    {
+		      rx_Bitset it = inverse_translation (rxb, 
+							  validate_inv_tr,
+							  inverse_translate,
+							  translate,
+							  c1);
+		      rx_bitset_union (rxb->rx.local_cset_size, cs, it);
+		    }
+                    continue;
+                  }
+		
+                /* Could be the end of the bracket expression.  If it's
+                   not (i.e., when the bracket expression is `[]' so
+                   far), the ']' character bit gets set way below.  */
+                if (c == ']' && p != p1 + 1)
+                  goto finalize_class_and_append;
+		
+                /* Look ahead to see if it's a range when the last thing
+                   was a character class.  */
+                if (had_char_class && c == '-' && *p != ']')
+                  return REG_ERANGE;
+		
+                /* Look ahead to see if it's a range when the last thing
+                   was a character: if this is a hyphen not at the
+                   beginning or the end of a list, then it's the range
+                   operator.  */
+                if (c == '-' 
+                    && !(p - 2 >= pattern && p[-2] == '[') 
+                    && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
+                    && *p != ']')
+                  {
+                    reg_errcode_t ret
+                      = compile_range (rxb, cs, &p, pend, translate, syntax,
+				       inverse_translate, validate_inv_tr);
+                    if (ret != REG_NOERROR) return ret;
+                  }
+		
+                else if (p[0] == '-' && p[1] != ']')
+                  { /* This handles ranges made up of characters only.  */
+                    reg_errcode_t ret;
+		    
+		    /* Move past the `-'.  */
+                    PATFETCH (c1);
+                    
+                    ret = compile_range (rxb, cs, &p, pend, translate, syntax,
+					 inverse_translate, validate_inv_tr);
+                    if (ret != REG_NOERROR) return ret;
+                  }
+		
+                /* See if we're at the beginning of a possible character
+                   class.  */
+		
+		else if ((syntax & RE_CHAR_CLASSES)
+			 && (c == '[') && (*p == ':'))
+                  {
+                    char str[CHAR_CLASS_MAX_LENGTH + 1];
+		    
+                    PATFETCH (c);
+                    c1 = 0;
+		    
+                    /* If pattern is `[[:'.  */
+                    if (p == pend) return REG_EBRACK;
+		    
+                    for (;;)
+                      {
+                        PATFETCH (c);
+                        if (c == ':' || c == ']' || p == pend
+                            || c1 == CHAR_CLASS_MAX_LENGTH)
+			  break;
+                        str[c1++] = c;
+                      }
+                    str[c1] = '\0';
+		    
+                    /* If isn't a word bracketed by `[:' and:`]':
+                       undo the ending character, the letters, and leave 
+                       the leading `:' and `[' (but set bits for them).  */
+                    if (c == ':' && *p == ']')
+                      {
+                        int ch;
+                        boolean is_alnum = !strcmp (str, "alnum");
+                        boolean is_alpha = !strcmp (str, "alpha");
+                        boolean is_blank = !strcmp (str, "blank");
+                        boolean is_cntrl = !strcmp (str, "cntrl");
+                        boolean is_digit = !strcmp (str, "digit");
+                        boolean is_graph = !strcmp (str, "graph");
+                        boolean is_lower = !strcmp (str, "lower");
+                        boolean is_print = !strcmp (str, "print");
+                        boolean is_punct = !strcmp (str, "punct");
+                        boolean is_space = !strcmp (str, "space");
+                        boolean is_upper = !strcmp (str, "upper");
+                        boolean is_xdigit = !strcmp (str, "xdigit");
+                        
+                        if (!IS_CHAR_CLASS (str)) return REG_ECTYPE;
+			
+                        /* Throw away the ] at the end of the character
+                           class.  */
+                        PATFETCH (c);					
+			
+                        if (p == pend) return REG_EBRACK;
+			
+                        for (ch = 0; ch < 1 << CHARBITS; ch++)
+                          {
+                            if (   (is_alnum  && isalnum (ch))
+                                || (is_alpha  && isalpha (ch))
+                                || (is_blank  && isblank (ch))
+                                || (is_cntrl  && iscntrl (ch))
+                                || (is_digit  && isdigit (ch))
+                                || (is_graph  && isgraph (ch))
+                                || (is_lower  && islower (ch))
+                                || (is_print  && isprint (ch))
+                                || (is_punct  && ispunct (ch))
+                                || (is_space  && isspace (ch))
+                                || (is_upper  && isupper (ch))
+                                || (is_xdigit && isxdigit (ch)))
+			      {
+				rx_Bitset it =
+				  inverse_translation (rxb, 
+						       validate_inv_tr,
+						       inverse_translate,
+						       translate,
+						       ch);
+				rx_bitset_union (rxb->rx.local_cset_size,
+						 cs, it);
+			      }
+                          }
+                        had_char_class = true;
+                      }
+                    else
+                      {
+                        c1++;
+                        while (c1--)    
+                          PATUNFETCH;
+			{
+			  rx_Bitset it =
+			    inverse_translation (rxb, 
+						 validate_inv_tr,
+						 inverse_translate,
+						 translate,
+						 '[');
+			  rx_bitset_union (rxb->rx.local_cset_size,
+					   cs, it);
+			}
+			{
+			  rx_Bitset it =
+			    inverse_translation (rxb, 
+						 validate_inv_tr,
+						 inverse_translate,
+						 translate,
+						 ':');
+			  rx_bitset_union (rxb->rx.local_cset_size,
+					   cs, it);
+			}
+                        had_char_class = false;
+                      }
+                  }
+                else
+                  {
+                    had_char_class = false;
+		    {
+		      rx_Bitset it = inverse_translation (rxb, 
+							  validate_inv_tr,
+							  inverse_translate,
+							  translate,
+							  c);
+		      rx_bitset_union (rxb->rx.local_cset_size, cs, it);
+		    }
+                  }
+              }
+
+	  finalize_class_and_append:
+	    if (is_inverted)
+	      {
+		rx_bitset_complement (rxb->rx.local_cset_size, cs);
+		if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
+		  RX_bitset_remove (cs, '\n');
+	      }
+	    goto append_node;
+          }
+          break;
+
+
+	case '(':
+          if (syntax & RE_NO_BK_PARENS)
+            goto handle_open;
+          else
+            goto normal_char;
+
+
+        case ')':
+          if (syntax & RE_NO_BK_PARENS)
+            goto handle_close;
+          else
+            goto normal_char;
+
+
+        case '\n':
+          if (syntax & RE_NEWLINE_ALT)
+            goto handle_alt;
+          else
+            goto normal_char;
+
+
+	case '|':
+          if (syntax & RE_NO_BK_VBAR)
+            goto handle_alt;
+          else
+            goto normal_char;
+
+
+        case '{':
+	  if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+	    goto handle_interval;
+	  else
+	    goto normal_char;
+
+
+        case '\\':
+          if (p == pend) return REG_EESCAPE;
+
+          /* Do not translate the character after the \, so that we can
+             distinguish, e.g., \B from \b, even if we normally would
+             translate, e.g., B to b.  */
+          PATFETCH_RAW (c);
+
+          switch (c)
+            {
+            case '(':
+              if (syntax & RE_NO_BK_PARENS)
+                goto normal_backslash;
+
+            handle_open:
+              rxb->re_nsub++;
+              regnum++;
+              if (COMPILE_STACK_FULL)
+                { 
+                  ((compile_stack.stack) =
+		   (compile_stack_elt_t *) realloc (compile_stack.stack, ( compile_stack.size << 1) * sizeof (
+													      compile_stack_elt_t)));
+                  if (compile_stack.stack == 0) return REG_ESPACE;
+
+                  compile_stack.size <<= 1;
+                }
+
+	      if (*last_expression)
+		{
+		  struct rexp_node * concat
+		    = rx_mk_r_concat (&rxb->rx, *last_expression, 0);
+		  if (!concat)
+		    return REG_ESPACE;
+		  *last_expression = concat;
+		  last_expression = &concat->params.pair.right;
+		}
+
+              /*
+	       * These are the values to restore when we hit end of this
+               * group.  
+	       */
+	      COMPILE_STACK_TOP.top_expression = top_expression;
+	      COMPILE_STACK_TOP.last_expression = last_expression;
+              COMPILE_STACK_TOP.regnum = regnum;
+	      
+              compile_stack.avail++;
+	      
+	      top_expression = last_expression;
+	      break;
+
+
+            case ')':
+              if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
+
+            handle_close:
+              /* See similar code for backslashed left paren above.  */
+              if (COMPILE_STACK_EMPTY)
+                if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+                  goto normal_char;
+                else
+                  return REG_ERPAREN;
+
+              /* Since we just checked for an empty stack above, this
+                 ``can't happen''.  */
+
+              {
+                /* We don't just want to restore into `regnum', because
+                   later groups should continue to be numbered higher,
+                   as in `(ab)c(de)' -- the second group is #2.  */
+                regnum_t this_group_regnum;
+		struct rexp_node ** inner = top_expression;
+
+                compile_stack.avail--;
+		top_expression = COMPILE_STACK_TOP.top_expression;
+		last_expression = COMPILE_STACK_TOP.last_expression;
+                this_group_regnum = COMPILE_STACK_TOP.regnum;
+		{
+		  int left_se = paramc;
+		  int right_se = paramc + 1;
+
+		  params = (params
+			    ? ((struct re_se_params *)
+			       realloc (params,
+					(paramc + 2) * sizeof (params[0])))
+			    : ((struct re_se_params *)
+			       malloc (2 * sizeof (params[0]))));
+		  if (!params)
+		    return REG_ESPACE;
+		  paramc += 2;
+
+		  params[left_se].se = re_se_lparen;
+		  params[left_se].op1 = this_group_regnum;
+		  params[right_se].se = re_se_rparen;
+		  params[right_se].op1 = this_group_regnum;
+		  {
+		    struct rexp_node * left
+		      = rx_mk_r_side_effect (&rxb->rx,
+					     (rx_side_effect)left_se);
+		    struct rexp_node * right
+		      = rx_mk_r_side_effect (&rxb->rx,
+					     (rx_side_effect)right_se);
+		    struct rexp_node * c1
+		      = (*inner
+			 ? rx_mk_r_concat (&rxb->rx, left, *inner) : left);
+		    struct rexp_node * c2
+		      = rx_mk_r_concat (&rxb->rx, c1, right);
+		    if (!(left && right && c1 && c2))
+		      return REG_ESPACE;
+		    *inner = c2;
+		  }
+		}
+		break;
+	      }
+
+            case '|':					/* `\|'.  */
+              if ((syntax & RE_LIMITED_OPS) || (syntax & RE_NO_BK_VBAR))
+                goto normal_backslash;
+            handle_alt:
+              if (syntax & RE_LIMITED_OPS)
+                goto normal_char;
+
+	      {
+		struct rexp_node * alt
+		  = rx_mk_r_alternate (&rxb->rx, *top_expression, 0);
+		if (!alt)
+		  return REG_ESPACE;
+		*top_expression = alt;
+		last_expression = &alt->params.pair.right;
+		{
+		  int sync_se = paramc;
+
+		  params = (params
+			    ? ((struct re_se_params *)
+			       realloc (params,
+					(paramc + 1) * sizeof (params[0])))
+			    : ((struct re_se_params *)
+			       malloc (sizeof (params[0]))));
+		  if (!params)
+		    return REG_ESPACE;
+		  ++paramc;
+
+		  params[sync_se].se = re_se_tv;
+		  {
+		    struct rexp_node * sync
+		      = rx_mk_r_side_effect (&rxb->rx,
+					     (rx_side_effect)sync_se);
+		    struct rexp_node * conc
+		      = rx_mk_r_concat (&rxb->rx, sync, 0);
+
+		    if (!sync || !conc)
+		      return REG_ESPACE;
+
+		    *last_expression = conc;
+		    last_expression = &conc->params.pair.right;
+		  }
+		}
+	      }
+              break;
+
+
+            case '{': 
+              /* If \{ is a literal.  */
+              if (!(syntax & RE_INTERVALS)
+                     /* If we're at `\{' and it's not the open-interval 
+                        operator.  */
+                  || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+                  || (p - 2 == pattern  &&  p == pend))
+                goto normal_backslash;
+
+            handle_interval:
+              {
+                /* If got here, then the syntax allows intervals.  */
+
+                /* At least (most) this many matches must be made.  */
+                int lower_bound = -1, upper_bound = -1;
+
+                beg_interval = p - 1;
+
+                if (p == pend)
+                  {
+                    if (syntax & RE_NO_BK_BRACES)
+                      goto unfetch_interval;
+                    else
+                      return REG_EBRACE;
+                  }
+
+                GET_UNSIGNED_NUMBER (lower_bound);
+
+                if (c == ',')
+                  {
+                    GET_UNSIGNED_NUMBER (upper_bound);
+                    if (upper_bound < 0) upper_bound = RE_DUP_MAX;
+                  }
+                else
+                  /* Interval such as `{1}' => match exactly once. */
+                  upper_bound = lower_bound;
+
+                if (lower_bound < 0 || upper_bound > RE_DUP_MAX
+                    || lower_bound > upper_bound)
+                  {
+                    if (syntax & RE_NO_BK_BRACES)
+                      goto unfetch_interval;
+                    else 
+                      return REG_BADBR;
+                  }
+
+                if (!(syntax & RE_NO_BK_BRACES)) 
+                  {
+                    if (c != '\\') return REG_EBRACE;
+                    PATFETCH (c);
+                  }
+
+                if (c != '}')
+                  {
+                    if (syntax & RE_NO_BK_BRACES)
+                      goto unfetch_interval;
+                    else 
+                      return REG_BADBR;
+                  }
+
+                /* We just parsed a valid interval.  */
+
+                /* If it's invalid to have no preceding re.  */
+                if (pointless_if_repeated (*last_expression, params))
+                  {
+                    if (syntax & RE_CONTEXT_INVALID_OPS)
+                      return REG_BADRPT;
+                    else if (!(syntax & RE_CONTEXT_INDEP_OPS))
+                      goto unfetch_interval;
+		    /* was: else laststart = b; */
+                  }
+
+                /* If the upper bound is zero, don't want to iterate
+                 * at all.
+		 */
+                 if (upper_bound == 0)
+		   {
+		     if (*last_expression)
+		       {
+			 rx_free_rexp (&rxb->rx, *last_expression);
+			 *last_expression = 0;
+		       }
+		   }
+		else
+		  /* Otherwise, we have a nontrivial interval. */
+		  {
+		    int iter_se = paramc;
+		    int end_se = paramc + 1;
+		    params = (params
+			      ? ((struct re_se_params *)
+				 realloc (params,
+					  sizeof (*params) * (2 + paramc)))
+			      : ((struct re_se_params *)
+				 malloc (2 * sizeof (*params))));
+		    if (!params)
+		      return REG_ESPACE;
+		    paramc += 2;
+		    params [iter_se].se = re_se_iter;
+		    params [iter_se].op1 = lower_bound;
+		    params[iter_se].op2 = upper_bound;
+
+		    params[end_se].se = re_se_end_iter;
+		    params[end_se].op1 = lower_bound;
+		    params[end_se].op2 = upper_bound;
+		    {
+		      struct rexp_node * push0
+			= rx_mk_r_side_effect (&rxb->rx,
+					       (rx_side_effect)re_se_push0);
+		      struct rexp_node * start_one_iter
+			= rx_mk_r_side_effect (&rxb->rx,
+					       (rx_side_effect)iter_se);
+		      struct rexp_node * phase1
+			= rx_mk_r_concat (&rxb->rx, start_one_iter,
+					  *last_expression);
+		      struct rexp_node * pushback
+			= rx_mk_r_side_effect (&rxb->rx,
+					       (rx_side_effect)re_se_pushback);
+		      rx_Bitset cs = rx_cset (&rxb->rx);
+		      struct rexp_node * lit_t
+			= rx_mk_r_cset (&rxb->rx, cs);
+		      struct rexp_node * phase2
+			= rx_mk_r_concat (&rxb->rx, pushback, lit_t);
+		      struct rexp_node * loop
+			= rx_mk_r_2phase_star (&rxb->rx, phase1, phase2);
+		      struct rexp_node * push_n_loop
+			= rx_mk_r_concat (&rxb->rx, push0, loop);
+		      struct rexp_node * final_test
+			= rx_mk_r_side_effect (&rxb->rx,
+					       (rx_side_effect)end_se);
+		      struct rexp_node * full_exp
+			= rx_mk_r_concat (&rxb->rx, push_n_loop, final_test);
+
+		      if (!(push0 && start_one_iter && phase1
+			    && pushback && lit_t && phase2
+			    && loop && push_n_loop && final_test && full_exp))
+			return REG_ESPACE;
+
+		      RX_bitset_enjoin(cs, 't');
+
+		      *last_expression = full_exp;
+		    }
+		  }
+                beg_interval = 0;
+              }
+              break;
+
+            unfetch_interval:
+              /* If an invalid interval, match the characters as literals.  */
+               p = beg_interval;
+               beg_interval = 0;
+
+               /* normal_char and normal_backslash need `c'.  */
+               PATFETCH (c);	
+
+               if (!(syntax & RE_NO_BK_BRACES))
+                 {
+                   if (p > pattern  &&  p[-1] == '\\')
+                     goto normal_backslash;
+                 }
+               goto normal_char;
+
+#ifdef emacs
+            /* There is no way to specify the before_dot and after_dot
+               operators.  rms says this is ok.  --karl  */
+            case '=':
+	      side = (rx_side_effect)rx_se_at_dot;
+	      goto add_side_effect;
+              break;
+
+            case 's':
+	    case 'S':
+	      {
+		rx_Bitset cs = rx_cset (&rxb->rx);
+		struct rexp_node * set = rx_mk_r_cset (&rxb->rx, cs);
+		if (!(cs && set))
+		  return REG_ESPACE;
+		if (c == 'S')
+		  rx_bitset_universe (rxb->rx.local_cset_size, cs);
+
+		PATFETCH (c);
+		{
+		  int x;
+		  enum syntaxcode code = syntax_spec_code [c];
+		  for (x = 0; x < 256; ++x)
+		    {
+		      
+		      if (SYNTAX (x) == code)
+			{
+			  rx_Bitset it =
+			    inverse_translation (rxb, validate_inv_tr,
+						 inverse_translate,
+						 translate, x);
+			  rx_bitset_xor (rxb->rx.local_cset_size, cs, it);
+			}
+		    }
+		}
+		append = set;
+		goto append_node;
+	      }
+              break;
+#endif /* emacs */
+
+
+            case 'w':
+            case 'W':
+	      {
+		rx_Bitset cs = rx_cset (&rxb->rx);
+		struct rexp_node * n = (cs ? rx_mk_r_cset (&rxb->rx, cs) : 0);
+		if (!(cs && n))
+		  return REG_ESPACE;
+		if (c == 'W')
+		  rx_bitset_universe (rxb->rx.local_cset_size ,cs);
+		{
+		  int x;
+		  for (x = rxb->rx.local_cset_size - 1; x > 0; --x)
+		    if (SYNTAX(x) & Sword)
+		      RX_bitset_toggle (cs, x);
+		}
+		append = n;
+		goto append_node;
+	      }
+              break;
+
+/* With a little extra work, some of these side effects could be optimized
+ * away (basicly by looking at what we already know about the surrounding
+ * chars).  
+ */
+            case '<':
+	      side = (rx_side_effect)re_se_wordbeg;
+	      goto add_side_effect;
+              break;
+
+            case '>':
+              side = (rx_side_effect)re_se_wordend;
+	      goto add_side_effect;
+              break;
+
+            case 'b':
+              side = (rx_side_effect)re_se_wordbound;
+	      goto add_side_effect;
+              break;
+
+            case 'B':
+              side = (rx_side_effect)re_se_notwordbound;
+	      goto add_side_effect;
+              break;
+
+            case '`':
+	      side = (rx_side_effect)re_se_begbuf;
+	      goto add_side_effect;
+	      break;
+	      
+            case '\'':
+	      side = (rx_side_effect)re_se_endbuf;
+	      goto add_side_effect;
+              break;
+
+	    add_side_effect:
+	      {
+		struct rexp_node * se
+		  = rx_mk_r_side_effect (&rxb->rx, side);
+		if (!se)
+		  return REG_ESPACE;
+		append = se;
+		goto append_node;
+	      }
+	      break;
+
+            case '1': case '2': case '3': case '4': case '5':
+            case '6': case '7': case '8': case '9':
+              if (syntax & RE_NO_BK_REFS)
+                goto normal_char;
+
+              c1 = c - '0';
+
+              if (c1 > regnum)
+                return REG_ESUBREG;
+
+              /* Can't back reference to a subexpression if inside of it.  */
+              if (group_in_compile_stack (compile_stack, c1))
+		return REG_ESUBREG;
+
+	      {
+		int backref_se = paramc;
+		params = (params
+			  ? ((struct re_se_params *)
+			     realloc (params,
+				      sizeof (*params) * (1 + paramc)))
+			  : ((struct re_se_params *)
+			     malloc (sizeof (*params))));
+		if (!params)
+		  return REG_ESPACE;
+		++paramc;
+		params[backref_se].se = re_se_backref;
+		params[backref_se].op1 = c1;
+		side = (rx_side_effect)backref_se;
+		goto add_side_effect;
+	      }
+              break;
+
+            case '+':
+            case '?':
+              if (syntax & RE_BK_PLUS_QM)
+                goto handle_plus;
+              else
+                goto normal_backslash;
+
+            default:
+            normal_backslash:
+              /* You might think it would be useful for \ to mean
+                 not to translate; but if we don't translate it
+                 it will never match anything.  */
+              c = TRANSLATE (c);
+              goto normal_char;
+            }
+          break;
+
+
+	default:
+        /* Expects the character in `c'.  */
+	normal_char:
+	    {
+	      rx_Bitset cs = rx_cset(&rxb->rx);
+	      struct rexp_node * match = rx_mk_r_cset (&rxb->rx, cs);
+	      rx_Bitset it;
+	      if (!(cs && match))
+		return REG_ESPACE;
+	      it = inverse_translation (rxb, validate_inv_tr,
+					inverse_translate, translate, c);
+	      rx_bitset_union (CHAR_SET_SIZE, cs, it);
+	      append = match;
+
+	    append_node:
+	      /* This genericly appends the rexp APPEND to *LAST_EXPRESSION
+	       * and then parses the next character normally.
+	       */
+	      if (*last_expression)
+		{
+		  struct rexp_node * concat
+		    = rx_mk_r_concat (&rxb->rx, *last_expression, append);
+		  if (!concat)
+		    return REG_ESPACE;
+		  *last_expression = concat;
+		  last_expression = &concat->params.pair.right;
+		}
+	      else
+		*last_expression = append;
+	    }
+	} /* switch (c) */
+    } /* while p != pend */
+
+  
+  {
+    int win_se = paramc;
+    params = (params
+	      ? ((struct re_se_params *)
+		 realloc (params,
+			  sizeof (*params) * (1 + paramc)))
+	      : ((struct re_se_params *)
+		 malloc (sizeof (*params))));
+    if (!params)
+      return REG_ESPACE;
+    ++paramc;
+    params[win_se].se = re_se_win;
+    {
+      struct rexp_node * se
+	= rx_mk_r_side_effect (&rxb->rx, (rx_side_effect)win_se);
+      struct rexp_node * concat
+	= rx_mk_r_concat (&rxb->rx, rexp, se);
+      if (!(se && concat))
+	return REG_ESPACE;
+      rexp = concat;
+    }
+  }
+
+
+  /* Through the pattern now.  */
+
+  if (!COMPILE_STACK_EMPTY) 
+    return REG_EPAREN;
+
+      free (compile_stack.stack);
+
+  orig_rexp = rexp;
+#ifdef RX_DEBUG
+  if (rx_debug_compile)
+    {
+      dbug_rxb = rxb;
+      fputs ("\n\nCompiling ", stdout);
+      fwrite (pattern, 1, size, stdout);
+      fputs (":\n", stdout);
+      rxb->se_params = params;
+      print_rexp (&rxb->rx, orig_rexp, 2, re_seprint, stdout);
+    }
+#endif
+  {
+    rx_Bitset cs = rx_cset(&rxb->rx);
+    rx_Bitset cs2 = rx_cset(&rxb->rx);
+#ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+    char * se_map = (char *) _alloca (paramc);
+#else
+    char * se_map = (char *) alloca (paramc);
+#endif
+    struct rexp_node * new_rexp = 0;
+
+
+    bzero (se_map, paramc);
+    find_backrefs (se_map, rexp, params);
+    fewer_side_effects =
+      remove_unecessary_side_effects (&rxb->rx, se_map,
+				      rx_copy_rexp (&rxb->rx, rexp), params);
+
+    speed_up_alt (&rxb->rx, rexp, 0);
+    speed_up_alt (&rxb->rx, fewer_side_effects, 1);
+
+    {
+      char * syntax_parens = rxb->syntax_parens;
+      if (syntax_parens == (char *)0x1)
+	rexp = remove_unecessary_side_effects
+	  (&rxb->rx, se_map, rexp, params);
+      else if (syntax_parens)
+	{
+	  int x;
+	  for (x = 0; x < paramc; ++x)
+	    if ((   (params[x].se == re_se_lparen)
+		 || (params[x].se == re_se_rparen))
+		&& (!syntax_parens [params[x].op1]))
+	      se_map [x] = 1;
+	  rexp = remove_unecessary_side_effects
+	    (&rxb->rx, se_map, rexp, params);
+	}
+    }
+
+    /* At least one more optimization would be nice to have here but i ran out 
+     * of time.  The idea would be to delay side effects.  
+     * For examle, `(abc)' is the same thing as `abc()' except that the
+     * left paren is offset by 3 (which we know at compile time).
+     * (In this comment, write that second pattern `abc(:3:)' 
+     * where `(:3:' is a syntactic unit.)
+     *
+     * Trickier:  `(abc|defg)'  is the same as `(abc(:3:|defg(:4:))'
+     * (The paren nesting may be hard to follow -- that's an alternation
+     *	of `abc(:3:' and `defg(:4:' inside (purely syntactic) parens
+     *  followed by the closing paren from the original expression.)
+     *
+     * Neither the expression tree representation nor the the nfa make
+     * this very easy to write. :(
+     */
+
+  /* What we compile is different than what the parser returns.
+   * Suppose the parser returns expression R.
+   * Let R' be R with unnecessary register assignments removed 
+   * (see REMOVE_UNECESSARY_SIDE_EFFECTS, above).
+   *
+   * What we will compile is the expression:
+   *
+   *    m{try}R{win}\|s{try}R'{win}
+   *
+   * {try} and {win} denote side effect epsilons (see EXPLORE_FUTURE).
+   * 
+   * When trying a match, we insert an `m' at the beginning of the 
+   * string if the user wants registers to be filled, `s' if not.
+   */
+    new_rexp =
+      rx_mk_r_alternate
+	(&rxb->rx,
+	 rx_mk_r_concat (&rxb->rx, rx_mk_r_cset (&rxb->rx, cs2), rexp),
+	 rx_mk_r_concat (&rxb->rx,
+			 rx_mk_r_cset (&rxb->rx, cs), fewer_side_effects));
+
+    if (!(new_rexp && cs && cs2))
+      return REG_ESPACE;
+    RX_bitset_enjoin (cs2, '\0'); /* prefixed to the rexp used for matching. */
+    RX_bitset_enjoin (cs, '\1'); /* prefixed to the rexp used for searching. */
+    rexp = new_rexp;
+  }
+
+#ifdef RX_DEBUG
+  if (rx_debug_compile)
+    {
+      fputs ("\n...which is compiled as:\n", stdout);
+      print_rexp (&rxb->rx, rexp, 2, re_seprint, stdout);
+    }
+#endif
+  {
+    struct rx_nfa_state *start = 0;
+    struct rx_nfa_state *end = 0;
+
+    if (!rx_build_nfa (&rxb->rx, rexp, &start, &end))
+      return REG_ESPACE;	/*  */
+    else
+      {
+	void * mem = (void *)rxb->buffer;
+	unsigned long size = rxb->allocated;
+	int start_id;
+	char * perm_mem;
+	int iterator_size = paramc * sizeof (params[0]);
+
+	end->is_final = 1;
+	start->is_start = 1;
+	rx_name_nfa_states (&rxb->rx);
+	start_id = start->id;
+#ifdef RX_DEBUG
+	if (rx_debug_compile)
+	  {
+	    fputs ("...giving the NFA: \n", stdout);
+	    dbug_rxb = rxb;
+	    print_nfa (&rxb->rx, rxb->rx.nfa_states, re_seprint, stdout);
+	  }
+#endif
+	if (!rx_eclose_nfa (&rxb->rx))
+	  return REG_ESPACE;
+	else
+	  {
+	    rx_delete_epsilon_transitions (&rxb->rx);
+	    
+	    /* For compatability reasons, we need to shove the
+	     * compiled nfa into one chunk of malloced memory.
+	     */
+	    rxb->rx.reserved = (   sizeof (params[0]) * paramc
+				+  rx_sizeof_bitset (rxb->rx.local_cset_size));
+#ifdef RX_DEBUG
+	    if (rx_debug_compile)
+	      {
+		dbug_rxb = rxb;
+		fputs ("...which cooks down (uncompactified) to: \n", stdout);
+		print_nfa (&rxb->rx, rxb->rx.nfa_states, re_seprint, stdout);
+	      }
+#endif
+	    if (!rx_compactify_nfa (&rxb->rx, &mem, &size))
+	      return REG_ESPACE;
+	    rxb->buffer = mem;
+	    rxb->allocated = size;
+	    rxb->rx.buffer = mem;
+	    rxb->rx.allocated = size;
+	    perm_mem = ((char *)rxb->rx.buffer
+			+ rxb->rx.allocated - rxb->rx.reserved);
+	    rxb->se_params = ((struct re_se_params *)perm_mem);
+	    bcopy (params, rxb->se_params, iterator_size);
+	    perm_mem += iterator_size;
+	    rxb->fastset = (rx_Bitset) perm_mem;
+	    rxb->start = rx_id_to_nfa_state (&rxb->rx, start_id);
+	  }
+	rx_bitset_null (rxb->rx.local_cset_size, rxb->fastset);
+	rxb->can_match_empty = compute_fastset (rxb, orig_rexp);
+	rxb->match_regs_on_stack =
+	  registers_on_stack (rxb, orig_rexp, 0, params); 
+	rxb->search_regs_on_stack =
+	  registers_on_stack (rxb, fewer_side_effects, 0, params);
+	if (rxb->can_match_empty)
+	  rx_bitset_universe (rxb->rx.local_cset_size, rxb->fastset);
+	rxb->is_anchored = is_anchored (orig_rexp, (rx_side_effect) re_se_hat);
+	rxb->begbuf_only = is_anchored (orig_rexp,
+					(rx_side_effect) re_se_begbuf);
+      }
+    rx_free_rexp (&rxb->rx, rexp);
+    if (params)
+      free (params);
+#ifdef RX_DEBUG
+    if (rx_debug_compile)
+      {
+	dbug_rxb = rxb;
+	fputs ("...which cooks down to: \n", stdout);
+	print_nfa (&rxb->rx, rxb->rx.nfa_states, re_seprint, stdout);
+      }
+#endif
+  }
+  return REG_NOERROR;
+}
+
+
+
+
+/* This table gives an error message for each of the error codes listed
+   in regex.h.  Obviously the order here has to be same as there.  */
+
+__const__ char * rx_error_msg[] =
+{ 0,						/* REG_NOERROR */
+    "No match",					/* REG_NOMATCH */
+    "Invalid regular expression",		/* REG_BADPAT */
+    "Invalid collation character",		/* REG_ECOLLATE */
+    "Invalid character class name",		/* REG_ECTYPE */
+    "Trailing backslash",			/* REG_EESCAPE */
+    "Invalid back reference",			/* REG_ESUBREG */
+    "Unmatched [ or [^",			/* REG_EBRACK */
+    "Unmatched ( or \\(",			/* REG_EPAREN */
+    "Unmatched \\{",				/* REG_EBRACE */
+    "Invalid content of \\{\\}",		/* REG_BADBR */
+    "Invalid range end",			/* REG_ERANGE */
+    "Memory exhausted",				/* REG_ESPACE */
+    "Invalid preceding regular expression",	/* REG_BADRPT */
+    "Premature end of regular expression",	/* REG_EEND */
+    "Regular expression too big",		/* REG_ESIZE */
+    "Unmatched ) or \\)",			/* REG_ERPAREN */
+};
+
+
+
+
+
+char rx_slowmap [256] =
+{
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+};
+
+#ifdef __STDC__
+RX_DECL void
+rx_blow_up_fastmap (struct re_pattern_buffer * rxb)
+#else
+RX_DECL void
+rx_blow_up_fastmap (rxb)
+     struct re_pattern_buffer * rxb;
+#endif
+{
+  int x;
+  for (x = 0; x < 256; ++x)	/* &&&& 3.6 % */
+    rxb->fastmap [x] = !!RX_bitset_member (rxb->fastset, x);
+  rxb->fastmap_accurate = 1;
+}
+
+
+
+
+
+#if !defined(REGEX_MALLOC) && !defined(__GNUC__)
+#define RE_SEARCH_2_FN	inner_re_search_2
+#define RE_S2_QUAL static
+#else
+#define RE_SEARCH_2_FN	re_search_2
+#define RE_S2_QUAL 
+#endif
+
+struct re_search_2_closure
+{
+  __const__ char * string1;
+  int size1;
+  __const__ char * string2;
+  int size2;
+};
+
+
+static __inline__ enum rx_get_burst_return
+re_search_2_get_burst (pos, vclosure, stop)
+     struct rx_string_position * pos;
+     void * vclosure;
+     int stop;
+{
+  struct re_search_2_closure * closure;
+  closure = (struct re_search_2_closure *)vclosure;
+  if (!closure->string2)
+    {
+      int inset;
+
+      inset = pos->pos - pos->string;
+      if ((inset < -1) || (inset > closure->size1))
+	return rx_get_burst_no_more;
+      else
+	{
+	  pos->pos = (__const__ unsigned char *) closure->string1 + inset;
+	  pos->string = (__const__ unsigned char *) closure->string1;
+	  pos->size = closure->size1;
+	  pos->end = ((__const__ unsigned char *)
+		      MIN(closure->string1 + closure->size1,
+			  closure->string1 + stop));
+	  pos->offset = 0;
+	  return ((pos->pos < pos->end)
+		  ? rx_get_burst_ok
+		  :  rx_get_burst_no_more);
+	}
+    }
+  else if (!closure->string1)
+    {
+      int inset;
+
+      inset = pos->pos - pos->string;
+      pos->pos = (__const__ unsigned char *) closure->string2 + inset;
+      pos->string = (__const__ unsigned char *) closure->string2;
+      pos->size = closure->size2;
+      pos->end = ((__const__ unsigned char *)
+		  MIN(closure->string2 + closure->size2,
+		      closure->string2 + stop));
+      pos->offset = 0;
+      return ((pos->pos < pos->end)
+	      ? rx_get_burst_ok
+	      :  rx_get_burst_no_more);
+    }
+  else
+    {
+      int inset;
+
+      inset = pos->pos - pos->string + pos->offset;
+      if (inset < closure->size1)
+	{
+	  pos->pos = (__const__ unsigned char *) closure->string1 + inset;
+	  pos->string = (__const__ unsigned char *) closure->string1;
+	  pos->size = closure->size1;
+	  pos->end = ((__const__ unsigned char *)
+		      MIN(closure->string1 + closure->size1,
+			  closure->string1 + stop));
+	  pos->offset = 0;
+	  return rx_get_burst_ok;
+	}
+      else
+	{
+	  pos->pos = ((__const__ unsigned char *)
+		      closure->string2 + inset - closure->size1);
+	  pos->string = (__const__ unsigned char *) closure->string2;
+	  pos->size = closure->size2;
+	  pos->end = ((__const__ unsigned char *)
+		      MIN(closure->string2 + closure->size2,
+			  closure->string2 + stop - closure->size1));
+	  pos->offset = closure->size1;
+	  return ((pos->pos < pos->end)
+		  ? rx_get_burst_ok
+		  :  rx_get_burst_no_more);
+	}
+    }
+}
+
+
+static __inline__ enum rx_back_check_return
+re_search_2_back_check (pos, lparen, rparen, translate, vclosure, stop)
+     struct rx_string_position * pos;
+     int lparen;
+     int rparen;
+     unsigned char * translate;
+     void * vclosure;
+     int stop;
+{
+  struct rx_string_position there;
+  struct rx_string_position past;
+
+  there = *pos;
+  there.pos = there.string + lparen - there.offset;
+  re_search_2_get_burst (&there, vclosure, stop);
+
+  past = *pos;
+  past.pos = past.string + rparen - there.offset;
+  re_search_2_get_burst (&past, vclosure, stop);
+
+  ++pos->pos;
+  re_search_2_get_burst (pos, vclosure, stop);
+
+  while (   (there.pos != past.pos)
+	 && (pos->pos != pos->end))
+    if (TRANSLATE(*there.pos) != TRANSLATE(*pos->pos))
+      return rx_back_check_fail;
+    else
+      {
+	++there.pos;
+	++pos->pos;
+	if (there.pos == there.end)
+	  re_search_2_get_burst (&there, vclosure, stop);
+	if (pos->pos == pos->end)
+	  re_search_2_get_burst (pos, vclosure, stop);
+      }
+
+  if (there.pos != past.pos)
+    return rx_back_check_fail;
+  --pos->pos;
+  re_search_2_get_burst (pos, vclosure, stop);
+  return rx_back_check_pass;
+}
+
+static __inline__ int
+re_search_2_fetch_char (pos, offset, app_closure, stop)
+     struct rx_string_position * pos;
+     int offset;
+     void * app_closure;
+     int stop;
+{
+  struct re_search_2_closure * closure;
+  closure = (struct re_search_2_closure *)app_closure;
+  if (offset == 0)
+    {
+      if (pos->pos >= pos->string)
+	return *pos->pos;
+      else
+	{
+	  if (   (pos->string == (__const__ unsigned char *) closure->string2)
+	      && (closure->string1)
+	      && (closure->size1))
+	    return closure->string1[closure->size1 - 1];
+	  else
+	    return 0;		/* sure, why not. */
+	}
+    }
+  if (pos->pos == pos->end)
+    return *closure->string2;
+  else
+    return pos->pos[1];
+}
+     
+
+#ifdef __STDC__
+RE_S2_QUAL int
+RE_SEARCH_2_FN (struct re_pattern_buffer *rxb,
+		__const__ char * string1, int size1,
+		__const__ char * string2, int size2,
+		int startpos, int range,
+		struct re_registers *regs,
+		int stop)
+#else
+RE_S2_QUAL int
+RE_SEARCH_2_FN (rxb,
+		string1, size1, string2, size2, startpos, range, regs, stop)
+     struct re_pattern_buffer *rxb;
+     __const__ char * string1;
+     int size1;
+     __const__ char * string2;
+     int size2;
+     int startpos;
+     int range;
+     struct re_registers *regs;
+     int stop;
+#endif
+{
+  int answer;
+  struct re_search_2_closure closure;
+  closure.string1 = string1;
+  closure.size1 = size1;
+  closure.string2 = string2;
+  closure.size2 = size2;
+  answer = rx_search (rxb, startpos, range, stop, size1 + size2,
+		      re_search_2_get_burst,
+		      re_search_2_back_check,
+		      re_search_2_fetch_char,
+		      (void *)&closure,
+		      regs,
+		      0,
+		      0);
+  switch (answer)
+    {
+    case rx_search_continuation:
+      abort ();
+    case rx_search_error:
+      return -2;
+    case rx_search_soft_fail:
+    case rx_search_fail:
+      return -1;
+    default:
+      return answer;
+    }
+}
+
+/* Export rx_search to callers outside this file.  */
+
+int
+re_rx_search (rxb, startpos, range, stop, total_size,
+	      get_burst, back_check, fetch_char,
+	      app_closure, regs, resume_state, save_state)
+     struct re_pattern_buffer * rxb;
+     int startpos;
+     int range;
+     int stop;
+     int total_size;
+     rx_get_burst_fn get_burst;
+     rx_back_check_fn back_check;
+     rx_fetch_char_fn fetch_char;
+     void * app_closure;
+     struct re_registers * regs;
+     struct rx_search_state * resume_state;
+     struct rx_search_state * save_state;
+{
+  return rx_search (rxb, startpos, range, stop, total_size,
+		    get_burst, back_check, fetch_char, app_closure,
+		    regs, resume_state, save_state);
+}
+
+#if !defined(REGEX_MALLOC) && !defined(__GNUC__)
+#ifdef __STDC__
+int
+re_search_2 (struct re_pattern_buffer *rxb,
+	     __const__ char * string1, int size1,
+	     __const__ char * string2, int size2,
+	     int startpos, int range,
+	     struct re_registers *regs,
+	     int stop)
+#else
+int
+re_search_2 (rxb, string1, size1, string2, size2, startpos, range, regs, stop)
+     struct re_pattern_buffer *rxb;
+     __const__ char * string1;
+     int size1;
+     __const__ char * string2;
+     int size2;
+     int startpos;
+     int range;
+     struct re_registers *regs;
+     int stop;
+#endif
+{
+  int ret;
+  ret = inner_re_search_2 (rxb, string1, size1, string2, size2, startpos,
+			   range, regs, stop);
+#ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+  _alloca (0);
+#else
+  alloca (0);
+#endif
+  return ret;
+}
+#endif
+
+
+/* Like re_search_2, above, but only one string is specified, and
+ * doesn't let you say where to stop matching.
+ */
+
+#ifdef __STDC__
+int
+re_search (struct re_pattern_buffer * rxb, __const__ char *string,
+	   int size, int startpos, int range,
+	   struct re_registers *regs)
+#else
+int
+re_search (rxb, string, size, startpos, range, regs)
+     struct re_pattern_buffer * rxb;
+     __const__ char * string;
+     int size;
+     int startpos;
+     int range;
+     struct re_registers *regs;
+#endif
+{
+  return re_search_2 (rxb, 0, 0, string, size, startpos, range, regs, size);
+}
+
+#ifdef __STDC__
+int
+re_match_2 (struct re_pattern_buffer * rxb,
+	    __const__ char * string1, int size1,
+	    __const__ char * string2, int size2,
+	    int pos, struct re_registers *regs, int stop)
+#else
+int
+re_match_2 (rxb, string1, size1, string2, size2, pos, regs, stop)
+     struct re_pattern_buffer * rxb;
+     __const__ char * string1;
+     int size1;
+     __const__ char * string2;
+     int size2;
+     int pos;
+     struct re_registers *regs;
+     int stop;
+#endif
+{
+  struct re_registers some_regs;
+  regoff_t start;
+  regoff_t end;
+  int srch;
+  int save = rxb->regs_allocated;
+  struct re_registers * regs_to_pass = regs;
+
+  if (!regs)
+    {
+      some_regs.start = &start;
+      some_regs.end = &end;
+      some_regs.num_regs = 1;
+      regs_to_pass = &some_regs;
+      rxb->regs_allocated = REGS_FIXED;
+    }
+
+  srch = re_search_2 (rxb, string1, size1, string2, size2,
+		      pos, 1, regs_to_pass, stop);
+  if (regs_to_pass != regs)
+    rxb->regs_allocated = save;
+  if (srch < 0)
+    return srch;
+  return regs_to_pass->end[0] - regs_to_pass->start[0];
+}
+
+/* re_match is like re_match_2 except it takes only a single string.  */
+
+#ifdef __STDC__
+int
+re_match (struct re_pattern_buffer * rxb,
+	  __const__ char * string,
+	  int size, int pos,
+	  struct re_registers *regs)
+#else
+int
+re_match (rxb, string, size, pos, regs)
+     struct re_pattern_buffer * rxb;
+     __const__ char *string;
+     int size;
+     int pos;
+     struct re_registers *regs;
+#endif
+{
+  return re_match_2 (rxb, string, size, 0, 0, pos, regs, size);
+}
+
+
+
+
+/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
+   also be assigned to arbitrarily: each pattern buffer stores its own
+   syntax, so it can be changed between regex compilations.  */
+reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS;
+
+
+/* Specify the precise syntax of regexps for compilation.  This provides
+   for compatibility for various utilities which historically have
+   different, incompatible syntaxes.
+
+   The argument SYNTAX is a bit mask comprised of the various bits
+   defined in regex.h.  We return the old syntax.  */
+
+#ifdef __STDC__
+reg_syntax_t
+re_set_syntax (reg_syntax_t syntax)
+#else
+reg_syntax_t
+re_set_syntax (syntax)
+    reg_syntax_t syntax;
+#endif
+{
+  reg_syntax_t ret = re_syntax_options;
+
+  re_syntax_options = syntax;
+  return ret;
+}
+
+
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
+   this memory for recording register information.  STARTS and ENDS
+   must be allocated using the malloc library routine, and must each
+   be at least NUM_REGS * sizeof (regoff_t) bytes long.
+
+   If NUM_REGS == 0, then subsequent matches should allocate their own
+   register data.
+
+   Unless this function is called, the first search or match using
+   PATTERN_BUFFER will allocate its own register data, without
+   freeing the old data.  */
+
+#ifdef __STDC__
+void
+re_set_registers (struct re_pattern_buffer *bufp,
+		  struct re_registers *regs,
+		  unsigned num_regs,
+		  regoff_t * starts, regoff_t * ends)
+#else
+void
+re_set_registers (bufp, regs, num_regs, starts, ends)
+     struct re_pattern_buffer *bufp;
+     struct re_registers *regs;
+     unsigned num_regs;
+     regoff_t * starts;
+     regoff_t * ends;
+#endif
+{
+  if (num_regs)
+    {
+      bufp->regs_allocated = REGS_REALLOCATE;
+      regs->num_regs = num_regs;
+      regs->start = starts;
+      regs->end = ends;
+    }
+  else
+    {
+      bufp->regs_allocated = REGS_UNALLOCATED;
+      regs->num_regs = 0;
+      regs->start = regs->end = (regoff_t) 0;
+    }
+}
+
+
+
+
+
+#ifdef __STDC__
+static int 
+cplx_se_sublist_len (struct rx_se_list * list)
+#else
+static int 
+cplx_se_sublist_len (list)
+     struct rx_se_list * list;
+#endif
+{
+  int x = 0;
+  while (list)
+    {
+      if ((long)list->car >= 0)
+	++x;
+      list = list->cdr;
+    }
+  return x;
+}
+
+
+/* For rx->se_list_cmp */
+
+#ifdef __STDC__
+static int 
+posix_se_list_order (struct rx * rx,
+		     struct rx_se_list * a, struct rx_se_list * b)
+#else
+static int 
+posix_se_list_order (rx, a, b)
+     struct rx * rx;
+     struct rx_se_list * a;
+     struct rx_se_list * b;
+#endif
+{
+  int al = cplx_se_sublist_len (a);
+  int bl = cplx_se_sublist_len (b);
+
+  if (!al && !bl)
+    return ((a == b)
+	    ? 0
+	    : ((a < b) ? -1 : 1));
+  
+  else if (!al)
+    return -1;
+
+  else if (!bl)
+    return 1;
+
+  else
+    {
+#ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+      rx_side_effect * av = ((rx_side_effect *)
+			     _alloca (sizeof (rx_side_effect) * (al + 1)));
+      rx_side_effect * bv = ((rx_side_effect *)
+			     _alloca (sizeof (rx_side_effect) * (bl + 1)));
+#else
+      rx_side_effect * av = ((rx_side_effect *)
+			     alloca (sizeof (rx_side_effect) * (al + 1)));
+      rx_side_effect * bv = ((rx_side_effect *)
+			     alloca (sizeof (rx_side_effect) * (bl + 1)));
+#endif
+      struct rx_se_list * ap = a;
+      struct rx_se_list * bp = b;
+      int ai, bi;
+      
+      for (ai = al - 1; ai >= 0; --ai)
+	{
+	  while ((long)ap->car < 0)
+	    ap = ap->cdr;
+	  av[ai] = ap->car;
+	  ap = ap->cdr;
+	}
+      av[al] = (rx_side_effect)-2;
+      for (bi = bl - 1; bi >= 0; --bi)
+	{
+	  while ((long)bp->car < 0)
+	    bp = bp->cdr;
+	  bv[bi] = bp->car;
+	  bp = bp->cdr;
+	}
+      bv[bl] = (rx_side_effect)-1;
+
+      {
+	int ret;
+	int x = 0;
+	while (av[x] == bv[x])
+	  ++x;
+ 	ret = (((unsigned *)(av[x]) < (unsigned *)(bv[x])) ? -1 : 1);
+	return ret;
+      }
+    }
+}
+
+
+
+
+
+/* re_compile_pattern is the GNU regular expression compiler: it
+   compiles PATTERN (of length SIZE) and puts the result in RXB.
+   Returns 0 if the pattern was valid, otherwise an error string.
+
+   Assumes the `allocated' (and perhaps `buffer') and `translate' fields
+   are set in RXB on entry.
+
+   We call rx_compile to do the actual compilation.  */
+
+#ifdef __STDC__
+__const__ char *
+re_compile_pattern (__const__ char *pattern,
+		    int length,
+		    struct re_pattern_buffer * rxb)
+#else
+__const__ char *
+re_compile_pattern (pattern, length, rxb)
+     __const__ char *pattern;
+     int length;
+     struct re_pattern_buffer * rxb;
+#endif
+{
+  reg_errcode_t ret;
+
+  /* GNU code is written to assume at least RE_NREGS registers will be set
+     (and at least one extra will be -1).  */
+  rxb->regs_allocated = REGS_UNALLOCATED;
+
+  /* And GNU code determines whether or not to get register information
+     by passing null for the REGS argument to re_match, etc., not by
+     setting no_sub.  */
+  rxb->no_sub = 0;
+
+  rxb->rx.local_cset_size = 256;
+
+  /* Match anchors at newline.  */
+  rxb->newline_anchor = 1;
+ 
+  rxb->re_nsub = 0;
+  rxb->start = 0;
+  rxb->se_params = 0;
+  rxb->rx.nodec = 0;
+  rxb->rx.epsnodec = 0;
+  rxb->rx.instruction_table = 0;
+  rxb->rx.nfa_states = 0;
+  rxb->rx.se_list_cmp = posix_se_list_order;
+  rxb->rx.start_set = 0;
+
+  ret = rx_compile (pattern, length, re_syntax_options, rxb);
+#ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+  _alloca (0);
+#else
+  alloca (0);
+#endif
+  return rx_error_msg[(int) ret];
+}
+
+
+
+#ifdef __STDC__
+int
+re_compile_fastmap (struct re_pattern_buffer * rxb)
+#else
+int
+re_compile_fastmap (rxb)
+     struct re_pattern_buffer * rxb;
+#endif
+{
+  rx_blow_up_fastmap (rxb);
+  return 0;
+}
+
+
+
+
+
+/* Entry points compatible with 4.2 BSD regex library.  We don't define
+   them if this is an Emacs or POSIX compilation.  */
+
+#if (!defined (emacs) && !defined (_POSIX_SOURCE)) || defined(USE_BSD_REGEX)
+
+/* BSD has one and only one pattern buffer.  */
+static struct re_pattern_buffer rx_comp_buf;
+
+#ifdef __STDC__
+char *
+re_comp (__const__ char *s)
+#else
+char *
+re_comp (s)
+    __const__ char *s;
+#endif
+{
+  reg_errcode_t ret;
+
+  if (!s || (*s == '\0'))
+    {
+      if (!rx_comp_buf.buffer)
+	return "No previous regular expression";
+      return 0;
+    }
+
+  if (!rx_comp_buf.fastmap)
+    {
+      rx_comp_buf.fastmap = (char *) malloc (1 << CHARBITS);
+      if (!rx_comp_buf.fastmap)
+	return "Memory exhausted";
+    }
+
+  /* Since `rx_exec' always passes NULL for the `regs' argument, we
+     don't need to initialize the pattern buffer fields which affect it.  */
+
+  /* Match anchors at newlines.  */
+  rx_comp_buf.newline_anchor = 1;
+
+  rx_comp_buf.re_nsub = 0;
+  rx_comp_buf.start = 0;
+  rx_comp_buf.se_params = 0;
+  rx_comp_buf.rx.nodec = 0;
+  rx_comp_buf.rx.epsnodec = 0;
+  rx_comp_buf.rx.instruction_table = 0;
+  rx_comp_buf.rx.nfa_states = 0;
+  rx_comp_buf.rx.start = 0;
+  rx_comp_buf.rx.se_list_cmp = posix_se_list_order;
+  rx_comp_buf.rx.local_cset_size = 256;
+
+  ret = rx_compile (s, strlen (s), re_syntax_options, &rx_comp_buf);
+#ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+  _alloca (0);
+#else
+  alloca (0);
+#endif
+
+  /* Yes, we're discarding `__const__' here.  */
+  return (char *) rx_error_msg[(int) ret];
+}
+
+
+#ifdef __STDC__
+int
+re_exec (__const__ char *s)
+#else
+int
+re_exec (s)
+    __const__ char *s;
+#endif
+{
+  __const__ int len = strlen (s);
+  return
+    0 <= re_search (&rx_comp_buf, s, len, 0, len, (struct re_registers *) 0);
+}
+#endif /* not emacs and not _POSIX_SOURCE */
+
+
+
+
+/* POSIX.2 functions.  Don't define these for Emacs.  */
+
+#if !defined(emacs)
+
+/* regcomp takes a regular expression as a string and compiles it.
+
+   PREG is a regex_t *.  We do not expect any fields to be initialized,
+   since POSIX says we shouldn't.  Thus, we set
+
+     `buffer' to the compiled pattern;
+     `used' to the length of the compiled pattern;
+     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
+       REG_EXTENDED bit in CFLAGS is set; otherwise, to
+       RE_SYNTAX_POSIX_BASIC;
+     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
+     `fastmap' and `fastmap_accurate' to zero;
+     `re_nsub' to the number of subexpressions in PATTERN.
+
+   PATTERN is the address of the pattern string.
+
+   CFLAGS is a series of bits which affect compilation.
+
+     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
+     use POSIX basic syntax.
+
+     If REG_NEWLINE is set, then . and [^...] don't match newline.
+     Also, regexec will try a match beginning after every newline.
+
+     If REG_ICASE is set, then we considers upper- and lowercase
+     versions of letters to be equivalent when matching.
+
+     If REG_NOSUB is set, then when PREG is passed to regexec, that
+     routine will report only success or failure, and nothing about the
+     registers.
+
+   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
+   the return codes and their meanings.)  */
+
+
+#ifdef __STDC__
+int
+regcomp (regex_t * preg, __const__ char * pattern, int cflags)
+#else
+int
+regcomp (preg, pattern, cflags)
+    regex_t * preg;
+    __const__ char * pattern;
+    int cflags;
+#endif
+{
+  reg_errcode_t ret;
+  unsigned syntax
+    = cflags & REG_EXTENDED ? RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
+
+  /* regex_compile will allocate the space for the compiled pattern.  */
+  preg->buffer = 0;
+  preg->allocated = 0;
+  preg->fastmap = malloc (256);
+  if (!preg->fastmap)
+    return REG_ESPACE;
+  preg->fastmap_accurate = 0;
+
+  if (cflags & REG_ICASE)
+    {
+      unsigned i;
+
+      preg->translate = (unsigned char *) malloc (256);
+      if (!preg->translate)
+        return (int) REG_ESPACE;
+
+      /* Map uppercase characters to corresponding lowercase ones.  */
+      for (i = 0; i < CHAR_SET_SIZE; i++)
+        preg->translate[i] = isupper (i) ? tolower (i) : i;
+    }
+  else
+    preg->translate = 0;
+
+  /* If REG_NEWLINE is set, newlines are treated differently.  */
+  if (cflags & REG_NEWLINE)
+    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
+      syntax &= ~RE_DOT_NEWLINE;
+      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+      /* It also changes the matching behavior.  */
+      preg->newline_anchor = 1;
+    }
+  else
+    preg->newline_anchor = 0;
+
+  preg->no_sub = !!(cflags & REG_NOSUB);
+
+  /* POSIX says a null character in the pattern terminates it, so we
+     can use strlen here in compiling the pattern.  */
+  preg->re_nsub = 0;
+  preg->start = 0;
+  preg->se_params = 0;
+  preg->syntax_parens = 0;
+  preg->rx.nodec = 0;
+  preg->rx.epsnodec = 0;
+  preg->rx.instruction_table = 0;
+  preg->rx.nfa_states = 0;
+  preg->rx.local_cset_size = 256;
+  preg->rx.start = 0;
+  preg->rx.se_list_cmp = posix_se_list_order;
+  preg->rx.start_set = 0;
+  ret = rx_compile (pattern, strlen (pattern), syntax, preg);
+
+#ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+  _alloca (0);
+#else
+  alloca (0);
+#endif
+
+  /* POSIX doesn't distinguish between an unmatched open-group and an
+     unmatched close-group: both are REG_EPAREN.  */
+  if (ret == REG_ERPAREN) ret = REG_EPAREN;
+
+  return (int) ret;
+}
+
+
+/* regexec searches for a given pattern, specified by PREG, in the
+   string STRING.
+
+   If NMATCH is zero or REG_NOSUB was set in the cflags argument to
+   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at
+   least NMATCH elements, and we set them to the offsets of the
+   corresponding matched substrings.
+
+   EFLAGS specifies `execution flags' which affect matching: if
+   REG_NOTBOL is set, then ^ does not match at the beginning of the
+   string; if REG_NOTEOL is set, then $ does not match at the end.
+
+   We return 0 if we find a match and REG_NOMATCH if not.  */
+
+#ifdef __STDC__
+int
+regexec (__const__ regex_t *preg, __const__ char *string,
+	 size_t nmatch, regmatch_t pmatch[],
+	 int eflags)
+#else
+int
+regexec (preg, string, nmatch, pmatch, eflags)
+    __const__ regex_t *preg;
+    __const__ char *string;
+    size_t nmatch;
+    regmatch_t pmatch[];
+    int eflags;
+#endif
+{
+  int ret;
+  struct re_registers regs;
+  regex_t private_preg;
+  int len = strlen (string);
+  boolean want_reg_info = !preg->no_sub && nmatch > 0;
+
+  private_preg = *preg;
+
+  private_preg.not_bol = !!(eflags & REG_NOTBOL);
+  private_preg.not_eol = !!(eflags & REG_NOTEOL);
+
+  /* The user has told us exactly how many registers to return
+   * information about, via `nmatch'.  We have to pass that on to the
+   * matching routines.
+   */
+  private_preg.regs_allocated = REGS_FIXED;
+
+  if (want_reg_info)
+    {
+      regs.num_regs = nmatch;
+      regs.start =  (( regoff_t *) malloc ((nmatch) * sizeof ( regoff_t)));
+      regs.end =  (( regoff_t *) malloc ((nmatch) * sizeof ( regoff_t)));
+      if (regs.start == 0 || regs.end == 0)
+        return (int) REG_NOMATCH;
+    }
+
+  /* Perform the searching operation.  */
+  ret = re_search (&private_preg,
+		   string, len,
+                   /* start: */ 0,
+		   /* range: */ len,
+                   want_reg_info ? &regs : (struct re_registers *) 0);
+
+  /* Copy the register information to the POSIX structure.  */
+  if (want_reg_info)
+    {
+      if (ret >= 0)
+        {
+          unsigned r;
+
+          for (r = 0; r < nmatch; r++)
+            {
+              pmatch[r].rm_so = regs.start[r];
+              pmatch[r].rm_eo = regs.end[r];
+            }
+        }
+
+      /* If we needed the temporary register info, free the space now.  */
+      free (regs.start);
+      free (regs.end);
+    }
+
+  /* We want zero return to mean success, unlike `re_search'.  */
+  return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
+}
+
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+   from either regcomp or regexec.   */
+
+#ifdef __STDC__
+size_t
+regerror (int rx_errcode, __const__ regex_t *preg,
+	  char *errbuf, size_t errbuf_size)
+#else
+size_t
+regerror (rx_errcode, preg, errbuf, errbuf_size)
+    int rx_errcode;
+    __const__ regex_t *preg;
+    char *errbuf;
+    size_t errbuf_size;
+#endif
+{
+  __const__ char *msg
+    = rx_error_msg[rx_errcode] == 0 ? "Success" : rx_error_msg[rx_errcode];
+  size_t msg_size = strlen (msg) + 1; /* Includes the 0.  */
+
+  if (errbuf_size != 0)
+    {
+      if (msg_size > errbuf_size)
+        {
+          strncpy (errbuf, msg, errbuf_size - 1);
+          errbuf[errbuf_size - 1] = 0;
+        }
+      else
+        strcpy (errbuf, msg);
+    }
+
+  return msg_size;
+}
+
+
+/* Free dynamically allocated space used by PREG.  */
+
+#ifdef __STDC__
+void
+regfree (regex_t *preg)
+#else
+void
+regfree (preg)
+    regex_t *preg;
+#endif
+{
+  if (preg->buffer != 0)
+    free (preg->buffer);
+  preg->buffer = 0;
+  preg->allocated = 0;
+
+  if (preg->fastmap != 0)
+    free (preg->fastmap);
+  preg->fastmap = 0;
+  preg->fastmap_accurate = 0;
+
+  if (preg->translate != 0)
+    free (preg->translate);
+  preg->translate = 0;
+}
+
+#endif /* not emacs  */
+
+
+
+
+
Index: /indexers/branches/3.03a/mg/lib/rx.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/rx.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/rx.h	(revision 14757)
@@ -0,0 +1,3755 @@
+#if !defined(RXH) || defined(RX_WANT_SE_DEFS)
+#define RXH
+
+/*	Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of the librx library.
+
+Librx is free software; you can redistribute it and/or modify it under
+the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+Librx 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 Library General Public
+License along with this software; see the file COPYING.LIB.  If not,
+write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA
+02139, USA.  */
+/*  t. lord	Wed Sep 23 18:20:57 1992	*/
+
+
+
+
+
+
+
+
+
+#ifndef RX_WANT_SE_DEFS
+
+/* This page: Bitsets */
+
+#ifndef RX_subset
+typedef unsigned int RX_subset;
+#define RX_subset_bits	(32)
+#define RX_subset_mask	(RX_subset_bits - 1)
+#endif
+
+typedef RX_subset * rx_Bitset;
+
+#ifdef __STDC__
+typedef void (*rx_bitset_iterator) (void *, int member_index);
+#else
+typedef void (*rx_bitset_iterator) ();
+#endif
+
+#define rx_bitset_subset(N)  ((N) / RX_subset_bits)
+#define rx_bitset_subset_val(B,N)  ((B)[rx_bitset_subset(N)])
+#define RX_bitset_access(B,N,OP) \
+  ((B)[rx_bitset_subset(N)] OP rx_subset_singletons[(N) & RX_subset_mask])
+#define RX_bitset_member(B,N)   RX_bitset_access(B, N, &)
+#define RX_bitset_enjoin(B,N)   RX_bitset_access(B, N, |=)
+#define RX_bitset_remove(B,N)   RX_bitset_access(B, N, &= ~)
+#define RX_bitset_toggle(B,N)   RX_bitset_access(B, N, ^= )
+#define rx_bitset_numb_subsets(N) (((N) + RX_subset_bits - 1) / RX_subset_bits)
+#define rx_sizeof_bitset(N)	(rx_bitset_numb_subsets(N) * sizeof(RX_subset))
+
+
+
+
+/* This page: Splay trees. */
+
+#ifdef __STDC__
+typedef int (*rx_sp_comparer) (void * a, void * b);
+#else
+typedef int (*rx_sp_comparer) ();
+#endif
+
+struct rx_sp_node 
+{
+  void * key;
+  void * data;
+  struct rx_sp_node * kids[2];
+};
+
+#ifdef __STDC__
+typedef void (*rx_sp_key_data_freer) (struct rx_sp_node *);
+#else
+typedef void (*rx_sp_key_data_freer) ();
+#endif
+
+
+
+/* giant inflatable hash trees */
+
+struct rx_hash_item
+{
+  struct rx_hash_item * next_same_hash;
+  struct rx_hash * table;
+  unsigned long hash;
+  void * data;
+  void * binding;
+};
+
+struct rx_hash
+{
+  struct rx_hash * parent;
+  int refs;
+  struct rx_hash * children[13];
+  struct rx_hash_item * buckets [13];
+  int bucket_size [13];
+};
+
+struct rx_hash_rules;
+
+#ifdef __STDC__
+/* should return like == */
+typedef int (*rx_hash_eq)(void *, void *);
+typedef struct rx_hash * (*rx_alloc_hash)(struct rx_hash_rules *);
+typedef void (*rx_free_hash)(struct rx_hash *,
+			    struct rx_hash_rules *);
+typedef struct rx_hash_item * (*rx_alloc_hash_item)(struct rx_hash_rules *,
+						    void *);
+typedef void (*rx_free_hash_item)(struct rx_hash_item *,
+				 struct rx_hash_rules *);
+#else
+typedef int (*rx_hash_eq)();
+typedef struct rx_hash * (*rx_alloc_hash)();
+typedef void (*rx_free_hash)();
+typedef struct rx_hash_item * (*rx_alloc_hash_item)();
+typedef void (*rx_free_hash_item)();
+#endif
+
+struct rx_hash_rules
+{
+  rx_hash_eq eq;
+  rx_alloc_hash hash_alloc;
+  rx_free_hash free_hash;
+  rx_alloc_hash_item hash_item_alloc;
+  rx_free_hash_item free_hash_item;
+};
+
+
+
+/* Forward declarations */
+
+struct rx_cache;
+struct rx_superset;
+struct rx;
+struct rx_se_list;
+
+
+
+
+/* 
+ * GLOSSARY
+ *
+ * regexp
+ * regular expression
+ * expression
+ * pattern - a `regular' expression.  The expression
+ *       need not be formally regular -- it can contain
+ *       constructs that don't correspond to purely regular
+ *       expressions.
+ *
+ * buffer
+ * string - the string (or strings) being searched or matched.
+ *
+ * pattern buffer - a structure of type `struct re_pattern_buffer'
+ *       This in turn contains a `struct rx', which holds the
+ *       NFA compiled from a pattern, as well as some of the state
+ *       of a matcher using the pattern.
+ *
+ * NFA - nondeterministic finite automata.  Some people
+ *       use this term to a member of the class of 
+ *       regular automata (those corresponding to a regular
+ *       language).  However, in this code, the meaning is
+ *       more general.  The automata used by Rx are comperable
+ *       in power to what are usually called `push down automata'.
+ *
+ *       Two NFA are built by rx for every pattern.  One is built
+ *       by the compiler.  The other is built from the first, on
+ *       the fly, by the matcher.  The latter is called the `superstate
+ *       NFA' because its states correspond to sets of states from
+ *       the first NFA.  (Joe Keane gets credit for the name
+ *       `superstate NFA').
+ *
+ * NFA edges
+ * epsilon edges
+ * side-effect edges - The NFA compiled from a pattern can have three
+ *       kinds of edges.  Epsilon edges can be taken freely anytime
+ *       their source state is reached.  Character set edges can be
+ *       taken when their source state is reached and when the next 
+ *       character in the buffer is a member of the set.  Side effect
+ *       edges imply a transition that can only be taken after the
+ *       indicated side effect has been successfully accomplished.
+ *       Some examples of side effects are:
+ *
+ *		Storing the current match position to record the
+ *              location of a parentesized subexpression.
+ *
+ *              Advancing the matcher over N characters if they
+ *              match the N characters previously matched by a 
+ *              parentesized subexpression.
+ *
+ *       Both of those kinds of edges occur in the NFA generated
+ *       by the pattern:  \(.\)\1
+ *
+ *       Epsilon and side effect edges are similar.  Unfortunately,
+ *       some of the code uses the name `epsilon edge' to mean
+ *       both epsilon and side effect edges.  For example,  the
+ *       function has_non_idempotent_epsilon_path computes the existance
+ *       of a non-trivial path containing only a mix of epsilon and
+ *       side effect edges.  In that case `nonidempotent epsilon' is being
+ *       used to mean `side effect'.
+ */
+
+
+
+
+
+
+/* LOW LEVEL PATTERN BUFFERS */
+
+/* Suppose that from some NFA state, more than one path through
+ * side-effect edges is possible.  In what order should the paths
+ * be tried?  A function of type rx_se_list_order answers that
+ * question.  It compares two lists of side effects, and says
+ * which list comes first.
+ */
+ 
+#ifdef __STDC__
+typedef int (*rx_se_list_order) (struct rx *,
+				 struct rx_se_list *, 
+				 struct rx_se_list *);
+#else
+typedef int (*rx_se_list_order) ();
+#endif
+
+
+
+/* Struct RX holds a compiled regular expression - that is, an nfa
+ * ready to be converted on demand to a more efficient superstate nfa.
+ * This is for the low level interface.  The high-level interfaces enclose
+ * this in a `struct re_pattern_buffer'.  
+ */
+struct rx
+{
+  /* The compiler assigns a unique id to every pattern.
+   * Like sequence numbers in X, there is a subtle bug here
+   * if you use Rx in a system that runs for a long time.
+   * But, because of the way the caches work out, it is almost
+   * impossible to trigger the Rx version of this bug.
+   *
+   * The id is used to validate superstates found in a cache
+   * of superstates.  It isn't sufficient to let a superstate
+   * point back to the rx for which it was compiled -- the caller
+   * may be re-using a `struct rx' in which case the superstate
+   * is not really valid.  So instead, superstates are validated
+   * by checking the sequence number of the pattern for which
+   * they were built.
+   */
+  int rx_id;
+
+  /* This is memory mgt. state for superstates.  This may be 
+   * shared by more than one struct rx.
+   */
+  struct rx_cache * cache;
+
+  /* Every regex defines the size of its own character set. 
+   * A superstate has an array of this size, with each element
+   * a `struct rx_inx'.  So, don't make this number too large.
+   * In particular, don't make it 2^16.
+   */
+  int local_cset_size;
+
+  /* After the NFA is built, it is copied into a contiguous region
+   * of memory (mostly for compatability with GNU regex).
+   * Here is that region, and it's size:
+   */
+  void * buffer;
+  unsigned long allocated;
+
+  /* Clients of RX can ask for some extra storage in the space pointed
+   * to by BUFFER.  The field RESERVED is an input parameter to the
+   * compiler.  After compilation, this much space will be available 
+   * at (buffer + allocated - reserved)
+   */
+  unsigned long reserved;
+
+  /* --------- The remaining fields are for internal use only. --------- */
+  /* --------- But! they must be initialized to 0.	       --------- */
+
+  /* NODEC is the number of nodes in the NFA with non-epsilon
+   * transitions. 
+   */
+  int nodec;
+
+  /* EPSNODEC is the number of nodes with only epsilon transitions. */
+  int epsnodec;
+
+  /* The sum (NODEC + EPSNODEC) is the total number of states in the
+   * compiled NFA.
+   */
+
+  /* Lists of side effects as stored in the NFA are `hash consed'..meaning
+   * that lists with the same elements are ==.  During compilation, 
+   * this table facilitates hash-consing.
+   */
+  struct rx_hash se_list_memo;
+
+  /* Lists of NFA states are also hashed. 
+   */
+  struct rx_hash set_list_memo;
+
+
+
+
+  /* The compiler and matcher must build a number of instruction frames.
+   * The format of these frames is fixed (c.f. struct rx_inx).  The values
+   * of the instructions is not fixed.
+   *
+   * An enumerated type (enum rx_opcode) defines the set of instructions
+   * that the compiler or matcher might generate.  When filling an instruction
+   * frame, the INX field is found by indexing this instruction table
+   * with an opcode:
+   */
+  void ** instruction_table;
+
+  /* The list of all states in an NFA.
+   * During compilation, the NEXT field of NFA states links this list.
+   * After compilation, all the states are compacted into an array,
+   * ordered by state id numbers.  At that time, this points to the base 
+   * of that array.
+   */
+  struct rx_nfa_state *nfa_states;
+
+  /* Every nfa begins with one distinguished starting state:
+   */
+  struct rx_nfa_state *start;
+
+  /* This orders the search through super-nfa paths.
+   * See the comment near the typedef of rx_se_list_order.
+   */
+  rx_se_list_order se_list_cmp;
+
+  struct rx_superset * start_set;
+};
+
+
+
+
+
+/* SYNTAX TREES */
+
+/* Compilation is in stages.  
+ *
+ * In the first stage, a pattern specified by a string is 
+ * translated into a syntax tree.  Later stages will convert
+ * the syntax tree into an NFA optimized for conversion to a
+ * superstate-NFA.
+ *
+ * This page is about syntax trees.
+ */
+
+enum rexp_node_type
+{
+  r_cset,			/* Match from a character set. `a' or `[a-z]'*/
+  r_concat,			/* Concat two subexpressions.   `ab' */
+  r_alternate,			/* Choose one of two subexpressions. `a\|b' */
+  r_opt,			/* Optional subexpression. `a?' */
+  r_star,			/* Repeated subexpression. `a*' */
+
+
+  /* A 2phase-star is a variation on a repeated subexpression.
+   * In this case, there are two subexpressions.  The first, if matched,
+   * begins a repitition (otherwise, the whole expression is matches the
+   * empth string).  
+   * 
+   * After matching the first subexpression, a 2phase star either finishes,
+   * or matches the second subexpression.  If the second subexpression is
+   * matched, then the whole construct repeats.
+   *
+   * 2phase stars are used in two circumstances.  First, they
+   * are used as part of the implementation of POSIX intervals (counted
+   * repititions).  Second, they are used to implement proper star
+   * semantics when the repeated subexpression contains paths of
+   * only side effects.  See rx_compile for more information.
+   */
+  r_2phase_star,
+
+
+  /* c.f. "typedef void * rx_side_effect" */
+  r_side_effect,
+
+  /* This is an extension type:  It is for transient use in source->source
+   * transformations (implemented over syntax trees).
+   */
+  r_data
+};
+
+/* A side effect is a matcher-specific action associated with
+ * transitions in the NFA.  The details of side effects are up
+ * to the matcher.  To the compiler and superstate constructors
+ * side effects are opaque:
+ */
+
+typedef void * rx_side_effect;
+
+/* Nodes in a syntax tree are of this type:
+ */
+struct rexp_node
+{
+  enum rexp_node_type type;
+  union
+  {
+    rx_Bitset cset;
+    rx_side_effect side_effect;
+    struct
+      {
+	struct rexp_node *left;
+	struct rexp_node *right;
+      } pair;
+    void * data;
+  } params;
+};
+
+
+
+
+/* NFA
+ *
+ * A syntax tree is compiled into an NFA.  This page defines the structure
+ * of that NFA.
+ */
+
+struct rx_nfa_state
+{
+  /* These are kept in a list as the NFA is being built. */
+  struct rx_nfa_state *next;
+
+  /* After the NFA is built, states are given integer id's.
+   * States whose outgoing transitions are all either epsilon or 
+   * side effect edges are given ids less than 0.  Other states
+   * are given successive non-negative ids starting from 0.
+   */
+  int id;
+
+  /* The list of NFA edges that go from this state to some other. */
+  struct rx_nfa_edge *edges;
+
+  /* If you land in this state, then you implicitly land
+   * in all other states reachable by only epsilon translations.
+   * Call the set of maximal paths to such states the epsilon closure
+   * of this state.
+   *
+   * There may be other states that are reachable by a mixture of
+   * epsilon and side effect edges.  Consider the set of maximal paths
+   * of that sort from this state.  Call it the epsilon-side-effect
+   * closure of the state.
+   * 
+   * The epsilon closure of the state is a subset of the epsilon-side-
+   * effect closure.  It consists of all the paths that contain 
+   * no side effects -- only epsilon edges.
+   * 
+   * The paths in the epsilon-side-effect closure  can be partitioned
+   * into equivalance sets. Two paths are equivalant if they have the
+   * same set of side effects, in the same order.  The epsilon-closure
+   * is one of these equivalance sets.  Let's call these equivalance
+   * sets: observably equivalant path sets.  That name is chosen
+   * because equivalance of two paths means they cause the same side
+   * effects -- so they lead to the same subsequent observations other
+   * than that they may wind up in different target states.
+   *
+   * The superstate nfa, which is derived from this nfa, is based on
+   * the observation that all of the paths in an observably equivalant
+   * path set can be explored at the same time, provided that the
+   * matcher keeps track not of a single nfa state, but of a set of
+   * states.   In particular, after following all the paths in an
+   * observably equivalant set, you wind up at a set of target states.
+   * That set of target states corresponds to one state in the
+   * superstate NFA.
+   *
+   * Staticly, before matching begins, it is convenient to analyze the
+   * nfa.  Each state is labeled with a list of the observably
+   * equivalant path sets who's union covers all the
+   * epsilon-side-effect paths beginning in this state.  This list is
+   * called the possible futures of the state.
+   *
+   * A trivial example is this NFA:
+   *             s1
+   *         A  --->  B
+   *
+   *             s2  
+   *            --->  C
+   *
+   *             epsilon           s1
+   *            --------->  D   ------> E
+   * 
+   * 
+   * In this example, A has two possible futures.
+   * One invokes the side effect `s1' and contains two paths,
+   * one ending in state B, the other in state E.
+   * The other invokes the side effect `s2' and contains only
+   * one path, landing in state C.
+   */
+  struct rx_possible_future *futures;
+
+
+  /* There are exactly two distinguished states in every NFA: */
+  unsigned int is_final:1;
+  unsigned int is_start:1;
+
+  /* These are used during NFA construction... */
+  unsigned int eclosure_needed:1;
+  unsigned int mark:1;
+};
+
+
+/* An edge in an NFA is typed: */
+enum rx_nfa_etype
+{
+  /* A cset edge is labled with a set of characters one of which
+   * must be matched for the edge to be taken.
+   */
+  ne_cset,
+
+  /* An epsilon edge is taken whenever its starting state is
+   * reached. 
+   */
+  ne_epsilon,
+
+  /* A side effect edge is taken whenever its starting state is
+   * reached.  Side effects may cause the match to fail or the
+   * position of the matcher to advance.
+   */
+  ne_side_effect		/* A special kind of epsilon. */
+};
+
+struct rx_nfa_edge
+{
+  struct rx_nfa_edge *next;
+  enum rx_nfa_etype type;
+  struct rx_nfa_state *dest;
+  union
+  {
+    rx_Bitset cset;
+    rx_side_effect side_effect;
+  } params;
+};
+
+
+
+/* A possible future consists of a list of side effects
+ * and a set of destination states.  Below are their
+ * representations.  These structures are hash-consed which
+ * means that lists with the same elements share a representation
+ * (their addresses are ==).
+ */
+
+struct rx_nfa_state_set
+{
+  struct rx_nfa_state * car;
+  struct rx_nfa_state_set * cdr;
+};
+
+struct rx_se_list
+{
+  rx_side_effect car;
+  struct rx_se_list * cdr;
+};
+
+struct rx_possible_future
+{
+  struct rx_possible_future *next;
+  struct rx_se_list * effects;
+  struct rx_nfa_state_set * destset;
+};
+
+
+
+
+/* This begins the description of the superstate NFA.
+ *
+ * The superstate NFA corresponds to the NFA in these ways:
+ *
+ * Every superstate NFA states SUPER correspond to sets of NFA states,
+ * nfa_states(SUPER).
+ *
+ * Superstate edges correspond to NFA paths.
+ *
+ * The superstate has no epsilon transitions;
+ * every edge has a character label, and a (possibly empty) side
+ * effect label.   The side effect label corresponds to a list of
+ * side effects that occur in the NFA.  These parts are referred
+ * to as:   superedge_character(EDGE) and superedge_sides(EDGE).
+ *
+ * For a superstate edge EDGE starting in some superstate SUPER,
+ * the following is true (in pseudo-notation :-):
+ *
+ *       exists DEST in nfa_states s.t. 
+ *         exists nfaEDGE in nfa_edges s.t.
+ *                 origin (nfaEDGE) == DEST
+ *              && origin (nfaEDGE) is a member of nfa_states(SUPER)
+ *              && exists PF in possible_futures(dest(nfaEDGE)) s.t.
+ * 	                sides_of_possible_future (PF) == superedge_sides (EDGE)
+ *
+ * also:
+ *
+ *      let SUPER2 := superedge_destination(EDGE)
+ *          nfa_states(SUPER2)
+ *           == union of all nfa state sets S s.t.
+ *                          exists PF in possible_futures(dest(nfaEDGE)) s.t.
+ * 	                       sides_of_possible_future (PF) == superedge_sides (EDGE)
+ *                          && S == dests_of_possible_future (PF) }
+ *
+ * Or in english, every superstate is a set of nfa states.  A given
+ * character and a superstate implies many transitions in the NFA --
+ * those that begin with an edge labeled with that character from a
+ * state in the set corresponding to the superstate.
+ * 
+ * The destinations of those transitions each have a set of possible
+ * futures.  A possible future is a list of side effects and a set of
+ * destination NFA states.  Two sets of possible futures can be
+ * `merged' by combining all pairs of possible futures that have the
+ * same side effects.  A pair is combined by creating a new future
+ * with the same side effect but the union of the two destination sets.
+ * In this way, all the possible futures suggested by a superstate
+ * and a character can be merged into a set of possible futures where
+ * no two elements of the set have the same set of side effects.
+ *
+ * The destination of a possible future, being a set of NFA states, 
+ * corresponds to a supernfa state.  So, the merged set of possible
+ * futures we just created can serve as a set of edges in the
+ * supernfa.
+ *
+ * The representation of the superstate nfa and the nfa is critical.
+ * The nfa has to be compact, but has to facilitate the rapid
+ * computation of missing superstates.  The superstate nfa has to 
+ * be fast to interpret, lazilly constructed, and bounded in space.
+ *
+ * To facilitate interpretation, the superstate data structures are 
+ * peppered with `instruction frames'.  There is an instruction set
+ * defined below which matchers using the supernfa must be able to
+ * interpret.
+ *
+ * We'd like to make it possible but not mandatory to use code
+ * addresses to represent instructions (c.f. gcc's computed goto).
+ * Therefore, we define an enumerated type of opcodes, and when
+ * writing one of these instructions into a data structure, use
+ * the opcode as an index into a table of instruction values.
+ * 
+ * Here are the opcodes that occur in the superstate nfa:
+ */
+ 
+
+/* Every superstate contains a table of instruction frames indexed 
+ * by characters.  A normal `move' in a matcher is to fetch the next
+ * character and use it as an index into a superstates transition
+ * table.
+ *
+ * In the fasted case, only one edge follows from that character.
+ * In other cases there is more work to do.
+ * 
+ * The descriptions of the opcodes refer to data structures that are
+ * described further below. 
+ */
+
+enum rx_opcode
+{
+  /* 
+   * BACKTRACK_POINT is invoked when a character transition in 
+   * a superstate leads to more than one edge.  In that case,
+   * the edges have to be explored independently using a backtracking
+   * strategy.
+   *
+   * A BACKTRACK_POINT instruction is stored in a superstate's 
+   * transition table for some character when it is known that that
+   * character crosses more than one edge.  On encountering this
+   * instruction, the matcher saves enough state to backtrack to this
+   * point in the match later.
+   */
+  rx_backtrack_point = 0,	/* data is (struct transition_class *) */
+
+  /* 
+   * RX_DO_SIDE_EFFECTS evaluates the side effects of an epsilon path.
+   * There is one occurence of this instruction per rx_distinct_future.
+   * This instruction is skipped if a rx_distinct_future has no side effects.
+   */
+  rx_do_side_effects = rx_backtrack_point + 1,
+
+  /* data is (struct rx_distinct_future *) */
+
+  /* 
+   * RX_CACHE_MISS instructions are stored in rx_distinct_futures whose
+   * destination superstate has been reclaimed (or was never built).
+   * It recomputes the destination superstate.
+   * RX_CACHE_MISS is also stored in a superstate transition table before
+   * any of its edges have been built.
+   */
+  rx_cache_miss = rx_do_side_effects + 1,
+  /* data is (struct rx_distinct_future *) */
+
+  /* 
+   * RX_NEXT_CHAR is called to consume the next character and take the
+   * corresponding transition.  This is the only instruction that uses 
+   * the DATA field of the instruction frame instead of DATA_2.
+   * (see EXPLORE_FUTURE in regex.c).
+   */
+  rx_next_char = rx_cache_miss + 1, /* data is (struct superstate *) */
+
+  /* RX_BACKTRACK indicates that a transition fails.
+   */
+  rx_backtrack = rx_next_char + 1, /* no data */
+
+  /* 
+   * RX_ERROR_INX is stored only in places that should never be executed.
+   */
+  rx_error_inx = rx_backtrack + 1, /* Not supposed to occur. */
+
+  rx_num_instructions = rx_error_inx + 1
+};
+
+/* An id_instruction_table holds the values stored in instruction
+ * frames.  The table is indexed by the enums declared above.
+ */
+extern void * rx_id_instruction_table[rx_num_instructions];
+
+/* The heart of the matcher is a `word-code-interpreter' 
+ * (like a byte-code interpreter, except that instructions
+ * are a full word wide).
+ *
+ * Instructions are not stored in a vector of code, instead,
+ * they are scattered throughout the data structures built
+ * by the regexp compiler and the matcher.  One word-code instruction,
+ * together with the arguments to that instruction, constitute
+ * an instruction frame (struct rx_inx).
+ *
+ * This structure type is padded by hand to a power of 2 because
+ * in one of the dominant cases, we dispatch by indexing a table
+ * of instruction frames.  If that indexing can be accomplished
+ * by just a shift of the index, we're happy.
+ *
+ * Instructions take at most one argument, but there are two
+ * slots in an instruction frame that might hold that argument.
+ * These are called data and data_2.  The data slot is only
+ * used for one instruction (RX_NEXT_CHAR).  For all other 
+ * instructions, data should be set to 0.
+ *
+ * RX_NEXT_CHAR is the most important instruction by far.
+ * By reserving the data field for its exclusive use, 
+ * instruction dispatch is sped up in that case.  There is
+ * no need to fetch both the instruction and the data,
+ * only the data is needed.  In other words, a `cycle' begins
+ * by fetching the field data.  If that is non-0, then it must
+ * be the destination state of a next_char transition, so
+ * make that value the current state, advance the match position
+ * by one character, and start a new cycle.  On the other hand,
+ * if data is 0, fetch the instruction and do a more complicated
+ * dispatch on that.
+ */
+
+struct rx_inx 
+{
+  void * data;
+  void * data_2;
+  void * inx;
+  void * fnord;
+};
+
+#ifndef RX_TAIL_ARRAY
+#define RX_TAIL_ARRAY  1
+#endif
+
+/* A superstate corresponds to a set of nfa states.  Those sets are
+ * represented by STRUCT RX_SUPERSET.  The constructors
+ * guarantee that only one (shared) structure is created for a given set.
+ */
+struct rx_superset
+{
+  int refs;			/* This is a reference counted structure. */
+
+  /* We keep these sets in a cache because (in an unpredictable way),
+   * the same set is often created again and again.  But that is also
+   * problematic -- compatibility with POSIX and GNU regex requires
+   * that we not be able to tell when a program discards a particular
+   * NFA (thus invalidating the supersets created from it).
+   *
+   * But when a cache hit appears to occur, we will have in hand the
+   * nfa for which it may have happened.  That is why every nfa is given
+   * its own sequence number.  On a cache hit, the cache is validated
+   * by comparing the nfa sequence number to this field:
+   */
+  int id;
+
+  struct rx_nfa_state * car;	/* May or may not be a valid addr. */
+  struct rx_superset * cdr;
+
+  /* If the corresponding superstate exists: */
+  struct rx_superstate * superstate;
+
+
+  /* There is another bookkeeping problem.  It is expensive to 
+   * compute the starting nfa state set for an nfa.  So, once computed,
+   * it is cached in the `struct rx'.
+   *
+   * But, the state set can be flushed from the superstate cache.
+   * When that happens, we can't know if the corresponding `struct rx'
+   * is still alive or if it has been freed or re-used by the program.
+   * So, the cached pointer to this set in a struct rx might be invalid
+   * and we need a way to validate it.
+   *
+   * Fortunately, even if this set is flushed from the cache, it is
+   * not freed.  It just goes on the free-list of supersets.
+   * So we can still examine it.  
+   *
+   * So to validate a starting set memo, check to see if the
+   * starts_for field still points back to the struct rx in question,
+   * and if the ID matches the rx sequence number.
+   */
+  struct rx * starts_for;
+
+  /* This is used to link into a hash bucket so these objects can
+   * be `hash-consed'.
+   */
+  struct rx_hash_item hash_item;
+};
+
+#define rx_protect_superset(RX,CON) (++(CON)->refs)
+
+/* The terminology may be confusing (rename this structure?).
+ * Every character occurs in at most one rx_super_edge per super-state.
+ * But, that structure might have more than one option, indicating a point
+ * of non-determinism. 
+ *
+ * In other words, this structure holds a list of superstate edges
+ * sharing a common starting state and character label.  The edges
+ * are in the field OPTIONS.  All superstate edges sharing the same
+ * starting state and character are in this list.
+ */
+struct rx_super_edge
+{
+  struct rx_super_edge *next;
+  struct rx_inx rx_backtrack_frame;
+  int cset_size;
+  rx_Bitset cset;
+  struct rx_distinct_future *options;
+};
+
+/* A superstate is a set of nfa states (RX_SUPERSET) along
+ * with a transition table.  Superstates are built on demand and reclaimed
+ * without warning.  To protect a superstate from this ghastly fate,
+ * use LOCK_SUPERSTATE. 
+ */
+struct rx_superstate
+{
+  int rx_id;			/* c.f. the id field of rx_superset */
+  int locks;			/* protection from reclamation */
+
+  /* Within a superstate cache, all the superstates are kept in a big
+   * queue.  The tail of the queue is the state most likely to be
+   * reclaimed.  The *recyclable fields hold the queue position of 
+   * this state.
+   */
+  struct rx_superstate * next_recyclable;
+  struct rx_superstate * prev_recyclable;
+
+  /* The supernfa edges that exist in the cache and that have
+   * this state as their destination are kept in this list:
+   */
+  struct rx_distinct_future * transition_refs;
+
+  /* The list of nfa states corresponding to this superstate: */
+  struct rx_superset * contents;
+
+  /* The list of edges in the cache beginning from this state. */
+  struct rx_super_edge * edges;
+
+  /* A tail of the recyclable queue is marked as semifree.  A semifree
+   * state has no incoming next_char transitions -- any transition
+   * into a semifree state causes a complex dispatch with the side
+   * effect of rescuing the state from its semifree state.
+   *
+   * An alternative to this might be to make next_char more expensive,
+   * and to move a state to the head of the recyclable queue whenever
+   * it is entered.  That way, popular states would never be recycled.
+   *
+   * But unilaterally making next_char more expensive actually loses.
+   * So, incoming transitions are only made expensive for states near
+   * the tail of the recyclable queue.  The more cache contention
+   * there is, the more frequently a state will have to prove itself
+   * and be moved back to the front of the queue.  If there is less 
+   * contention, then popular states just aggregate in the front of 
+   * the queue and stay there.
+   */
+  int is_semifree;
+
+
+  /* This keeps track of the size of the transition table for this
+   * state.  There is a half-hearted attempt to support variable sized
+   * superstates.
+   */
+  int trans_size;
+
+  /* Indexed by characters... */
+  struct rx_inx transitions[RX_TAIL_ARRAY];
+};
+
+
+/* A list of distinct futures define the edges that leave from a 
+ * given superstate on a given character.  c.f. rx_super_edge.
+ */
+
+struct rx_distinct_future
+{
+  struct rx_distinct_future * next_same_super_edge[2];
+  struct rx_distinct_future * next_same_dest;
+  struct rx_distinct_future * prev_same_dest;
+  struct rx_superstate * present;	/* source state */
+  struct rx_superstate * future;	/* destination state */
+  struct rx_super_edge * edge;
+
+
+  /* The future_frame holds the instruction that should be executed
+   * after all the side effects are done, when it is time to complete
+   * the transition to the next state.
+   *
+   * Normally this is a next_char instruction, but it may be a
+   * cache_miss instruction as well, depending on whether or not
+   * the superstate is in the cache and semifree.
+   * 
+   * If this is the only future for a given superstate/char, and
+   * if there are no side effects to be performed, this frame is
+   * not used (directly) at all.  Instead, its contents are copied
+   * into the transition table of the starting state of this dist. future.
+   */
+  struct rx_inx future_frame;
+
+  struct rx_inx side_effects_frame;
+  struct rx_se_list * effects;
+};
+
+#define rx_lock_superstate(R,S)  ((S)->locks++)
+#define rx_unlock_superstate(R,S) (--(S)->locks)
+
+
+
+/* This page destined for rx.h */
+
+struct rx_blocklist
+{
+  struct rx_blocklist * next;
+  int bytes;
+};
+
+struct rx_freelist
+{
+  struct rx_freelist * next;
+};
+
+struct rx_cache;
+
+#ifdef __STDC__
+typedef void (*rx_morecore_fn)(struct rx_cache *);
+#else
+typedef void (*rx_morecore_fn)();
+#endif
+
+/* You use this to control the allocation of superstate data 
+ * during matching.  Most of it should be initialized to 0.
+ *
+ * A MORECORE function is necessary.  It should allocate
+ * a new block of memory or return 0.
+ * A default that uses malloc is called `rx_morecore'.
+ *
+ * The number of SUPERSTATES_ALLOWED indirectly limits how much memory
+ * the system will try to allocate.  The default is 128.  Batch style
+ * applications that are very regexp intensive should use as high a number
+ * as possible without thrashing.
+ * 
+ * The LOCAL_CSET_SIZE is the number of characters in a character set.
+ * It is therefore the number of entries in a superstate transition table.
+ * Generally, it should be 256.  If your character set has 16 bits, 
+ * it is better to translate your regexps into equivalent 8 bit patterns.
+ */
+
+struct rx_cache
+{
+  struct rx_hash_rules superset_hash_rules;
+
+  /* Objects are allocated by incrementing a pointer that 
+   * scans across rx_blocklists.
+   */
+  struct rx_blocklist * memory;
+  struct rx_blocklist * memory_pos;
+  int bytes_left;
+  char * memory_addr;
+  rx_morecore_fn morecore;
+
+  /* Freelists. */
+  struct rx_freelist * free_superstates;
+  struct rx_freelist * free_transition_classes;
+  struct rx_freelist * free_discernable_futures;
+  struct rx_freelist * free_supersets;
+  struct rx_freelist * free_hash;
+
+  /* Two sets of superstates -- those that are semifreed, and those
+   * that are being used.
+   */
+  struct rx_superstate * lru_superstate;
+  struct rx_superstate * semifree_superstate;
+
+  struct rx_superset * empty_superset;
+
+  int superstates;
+  int semifree_superstates;
+  int hits;
+  int misses;
+  int superstates_allowed;
+
+  int local_cset_size;
+  void ** instruction_table;
+
+  struct rx_hash superset_table;
+};
+
+
+
+
+/* The lowest-level search function supports arbitrarily fragmented
+ * strings and (optionally) suspendable/resumable searches.
+ *
+ * Callers have to provide a few hooks.
+ */
+
+#ifndef __GNUC__
+#ifdef __STDC__
+#define __const__ const
+#else
+#define __const__
+#endif
+#endif
+
+/* This holds a matcher position */
+struct rx_string_position
+{
+  __const__ unsigned char * pos;	/* The current pos. */
+  __const__ unsigned char * string; /* The current string burst. */
+  __const__ unsigned char * end;	/* First invalid position >= POS. */
+  int offset;			/* Integer address of the current burst. */
+  int size;			/* Current string's size. */
+  int search_direction;		/* 1 or -1 */
+  int search_end;		/* First position to not try. */
+};
+
+
+enum rx_get_burst_return
+{
+  rx_get_burst_continuation,
+  rx_get_burst_error,
+  rx_get_burst_ok,
+  rx_get_burst_no_more
+};
+
+
+/* A call to get burst should make POS valid.  It might be invalid
+ * if the STRING field doesn't point to a burst that actually
+ * contains POS.
+ *
+ * GET_BURST should take a clue from SEARCH_DIRECTION (1 or -1) as to
+ * whether or not to pad to the left.  Padding to the right is always
+ * appropriate, but need not go past the point indicated by STOP.
+ *
+ * If a continuation is returned, then the reentering call to
+ * a search function will retry the get_burst.
+ */
+
+#ifdef __STDC__
+typedef enum rx_get_burst_return
+  (*rx_get_burst_fn) (struct rx_string_position * pos,
+		      void * app_closure,
+		      int stop);
+					       
+#else
+typedef enum rx_get_burst_return (*rx_get_burst_fn) ();
+#endif
+
+
+enum rx_back_check_return
+{
+  rx_back_check_continuation,
+  rx_back_check_error,
+  rx_back_check_pass,
+  rx_back_check_fail
+};
+
+/* Back_check should advance the position it is passed 
+ * over rparen - lparen characters and return pass iff
+ * the characters starting at POS match those indexed
+ * by [LPAREN..RPAREN].
+ *
+ * If a continuation is returned, then the reentering call to
+ * a search function will retry the back_check.
+ */
+
+#ifdef __STDC__
+typedef enum rx_back_check_return
+  (*rx_back_check_fn) (struct rx_string_position * pos,
+		       int lparen,
+		       int rparen,
+		       unsigned char * translate,
+		       void * app_closure,
+		       int stop);
+					       
+#else
+typedef enum rx_back_check_return (*rx_back_check_fn) ();
+#endif
+
+
+
+
+/* A call to fetch_char should return the character at POS or POS + 1.
+ * Returning continuations here isn't supported.  OFFSET is either 0 or 1
+ * and indicates which characters is desired.
+ */
+
+#ifdef __STDC__
+typedef int (*rx_fetch_char_fn) (struct rx_string_position * pos,
+				 int offset,
+				 void * app_closure,
+				 int stop);
+#else
+typedef int (*rx_fetch_char_fn) ();
+#endif
+
+
+enum rx_search_return
+{
+  rx_search_continuation = -4,
+  rx_search_error = -3,
+  rx_search_soft_fail = -2,	/* failed by running out of string */
+  rx_search_fail = -1		/* failed only by reaching failure states */
+  /* return values >= 0 indicate the position of a successful match */
+};
+
+
+
+
+
+
+
+/* regex.h
+ * 
+ * The remaining declarations replace regex.h.
+ */
+
+/* This is an array of error messages corresponding to the error codes.
+ */
+extern __const__ char *re_error_msg[];
+
+/* If any error codes are removed, changed, or added, update the
+   `re_error_msg' table in regex.c.  */
+typedef enum
+{
+  REG_NOERROR = 0,	/* Success.  */
+  REG_NOMATCH,		/* Didn't find a match (for regexec).  */
+
+  /* POSIX regcomp return error codes.  (In the order listed in the
+     standard.)  */
+  REG_BADPAT,		/* Invalid pattern.  */
+  REG_ECOLLATE,		/* Not implemented.  */
+  REG_ECTYPE,		/* Invalid character class name.  */
+  REG_EESCAPE,		/* Trailing backslash.  */
+  REG_ESUBREG,		/* Invalid back reference.  */
+  REG_EBRACK,		/* Unmatched left bracket.  */
+  REG_EPAREN,		/* Parenthesis imbalance.  */ 
+  REG_EBRACE,		/* Unmatched \{.  */
+  REG_BADBR,		/* Invalid contents of \{\}.  */
+  REG_ERANGE,		/* Invalid range end.  */
+  REG_ESPACE,		/* Ran out of memory.  */
+  REG_BADRPT,		/* No preceding re for repetition op.  */
+
+  /* Error codes we've added.  */
+  REG_EEND,		/* Premature end.  */
+  REG_ESIZE,		/* Compiled pattern bigger than 2^16 bytes.  */
+  REG_ERPAREN		/* Unmatched ) or \); not returned from regcomp.  */
+} reg_errcode_t;
+
+/* The regex.c support, as a client of rx, defines a set of possible
+ * side effects that can be added to the edge lables of nfa edges.
+ * Here is the list of sidef effects in use.
+ */
+
+enum re_side_effects
+{
+#define RX_WANT_SE_DEFS 1
+#undef RX_DEF_SE
+#undef RX_DEF_CPLX_SE
+#define RX_DEF_SE(IDEM, NAME, VALUE)	      NAME VALUE,
+#define RX_DEF_CPLX_SE(IDEM, NAME, VALUE)     NAME VALUE,
+#include "rx.h"
+#undef RX_DEF_SE
+#undef RX_DEF_CPLX_SE
+#undef RX_WANT_SE_DEFS
+   re_floogle_flap = 65533
+};
+
+/* These hold paramaters for the kinds of side effects that are possible
+ * in the supported pattern languages.  These include things like the 
+ * numeric bounds of {} operators and the index of paren registers for 
+ * subexpression measurement or backreferencing.
+ */
+struct re_se_params
+{
+  enum re_side_effects se;
+  int op1;
+  int op2;
+};
+
+typedef unsigned reg_syntax_t;
+
+struct re_pattern_buffer
+{
+  struct rx rx;
+  reg_syntax_t syntax;		/* See below for syntax bit definitions. */
+
+  unsigned int no_sub:1;	/* If set, don't  return register offsets. */
+  unsigned int not_bol:1;	/* If set, the anchors ('^' and '$') don't */
+  unsigned int not_eol:1;	/*     match at the ends of the string.  */  
+  unsigned int newline_anchor:1;/* If true, an anchor at a newline matches.*/
+  unsigned int least_subs:1;	/* If set, and returning registers, return
+				 * as few values as possible.  Only 
+				 * backreferenced groups and group 0 (the whole
+				 * match) will be returned.
+				 */
+
+  /* If true, this says that the matcher should keep registers on its
+   * backtracking stack.  For many patterns, we can easily determine that
+   * this isn't necessary.
+   */
+  unsigned int match_regs_on_stack:1;
+  unsigned int search_regs_on_stack:1;
+
+  /* is_anchored and begbuf_only are filled in by rx_compile. */
+  unsigned int is_anchored:1;	/* Anchorded by ^? */
+  unsigned int begbuf_only:1;	/* Anchored to char position 0? */
+
+  
+  /* If REGS_UNALLOCATED, allocate space in the `regs' structure
+   * for `max (RE_NREGS, re_nsub + 1)' groups.
+   * If REGS_REALLOCATE, reallocate space if necessary.
+   * If REGS_FIXED, use what's there.  
+   */
+#define REGS_UNALLOCATED 0
+#define REGS_REALLOCATE 1
+#define REGS_FIXED 2
+  unsigned int regs_allocated:2;
+
+  
+  /* Either a translate table to apply to all characters before
+   * comparing them, or zero for no translation.  The translation
+   * is applied to a pattern when it is compiled and to a string
+   * when it is matched.
+   */
+  unsigned char * translate;
+
+  /* If this is a valid pointer, it tells rx not to store the extents of 
+   * certain subexpressions (those corresponding to non-zero entries).
+   * Passing 0x1 is the same as passing an array of all ones.  Passing 0x0
+   * is the same as passing an array of all zeros.
+   * The array should contain as many entries as their are subexps in the 
+   * regexp.
+   *
+   * For POSIX compatability, when using regcomp and regexec this field
+   * is zeroed and ignored.
+   */
+  char * syntax_parens;
+
+	/* Number of subexpressions found by the compiler.  */
+  size_t re_nsub;
+
+  void * buffer;		/* Malloced memory for the nfa. */
+  unsigned long allocated;	/* Size of that memory. */
+
+  /* Pointer to a fastmap, if any, otherwise zero.  re_search uses
+   * the fastmap, if there is one, to skip over impossible
+   * starting points for matches.  */
+  char *fastmap;
+
+  unsigned int fastmap_accurate:1; /* These three are internal. */
+  unsigned int can_match_empty:1;  
+  struct rx_nfa_state * start;	/* The nfa starting state. */
+
+  /* This is the list of iterator bounds for {lo,hi} constructs.
+   * The memory pointed to is part of the rx->buffer.
+   */
+  struct re_se_params *se_params;
+
+  /* This is a bitset representation of the fastmap.
+   * This is a true fastmap that already takes the translate
+   * table into account.
+   */
+  rx_Bitset fastset;
+};
+
+/* Type for byte offsets within the string.  POSIX mandates this.  */
+typedef int regoff_t;
+
+/* This is the structure we store register match data in.  See
+   regex.texinfo for a full description of what registers match.  */
+struct re_registers
+{
+  unsigned num_regs;
+  regoff_t *start;
+  regoff_t *end;
+};
+
+typedef struct re_pattern_buffer regex_t;
+
+/* POSIX specification for registers.  Aside from the different names than
+   `re_registers', POSIX uses an array of structures, instead of a
+   structure of arrays.  */
+typedef struct
+{
+  regoff_t rm_so;  /* Byte offset from string's start to substring's start.  */
+  regoff_t rm_eo;  /* Byte offset from string's start to substring's end.  */
+} regmatch_t;
+
+
+
+/* The following bits are used to determine the regexp syntax we
+   recognize.  The set/not-set meanings are chosen so that Emacs syntax
+   remains the value 0.  The bits are given in alphabetical order, and
+   the definitions shifted by one from the previous bit; thus, when we
+   add or remove a bit, only one other definition need change.  */
+
+/* If this bit is not set, then \ inside a bracket expression is literal.
+   If set, then such a \ quotes the following character.  */
+#define RE_BACKSLASH_ESCAPE_IN_LISTS (1)
+
+/* If this bit is not set, then + and ? are operators, and \+ and \? are
+     literals. 
+   If set, then \+ and \? are operators and + and ? are literals.  */
+#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
+
+/* If this bit is set, then character classes are supported.  They are:
+     [:alpha:], [:upper:], [:lower:],  [:digit:], [:alnum:], [:xdigit:],
+     [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
+   If not set, then character classes are not supported.  */
+#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
+
+/* If this bit is set, then ^ and $ are always anchors (outside bracket
+     expressions, of course).
+   If this bit is not set, then it depends:
+        ^  is an anchor if it is at the beginning of a regular
+           expression or after an open-group or an alternation operator;
+        $  is an anchor if it is at the end of a regular expression, or
+           before a close-group or an alternation operator.  
+
+   This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
+   POSIX draft 11.2 says that * etc. in leading positions is undefined.
+   We already implemented a previous draft which made those constructs
+   invalid, though, so we haven't changed the code back.  */
+#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
+
+/* If this bit is set, then special characters are always special
+     regardless of where they are in the pattern.
+   If this bit is not set, then special characters are special only in
+     some contexts; otherwise they are ordinary.  Specifically, 
+     * + ? and intervals are only special when not after the beginning,
+     open-group, or alternation operator.  */
+#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
+
+/* If this bit is set, then *, +, ?, and { cannot be first in an re or
+     immediately after an alternation or begin-group operator.  */
+#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
+
+/* If this bit is set, then . matches newline.
+   If not set, then it doesn't.  */
+#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
+
+/* If this bit is set, then . doesn't match NUL.
+   If not set, then it does.  */
+#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
+
+/* If this bit is set, nonmatching lists [^...] do not match newline.
+   If not set, they do.  */
+#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
+
+/* If this bit is set, either \{...\} or {...} defines an
+     interval, depending on RE_NO_BK_BRACES. 
+   If not set, \{, \}, {, and } are literals.  */
+#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
+
+/* If this bit is set, +, ? and | aren't recognized as operators.
+   If not set, they are.  */
+#define RE_LIMITED_OPS (RE_INTERVALS << 1)
+
+/* If this bit is set, newline is an alternation operator.
+   If not set, newline is literal.  */
+#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
+
+/* If this bit is set, then `{...}' defines an interval, and \{ and \}
+     are literals.
+  If not set, then `\{...\}' defines an interval.  */
+#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
+
+/* If this bit is set, (...) defines a group, and \( and \) are literals.
+   If not set, \(...\) defines a group, and ( and ) are literals.  */
+#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
+
+/* If this bit is set, then \<digit> matches <digit>.
+   If not set, then \<digit> is a back-reference.  */
+#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
+
+/* If this bit is set, then | is an alternation operator, and \| is literal. 
+   If not set, then \| is an alternation operator, and | is literal.  */
+#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
+
+/* If this bit is set, then an ending range point collating higher
+     than the starting range point, as in [z-a], is invalid.
+   If not set, then when ending range point collates higher than the
+     starting range point, the range is ignored.  */
+#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
+
+/* If this bit is set, then an unmatched ) is ordinary.
+   If not set, then an unmatched ) is invalid.  */
+#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
+
+/* This global variable defines the particular regexp syntax to use (for
+   some interfaces).  When a regexp is compiled, the syntax used is
+   stored in the pattern buffer, so changing this does not affect
+   already-compiled regexps.  */
+extern reg_syntax_t re_syntax_options;
+
+
+/* Define combinations of the above bits for the standard possibilities.
+   (The [[[ comments delimit what gets put into the Texinfo file, so
+   don't delete them!)  */ 
+/* [[[begin syntaxes]]] */
+#define RE_SYNTAX_EMACS 0
+
+#define RE_SYNTAX_AWK							\
+  (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL			\
+   | RE_NO_BK_PARENS            | RE_NO_BK_REFS				\
+   | RE_NO_BK_VAR               | RE_NO_EMPTY_RANGES			\
+   | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+#define RE_SYNTAX_POSIX_AWK 						\
+  (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS)
+
+#define RE_SYNTAX_GREP							\
+  (RE_BK_PLUS_QM              | RE_CHAR_CLASSES				\
+   | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS				\
+   | RE_NEWLINE_ALT)
+
+#define RE_SYNTAX_EGREP							\
+  (RE_CHAR_CLASSES        | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE			\
+   | RE_NEWLINE_ALT       | RE_NO_BK_PARENS				\
+   | RE_NO_BK_VBAR)
+
+#define RE_SYNTAX_POSIX_EGREP						\
+  (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
+
+#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
+
+/* Syntax bits common to both basic and extended POSIX regex syntax.  */
+#define _RE_SYNTAX_POSIX_COMMON						\
+  (RE_CHAR_CLASSES | RE_DOT_NEWLINE      | RE_DOT_NOT_NULL		\
+   | RE_INTERVALS  | RE_NO_EMPTY_RANGES)
+
+#define RE_SYNTAX_POSIX_BASIC						\
+  (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
+
+/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
+   RE_LIMITED_OPS, i.e., \? \+ \| are not recognized.  Actually, this
+   isn't minimal, since other operators, such as \`, aren't disabled.  */
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC					\
+  (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
+
+#define RE_SYNTAX_POSIX_EXTENDED					\
+  (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INDEP_OPS  | RE_NO_BK_BRACES				\
+   | RE_NO_BK_PARENS       | RE_NO_BK_VBAR				\
+   | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
+   replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added.  */
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED				\
+  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES				\
+   | RE_NO_BK_PARENS        | RE_NO_BK_REFS				\
+   | RE_NO_BK_VBAR	    | RE_UNMATCHED_RIGHT_PAREN_ORD)
+/* [[[end syntaxes]]] */
+
+/* Maximum number of duplicates an interval can allow.  Some systems
+   (erroneously) define this in other header files, but we want our
+   value, so remove any previous define.  */
+#ifdef RE_DUP_MAX
+#undef RE_DUP_MAX
+#endif
+#define RE_DUP_MAX ((1 << 15) - 1) 
+
+
+
+/* POSIX `cflags' bits (i.e., information for `regcomp').  */
+
+/* If this bit is set, then use extended regular expression syntax.
+   If not set, then use basic regular expression syntax.  */
+#define REG_EXTENDED 1
+
+/* If this bit is set, then ignore case when matching.
+   If not set, then case is significant.  */
+#define REG_ICASE (REG_EXTENDED << 1)
+ 
+/* If this bit is set, then anchors do not match at newline
+     characters in the string.
+   If not set, then anchors do match at newlines.  */
+#define REG_NEWLINE (REG_ICASE << 1)
+
+/* If this bit is set, then report only success or fail in regexec.
+   If not set, then returns differ between not matching and errors.  */
+#define REG_NOSUB (REG_NEWLINE << 1)
+
+
+/* POSIX `eflags' bits (i.e., information for regexec).  */
+
+/* If this bit is set, then the beginning-of-line operator doesn't match
+     the beginning of the string (presumably because it's not the
+     beginning of a line).
+   If not set, then the beginning-of-line operator does match the
+     beginning of the string.  */
+#define REG_NOTBOL 1
+
+/* Like REG_NOTBOL, except for the end-of-line.  */
+#define REG_NOTEOL (1 << 1)
+
+/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
+ * `re_match_2' returns information about at least this many registers
+ * the first time a `regs' structure is passed. 
+ *
+ * Also, this is the greatest number of backreferenced subexpressions
+ * allowed in a pattern being matched without caller-supplied registers.
+ */
+#ifndef RE_NREGS
+#define RE_NREGS 30
+#endif
+
+extern int rx_cache_bound;
+extern char rx_version_string[];
+
+
+
+
+#ifdef RX_WANT_RX_DEFS
+
+/* This is decls to the interesting subsystems and lower layers
+ * of rx.  Everything which doesn't have a public counterpart in 
+ * regex.c is declared here.
+ */
+
+
+#ifdef __STDC__
+typedef void (*rx_hash_freefn) (struct rx_hash_item * it);
+#else /* ndef __STDC__ */
+typedef void (*rx_hash_freefn) ();
+#endif /* ndef __STDC__ */
+
+
+
+
+
+#ifdef __STDC__
+RX_DECL int rx_bitset_is_equal (int size, rx_Bitset a, rx_Bitset b);
+RX_DECL int rx_bitset_is_subset (int size, rx_Bitset a, rx_Bitset b);
+RX_DECL int rx_bitset_empty (int size, rx_Bitset set);
+RX_DECL void rx_bitset_null (int size, rx_Bitset b);
+RX_DECL void rx_bitset_universe (int size, rx_Bitset b);
+RX_DECL void rx_bitset_complement (int size, rx_Bitset b);
+RX_DECL void rx_bitset_assign (int size, rx_Bitset a, rx_Bitset b);
+RX_DECL void rx_bitset_union (int size, rx_Bitset a, rx_Bitset b);
+RX_DECL void rx_bitset_intersection (int size,
+				     rx_Bitset a, rx_Bitset b);
+RX_DECL void rx_bitset_difference (int size, rx_Bitset a, rx_Bitset b);
+RX_DECL void rx_bitset_revdifference (int size,
+				      rx_Bitset a, rx_Bitset b);
+RX_DECL void rx_bitset_xor (int size, rx_Bitset a, rx_Bitset b);
+RX_DECL unsigned long rx_bitset_hash (int size, rx_Bitset b);
+RX_DECL struct rx_hash_item * rx_hash_find (struct rx_hash * table,
+					    unsigned long hash,
+					    void * value,
+					    struct rx_hash_rules * rules);
+RX_DECL struct rx_hash_item * rx_hash_store (struct rx_hash * table,
+					     unsigned long hash,
+					     void * value,
+					     struct rx_hash_rules * rules);
+RX_DECL void rx_hash_free (struct rx_hash_item * it, struct rx_hash_rules * rules);
+RX_DECL void rx_free_hash_table (struct rx_hash * tab, rx_hash_freefn freefn,
+				 struct rx_hash_rules * rules);
+RX_DECL rx_Bitset rx_cset (struct rx *rx);
+RX_DECL rx_Bitset rx_copy_cset (struct rx *rx, rx_Bitset a);
+RX_DECL void rx_free_cset (struct rx * rx, rx_Bitset c);
+RX_DECL struct rexp_node * rexp_node (struct rx *rx,
+				      enum rexp_node_type type);
+RX_DECL struct rexp_node * rx_mk_r_cset (struct rx * rx,
+					 rx_Bitset b);
+RX_DECL struct rexp_node * rx_mk_r_concat (struct rx * rx,
+					   struct rexp_node * a,
+					   struct rexp_node * b);
+RX_DECL struct rexp_node * rx_mk_r_alternate (struct rx * rx,
+					      struct rexp_node * a,
+					      struct rexp_node * b);
+RX_DECL struct rexp_node * rx_mk_r_opt (struct rx * rx,
+					struct rexp_node * a);
+RX_DECL struct rexp_node * rx_mk_r_star (struct rx * rx,
+					 struct rexp_node * a);
+RX_DECL struct rexp_node * rx_mk_r_2phase_star (struct rx * rx,
+						struct rexp_node * a,
+						struct rexp_node * b);
+RX_DECL struct rexp_node * rx_mk_r_side_effect (struct rx * rx,
+						rx_side_effect a);
+RX_DECL struct rexp_node * rx_mk_r_data  (struct rx * rx,
+					  void * a);
+RX_DECL void rx_free_rexp (struct rx * rx, struct rexp_node * node);
+RX_DECL struct rexp_node * rx_copy_rexp (struct rx *rx,
+					 struct rexp_node *node);
+RX_DECL struct rx_nfa_state * rx_nfa_state (struct rx *rx);
+RX_DECL void rx_free_nfa_state (struct rx_nfa_state * n);
+RX_DECL struct rx_nfa_state * rx_id_to_nfa_state (struct rx * rx,
+						  int id);
+RX_DECL struct rx_nfa_edge * rx_nfa_edge (struct rx *rx,
+					  enum rx_nfa_etype type,
+					  struct rx_nfa_state *start,
+					  struct rx_nfa_state *dest);
+RX_DECL void rx_free_nfa_edge (struct rx_nfa_edge * e);
+RX_DECL void rx_free_nfa (struct rx *rx);
+RX_DECL int rx_build_nfa (struct rx *rx,
+			  struct rexp_node *rexp,
+			  struct rx_nfa_state **start,
+			  struct rx_nfa_state **end);
+RX_DECL void rx_name_nfa_states (struct rx *rx);
+RX_DECL int rx_eclose_nfa (struct rx *rx);
+RX_DECL void rx_delete_epsilon_transitions (struct rx *rx);
+RX_DECL int rx_compactify_nfa (struct rx *rx,
+			       void **mem, unsigned long *size);
+RX_DECL void rx_release_superset (struct rx *rx,
+				  struct rx_superset *set);
+RX_DECL struct rx_superset * rx_superset_cons (struct rx * rx,
+					       struct rx_nfa_state *car, struct rx_superset *cdr);
+RX_DECL struct rx_superset * rx_superstate_eclosure_union
+  (struct rx * rx, struct rx_superset *set, struct rx_nfa_state_set *ecl);
+RX_DECL struct rx_superstate * rx_superstate (struct rx *rx,
+					      struct rx_superset *set);
+RX_DECL struct rx_inx * rx_handle_cache_miss
+  (struct rx *rx, struct rx_superstate *super, unsigned char chr, void *data);
+RX_DECL reg_errcode_t rx_compile (__const__ char *pattern, int size,
+				  reg_syntax_t syntax,
+				  struct re_pattern_buffer * rxb);
+RX_DECL void rx_blow_up_fastmap (struct re_pattern_buffer * rxb);
+#else /* STDC */
+RX_DECL int rx_bitset_is_equal ();
+RX_DECL int rx_bitset_is_subset ();
+RX_DECL int rx_bitset_empty ();
+RX_DECL void rx_bitset_null ();
+RX_DECL void rx_bitset_universe ();
+RX_DECL void rx_bitset_complement ();
+RX_DECL void rx_bitset_assign ();
+RX_DECL void rx_bitset_union ();
+RX_DECL void rx_bitset_intersection ();
+RX_DECL void rx_bitset_difference ();
+RX_DECL void rx_bitset_revdifference ();
+RX_DECL void rx_bitset_xor ();
+RX_DECL unsigned long rx_bitset_hash ();
+RX_DECL struct rx_hash_item * rx_hash_find ();
+RX_DECL struct rx_hash_item * rx_hash_store ();
+RX_DECL void rx_hash_free ();
+RX_DECL void rx_free_hash_table ();
+RX_DECL rx_Bitset rx_cset ();
+RX_DECL rx_Bitset rx_copy_cset ();
+RX_DECL void rx_free_cset ();
+RX_DECL struct rexp_node * rexp_node ();
+RX_DECL struct rexp_node * rx_mk_r_cset ();
+RX_DECL struct rexp_node * rx_mk_r_concat ();
+RX_DECL struct rexp_node * rx_mk_r_alternate ();
+RX_DECL struct rexp_node * rx_mk_r_opt ();
+RX_DECL struct rexp_node * rx_mk_r_star ();
+RX_DECL struct rexp_node * rx_mk_r_2phase_star ();
+RX_DECL struct rexp_node * rx_mk_r_side_effect ();
+RX_DECL struct rexp_node * rx_mk_r_data  ();
+RX_DECL void rx_free_rexp ();
+RX_DECL struct rexp_node * rx_copy_rexp ();
+RX_DECL struct rx_nfa_state * rx_nfa_state ();
+RX_DECL void rx_free_nfa_state ();
+RX_DECL struct rx_nfa_state * rx_id_to_nfa_state ();
+RX_DECL struct rx_nfa_edge * rx_nfa_edge ();
+RX_DECL void rx_free_nfa_edge ();
+RX_DECL void rx_free_nfa ();
+RX_DECL int rx_build_nfa ();
+RX_DECL void rx_name_nfa_states ();
+RX_DECL int rx_eclose_nfa ();
+RX_DECL void rx_delete_epsilon_transitions ();
+RX_DECL int rx_compactify_nfa ();
+RX_DECL void rx_release_superset ();
+RX_DECL struct rx_superset * rx_superset_cons ();
+RX_DECL struct rx_superset * rx_superstate_eclosure_union ();
+RX_DECL struct rx_superstate * rx_superstate ();
+RX_DECL struct rx_inx * rx_handle_cache_miss ();
+RX_DECL reg_errcode_t rx_compile ();
+RX_DECL void rx_blow_up_fastmap ();
+#endif /* STDC */
+
+
+#endif /* RX_WANT_RX_DEFS */
+
+
+
+
+#ifdef __STDC__
+extern int re_search_2 (struct re_pattern_buffer *rxb,
+			__const__ char * string1, int size1,
+			__const__ char * string2, int size2,
+			int startpos, int range,
+			struct re_registers *regs,
+			int stop);
+extern int re_search (struct re_pattern_buffer * rxb, __const__ char *string,
+		      int size, int startpos, int range,
+		      struct re_registers *regs);
+extern int re_match_2 (struct re_pattern_buffer * rxb,
+		       __const__ char * string1, int size1,
+		       __const__ char * string2, int size2,
+		       int pos, struct re_registers *regs, int stop);
+extern int re_match (struct re_pattern_buffer * rxb,
+		     __const__ char * string,
+		     int size, int pos,
+		     struct re_registers *regs);
+extern reg_syntax_t re_set_syntax (reg_syntax_t syntax);
+extern void re_set_registers (struct re_pattern_buffer *bufp,
+			      struct re_registers *regs,
+			      unsigned num_regs,
+			      regoff_t * starts, regoff_t * ends);
+extern __const__ char * re_compile_pattern (__const__ char *pattern,
+					int length,
+					struct re_pattern_buffer * rxb);
+extern int re_compile_fastmap (struct re_pattern_buffer * rxb);
+extern char * re_comp (__const__ char *s);
+extern int re_exec (__const__ char *s);
+extern int regcomp (regex_t * preg, __const__ char * pattern, int cflags);
+extern int regexec (__const__ regex_t *preg, __const__ char *string,
+		    size_t nmatch, regmatch_t pmatch[],
+		    int eflags);
+extern size_t regerror (int errcode, __const__ regex_t *preg,
+			char *errbuf, size_t errbuf_size);
+extern void regfree (regex_t *preg);
+
+#else /* STDC */
+extern int re_search_2 ();
+extern int re_search ();
+extern int re_match_2 ();
+extern int re_match ();
+extern reg_syntax_t re_set_syntax ();
+extern void re_set_registers ();
+extern __const__ char * re_compile_pattern ();
+extern int re_compile_fastmap ();
+extern char * re_comp ();
+extern int re_exec ();
+extern int regcomp ();
+extern int regexec ();
+extern size_t regerror ();
+extern void regfree ();
+
+#endif /* STDC */
+
+
+
+
+#ifdef RX_WANT_RX_DEFS
+
+struct rx_counter_frame
+{
+  int tag;
+  int val;
+  struct rx_counter_frame * inherited_from; /* If this is a copy. */
+  struct rx_counter_frame * cdr;
+};
+
+struct rx_backtrack_frame
+{
+  char * counter_stack_sp;
+
+  /* A frame is used to save the matchers state when it crosses a 
+   * backtracking point.  The `stk_' fields correspond to variables
+   * in re_search_2 (just strip off thes `stk_').  They are documented
+   * tere.
+   */
+  struct rx_superstate * stk_super;
+  unsigned int stk_c;
+  struct rx_string_position stk_test_pos;
+  int stk_last_l;
+  int stk_last_r;
+  int stk_test_ret;
+
+  /* This is the list of options left to explore at the backtrack
+   * point for which this frame was created. 
+   */
+  struct rx_distinct_future * df;
+  struct rx_distinct_future * first_df;
+
+#ifdef RX_DEBUG
+   int stk_line_no;
+#endif
+};
+
+struct rx_stack_chunk
+{
+  struct rx_stack_chunk * next_chunk;
+  int bytes_left;
+  char * sp;
+};
+
+enum rx_outer_entry
+{
+  rx_outer_start,
+  rx_outer_fastmap,
+  rx_outer_test,
+  rx_outer_restore_pos
+};
+
+enum rx_fastmap_return
+{
+  rx_fastmap_continuation,
+  rx_fastmap_error,
+  rx_fastmap_ok,
+  rx_fastmap_fail
+};
+
+enum rx_fastmap_entry
+{
+  rx_fastmap_start,
+  rx_fastmap_string_break
+};
+
+enum rx_test_return
+{
+  rx_test_continuation,
+  rx_test_error,
+  rx_test_fail,
+  rx_test_ok
+};
+
+enum rx_test_internal_return
+{
+  rx_test_internal_error,
+  rx_test_found_first,
+  rx_test_line_finished
+};
+
+enum rx_test_match_entry
+{
+  rx_test_start,
+  rx_test_cache_hit_loop,
+  rx_test_backreference_check,
+  rx_test_backtrack_return
+};
+
+struct rx_search_state
+{
+  /* Two groups of registers are kept.  The group with the register state
+   * of the current test match, and the group that holds the state at the end
+   * of the best known match, if any.
+   *
+   * For some patterns, there may also be registers saved on the stack.
+   */
+  unsigned num_regs;		/* Includes an element for register zero. */
+  regoff_t * lparen;		/* scratch space for register returns */
+  regoff_t * rparen;
+  regoff_t * best_lpspace;	/* in case the user doesn't want these */
+  regoff_t * best_rpspace;	/* values, we still need space to store
+				 * them.  Normally, this memoryis unused
+				 * and the space pointed to by REGS is 
+				 * used instead.
+				 */
+  
+  int last_l;			/* Highest index of a valid lparen. */
+  int last_r;			/* It's dual. */
+  
+  int * best_lparen;		/* This contains the best known register */
+  int * best_rparen;		/* assignments. 
+				 * This may point to the same mem as
+				 * best_lpspace, or it might point to memory
+				 * passed by the caller.
+				 */
+  int best_last_l;		/* best_last_l:best_lparen::last_l:lparen */
+  int best_last_r;
+
+
+  unsigned char * translate;  
+
+  struct rx_string_position outer_pos;
+
+  struct rx_superstate * start_super;
+  int nfa_choice;
+  int first_found;		/* If true, return after finding any match. */
+  int ret_val;
+
+  /* For continuations... */
+  enum rx_outer_entry outer_search_resume_pt;
+  struct re_pattern_buffer * saved_rxb;
+  int saved_startpos;
+  int saved_range;
+  int saved_stop;
+  int saved_total_size;
+  rx_get_burst_fn saved_get_burst;
+  rx_back_check_fn saved_back_check;
+  struct re_registers * saved_regs;
+  
+  /**
+   ** state for fastmap
+   **/
+  char * fastmap;
+  int fastmap_chr;
+  int fastmap_val;
+
+  /* for continuations in the fastmap procedure: */
+  enum rx_fastmap_entry fastmap_resume_pt;
+
+  /**
+   ** state for test_match 
+   **/
+
+  /* The current superNFA position of the matcher. */
+  struct rx_superstate * super;
+  
+  /* The matcher interprets a series of instruction frames.
+   * This is the `instruction counter' for the interpretation.
+   */
+  struct rx_inx * ifr;
+  
+  /* We insert a ghost character in the string to prime
+   * the nfa.  test_pos.pos, test_pos.str_half, and test_pos.end_half
+   * keep track of the test-match position and string-half.
+   */
+  unsigned char c;
+  
+  /* Position within the string. */
+  struct rx_string_position test_pos;
+
+  struct rx_stack_chunk * counter_stack;
+  struct rx_stack_chunk * backtrack_stack;
+  int backtrack_frame_bytes;
+  int chunk_bytes;
+  struct rx_stack_chunk * free_chunks;
+
+  /* To return from this function, set test_ret and 
+   * `goto test_do_return'.
+   *
+   * Possible return values are:
+   *     1   --- end of string while the superNFA is still going
+   *     0   --- internal error (out of memory)
+   *	-1   --- search completed by reaching the superNFA fail state
+   *    -2   --- a match was found, maybe not the longest.
+   *
+   * When the search is complete (-1), best_last_r indicates whether
+   * a match was found.
+   *
+   * -2 is return only if search_state.first_found is non-zero.
+   *
+   * if search_state.first_found is non-zero, a return of -1 indicates no match,
+   * otherwise, best_last_r has to be checked.
+   */
+  int test_ret;
+
+  int could_have_continued;
+  
+#ifdef RX_DEBUG
+  int backtrack_depth;
+  /* There is a search tree with every node as set of deterministic
+   * transitions in the super nfa.  For every branch of a 
+   * backtrack point is an edge in the tree.
+   * This counts up a pre-order of nodes in that tree.
+   * It's saved on the search stack and printed when debugging. 
+   */
+  int line_no;
+  int lines_found;
+#endif
+
+
+  /* For continuations within the match tester */
+  enum rx_test_match_entry test_match_resume_pt;
+  struct rx_inx * saved_next_tr_table;
+  struct rx_inx * saved_this_tr_table;
+  int saved_reg;
+  struct rx_backtrack_frame * saved_bf;
+  
+};
+
+
+
+extern char rx_slowmap[];
+extern unsigned char rx_id_translation[];
+
+static __inline__ void
+init_fastmap (rxb, search_state)
+     struct re_pattern_buffer * rxb;
+     struct rx_search_state * search_state;
+{
+  search_state->fastmap = (rxb->fastmap
+			   ? (char *)rxb->fastmap
+			   : (char *)rx_slowmap);
+  /* Update the fastmap now if not correct already. 
+   * When the regexp was compiled, the fastmap was computed
+   * and stored in a bitset.  This expands the bitset into a
+   * character array containing 1s and 0s.
+   */
+  if ((search_state->fastmap == rxb->fastmap) && !rxb->fastmap_accurate)
+    rx_blow_up_fastmap (rxb);
+  search_state->fastmap_chr = -1;
+  search_state->fastmap_val = 0;
+  search_state->fastmap_resume_pt = rx_fastmap_start;
+}
+
+static __inline__ void
+uninit_fastmap (rxb, search_state)
+     struct re_pattern_buffer * rxb;
+     struct rx_search_state * search_state;
+{
+  /* Unset the fastmap sentinel */
+  if (search_state->fastmap_chr >= 0)
+    search_state->fastmap[search_state->fastmap_chr]
+      = search_state->fastmap_val;
+}
+
+static __inline__ int
+fastmap_search (rxb, stop, get_burst, app_closure, search_state)
+     struct re_pattern_buffer * rxb;
+     int stop;
+     rx_get_burst_fn get_burst;
+     void * app_closure;
+     struct rx_search_state * search_state;
+{
+  enum rx_fastmap_entry pc;
+
+  if (0)
+    {
+    return_continuation:
+      search_state->fastmap_resume_pt = pc;
+      return rx_fastmap_continuation;
+    }
+
+  pc = search_state->fastmap_resume_pt;
+
+  switch (pc)
+    {
+    default:
+      return rx_fastmap_error;
+    case rx_fastmap_start:
+    init_fastmap_sentinal:
+      /* For the sake of fast fastmapping, set a sentinal in the fastmap.
+       * This sentinal will trap the fastmap loop when it reaches the last
+       * valid character in a string half.
+       *
+       * This must be reset when the fastmap/search loop crosses a string 
+       * boundry, and before returning to the caller.  So sometimes,
+       * the fastmap loop is restarted with `continue', othertimes by
+       * `goto init_fastmap_sentinal'.
+       */
+      if (search_state->outer_pos.size)
+	{
+	  search_state->fastmap_chr = ((search_state->outer_pos.search_direction == 1)
+				       ? *(search_state->outer_pos.end - 1)
+				       : *search_state->outer_pos.string);
+	  search_state->fastmap_val
+	    = search_state->fastmap[search_state->fastmap_chr];
+	  search_state->fastmap[search_state->fastmap_chr] = 1;
+	}
+      else
+	{
+	  search_state->fastmap_chr = -1;
+	  search_state->fastmap_val = 0;
+	}
+      
+      if (search_state->outer_pos.pos >= search_state->outer_pos.end)
+	goto fastmap_hit_bound;
+      else
+	{
+	  if (search_state->outer_pos.search_direction == 1)
+	    {
+	      if (search_state->fastmap_val)
+		{
+		  for (;;)
+		    {
+		      while (!search_state->fastmap[*search_state->outer_pos.pos])
+			++search_state->outer_pos.pos;
+		      return rx_fastmap_ok;
+		    }
+		}
+	      else
+		{
+		  for (;;)
+		    {
+		      while (!search_state->fastmap[*search_state->outer_pos.pos])
+			++search_state->outer_pos.pos;
+		      if (*search_state->outer_pos.pos != search_state->fastmap_chr)
+			return rx_fastmap_ok;
+		      else 
+			{
+			  ++search_state->outer_pos.pos;
+			  if (search_state->outer_pos.pos == search_state->outer_pos.end)
+			    goto fastmap_hit_bound;
+			}
+		    }
+		}
+	    }
+	  else
+	    {
+	      __const__ unsigned char * bound;
+	      bound = search_state->outer_pos.string - 1;
+	      if (search_state->fastmap_val)
+		{
+		  for (;;)
+		    {
+		      while (!search_state->fastmap[*search_state->outer_pos.pos])
+			--search_state->outer_pos.pos;
+		      return rx_fastmap_ok;
+		    }
+		}
+	      else
+		{
+		  for (;;)
+		    {
+		      while (!search_state->fastmap[*search_state->outer_pos.pos])
+			--search_state->outer_pos.pos;
+		      if ((*search_state->outer_pos.pos != search_state->fastmap_chr) || search_state->fastmap_val)
+			return rx_fastmap_ok;
+		      else 
+			{
+			  --search_state->outer_pos.pos;
+			  if (search_state->outer_pos.pos == bound)
+			    goto fastmap_hit_bound;
+			}
+		    }
+		}
+	    }
+	}
+      
+    case rx_fastmap_string_break:
+    fastmap_hit_bound:
+      {
+	/* If we hit a bound, it may be time to fetch another burst
+	 * of string, or it may be time to return a continuation to 
+ 	 * the caller, or it might be time to fail.
+	 */
+
+	int burst_state;
+	burst_state = get_burst (&search_state->outer_pos, app_closure, stop);
+	switch (burst_state)
+	  {
+	  default:
+	  case rx_get_burst_error:
+	    return rx_fastmap_error;
+	  case rx_get_burst_continuation:
+	    {
+	      pc = rx_fastmap_string_break;
+	      goto return_continuation;
+	    }
+	  case rx_get_burst_ok:
+	    goto init_fastmap_sentinal;
+	  case rx_get_burst_no_more:
+	    /* ...not a string split, simply no more string. 
+	     *
+	     * When searching backward, running out of string
+	     * is reason to quit.
+	     *
+	     * When searching forward, we allow the possibility
+	     * of an (empty) match after the last character in the
+	     * virtual string.  So, fall through to the matcher
+	     */
+	    return (  (search_state->outer_pos.search_direction == 1)
+		    ? rx_fastmap_ok
+		    : rx_fastmap_fail);
+	  }
+      }
+    }
+
+}
+
+
+
+
+#ifdef emacs
+/* The `emacs' switch turns on certain matching commands
+ * that make sense only in Emacs. 
+ */
+#include "sysfuncs.h"
+#include "lisp.h"
+#include "buffer.h"
+#include "syntax.h"
+#endif /* emacs */
+
+/* Setting RX_MEMDBUG is useful if you have dbmalloc.  Maybe with similar
+ * packages too.
+ */
+#ifdef RX_MEMDBUG
+#include <malloc.h>
+#endif /* RX_RX_MEMDBUG */
+
+/* We used to test for `BSTRING' here, but only GCC and Emacs define
+ * `BSTRING', as far as I know, and neither of them use this code.  
+ */
+#if HAVE_STRING_H || STDC_HEADERS
+#include <string.h>
+
+#ifndef bcmp
+#define bcmp(s1, s2, n)	memcmp ((s1), (s2), (n))
+#endif
+
+#ifndef bcopy
+#define bcopy(s, d, n)	memcpy ((d), (s), (n))
+#endif
+
+#ifndef bzero
+#define bzero(s, n)	memset ((s), 0, (n))
+#endif
+
+#else /*  HAVE_STRING_H || STDC_HEADERS */
+#include <strings.h>
+#endif   /* not (HAVE_STRING_H || STDC_HEADERS) */
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else /* not STDC_HEADERS */
+char *malloc ();
+char *realloc ();
+#endif /* not STDC_HEADERS */
+
+
+
+
+
+/* How many characters in the character set.  */
+#define CHAR_SET_SIZE (1 << CHARBITS)
+
+#ifndef emacs
+/* Define the syntax basics for \<, \>, etc.
+ * This must be nonzero for the wordchar and notwordchar pattern
+ * commands in re_match_2.
+ */
+#ifndef Sword 
+#define Sword 1
+#endif
+#define SYNTAX(c) re_syntax_table[c]
+#ifdef SYNTAX_TABLE
+extern char *re_syntax_table;
+#else
+RX_DECL char re_syntax_table[CHAR_SET_SIZE];
+#endif
+#endif /* not emacs */
+
+
+/* Test if at very beginning or at very end of the virtual concatenation
+ *  of `string1' and `string2'.  If only one string, it's `string2'.  
+ */
+
+#define AT_STRINGS_BEG() \
+  (   -1		 \
+   == ((search_state.test_pos.pos - search_state.test_pos.string) \
+       + search_state.test_pos.offset))
+
+#define AT_STRINGS_END() \
+  (   (total_size - 1)	 \
+   == ((search_state.test_pos.pos - search_state.test_pos.string) \
+       + search_state.test_pos.offset))
+
+
+/* Test if POS + 1 points to a character which is word-constituent.  We have
+ * two special cases to check for: if past the end of string1, look at
+ * the first character in string2; and if before the beginning of
+ * string2, look at the last character in string1.
+ *
+ * Assumes `string1' exists, so use in conjunction with AT_STRINGS_BEG ().  
+ */
+#define LETTER_P(POS,OFF)						\
+  (   SYNTAX (fetch_char(POS, OFF, app_closure, stop))			\
+   == Sword)
+
+/* Test if the character at D and the one after D differ with respect
+ * to being word-constituent.  
+ */
+#define AT_WORD_BOUNDARY(d)						\
+  (AT_STRINGS_BEG () || AT_STRINGS_END () || LETTER_P (d,0) != LETTER_P (d, 1))
+
+
+#ifdef RX_SUPPORT_CONTINUATIONS
+#define RX_STACK_ALLOC(BYTES) malloc(BYTES)
+#define RX_STACK_FREE(MEM) free(MEM)
+#else
+#define RX_STACK_ALLOC(BYTES) alloca(BYTES)
+#define RX_STACK_FREE(MEM) \
+      ((struct rx_stack_chunk *)MEM)->next_chunk = search_state.free_chunks; \
+      search_state.free_chunks = ((struct rx_stack_chunk *)MEM);
+
+#endif
+
+#define PUSH(CHUNK_VAR,BYTES)   \
+  if (!CHUNK_VAR || (CHUNK_VAR->bytes_left < (BYTES)))  \
+    {					\
+      struct rx_stack_chunk * new_chunk;	\
+      if (search_state.free_chunks)			\
+	{				\
+	  new_chunk = search_state.free_chunks;	\
+	  search_state.free_chunks = search_state.free_chunks->next_chunk; \
+	}				\
+      else				\
+	{				\
+	  new_chunk = (struct rx_stack_chunk *)RX_STACK_ALLOC(search_state.chunk_bytes); \
+	  if (!new_chunk)		\
+	    {				\
+	      search_state.ret_val = 0;		\
+	      goto test_do_return;	\
+	    }				\
+	}				\
+      new_chunk->sp = (char *)new_chunk + sizeof (struct rx_stack_chunk); \
+      new_chunk->bytes_left = (search_state.chunk_bytes \
+			       - (BYTES) \
+			       - sizeof (struct rx_stack_chunk)); \
+      new_chunk->next_chunk = CHUNK_VAR; \
+      CHUNK_VAR = new_chunk;		\
+    } \
+  else \
+    (CHUNK_VAR->sp += (BYTES)), (CHUNK_VAR->bytes_left -= (BYTES))
+
+#define POP(CHUNK_VAR,BYTES) \
+  if (CHUNK_VAR->sp == ((char *)CHUNK_VAR + sizeof(*CHUNK_VAR))) \
+    { \
+      struct rx_stack_chunk * new_chunk = CHUNK_VAR->next_chunk; \
+      RX_STACK_FREE(CHUNK_VAR); \
+      CHUNK_VAR = new_chunk; \
+    } \
+  else \
+    (CHUNK_VAR->sp -= BYTES), (CHUNK_VAR->bytes_left += BYTES)
+
+
+
+#define SRCH_TRANSLATE(C)  search_state.translate[(unsigned char) (C)]
+
+
+
+
+
+#ifdef __STDC__
+RX_DECL __inline__ int
+rx_search  (struct re_pattern_buffer * rxb,
+	    int startpos,
+	    int range,
+	    int stop,
+	    int total_size,
+	    rx_get_burst_fn get_burst,
+	    rx_back_check_fn back_check,
+	    rx_fetch_char_fn fetch_char,
+	    void * app_closure,
+	    struct re_registers * regs,
+	    struct rx_search_state * resume_state,
+	    struct rx_search_state * save_state)
+#else
+RX_DECL __inline__ int
+rx_search  (rxb, startpos, range, stop, total_size,
+	    get_burst, back_check, fetch_char,
+	    app_closure, regs, resume_state, save_state)
+     struct re_pattern_buffer * rxb;
+     int startpos;
+     int range;
+     int stop;
+     int total_size;
+     rx_get_burst_fn get_burst;
+     rx_back_check_fn back_check;
+     rx_fetch_char_fn fetch_char;
+     void * app_closure;
+     struct re_registers * regs;
+     struct rx_search_state * resume_state;
+     struct rx_search_state * save_state;
+#endif
+{
+  int pc;
+  int test_state;
+  struct rx_search_state search_state;
+
+  search_state.free_chunks = 0;
+  if (!resume_state)
+    pc = rx_outer_start;
+  else
+    {
+      search_state = *resume_state;
+      regs = search_state.saved_regs;
+      rxb = search_state.saved_rxb;
+      startpos = search_state.saved_startpos;
+      range = search_state.saved_range;
+      stop = search_state.saved_stop;
+      total_size = search_state.saved_total_size;
+      get_burst = search_state.saved_get_burst;
+      back_check = search_state.saved_back_check;
+      pc = search_state.outer_search_resume_pt;
+      if (0)
+	{
+	return_continuation:
+	  if (save_state)
+	    {
+	      *save_state = search_state;
+	      save_state->saved_regs = regs;
+	      save_state->saved_rxb = rxb;
+	      save_state->saved_startpos = startpos;
+	      save_state->saved_range = range;
+	      save_state->saved_stop = stop;
+	      save_state->saved_total_size = total_size;
+	      save_state->saved_get_burst = get_burst;
+	      save_state->saved_back_check = back_check;
+	      save_state->outer_search_resume_pt = pc;
+	    }
+	  return rx_search_continuation;
+	}
+    }
+
+  switch (pc)
+    {
+    case rx_outer_start:
+      search_state.ret_val = rx_search_fail;
+      (  search_state.lparen
+       = search_state.rparen
+       = search_state.best_lpspace
+       = search_state.best_rpspace
+       = 0);
+      
+      /* figure the number of registers we may need for use in backreferences.
+       * the number here includes an element for register zero.  
+       */
+      search_state.num_regs = rxb->re_nsub + 1;
+      
+      
+      /* check for out-of-range startpos.  */
+      if ((startpos < 0) || (startpos > total_size))
+	return rx_search_fail;
+      
+      /* fix up range if it might eventually take us outside the string. */
+      {
+	int endpos;
+	endpos = startpos + range;
+	if (endpos < -1)
+	  range = (-1 - startpos);
+	else if (endpos > (total_size + 1))
+	  range = total_size - startpos;
+      }
+      
+      /* if the search isn't to be a backwards one, don't waste time in a
+       * long search for a pattern that says it is anchored.
+       */
+      if (rxb->begbuf_only && (range > 0))
+	{
+	  if (startpos > 0)
+	    return rx_search_fail;
+	  else
+	    range = 1;
+	}
+      
+      /* decide whether to use internal or user-provided reg buffers. */
+      if (!regs || rxb->no_sub)
+	{
+	  search_state.best_lpspace =
+	    (regoff_t *)REGEX_ALLOCATE (search_state.num_regs * sizeof(regoff_t));
+	  search_state.best_rpspace =
+	    (regoff_t *)REGEX_ALLOCATE (search_state.num_regs * sizeof(regoff_t));
+	  search_state.best_lparen = search_state.best_lpspace;
+	  search_state.best_rparen = search_state.best_rpspace;
+	}
+      else
+	{	
+	  /* have the register data arrays been allocated?  */
+	  if (rxb->regs_allocated == REGS_UNALLOCATED)
+	    { /* no.  so allocate them with malloc.  we need one
+		 extra element beyond `search_state.num_regs' for the `-1' marker
+		 gnu code uses.  */
+	      regs->num_regs = MAX (RE_NREGS, rxb->re_nsub + 1);
+	      regs->start = ((regoff_t *)
+			     malloc (regs->num_regs * sizeof ( regoff_t)));
+	      regs->end = ((regoff_t *)
+			   malloc (regs->num_regs * sizeof ( regoff_t)));
+	      if (regs->start == 0 || regs->end == 0)
+		return rx_search_error;
+	      rxb->regs_allocated = REGS_REALLOCATE;
+	    }
+	  else if (rxb->regs_allocated == REGS_REALLOCATE)
+	    { /* yes.  if we need more elements than were already
+		 allocated, reallocate them.  if we need fewer, just
+		 leave it alone.  */
+	      if (regs->num_regs < search_state.num_regs + 1)
+		{
+		  regs->num_regs = search_state.num_regs + 1;
+		  regs->start = ((regoff_t *)
+				 realloc (regs->start,
+					  regs->num_regs * sizeof (regoff_t)));
+		  regs->end = ((regoff_t *)
+			       realloc (regs->end,
+					regs->num_regs * sizeof ( regoff_t)));
+		  if (regs->start == 0 || regs->end == 0)
+		    return rx_search_error;
+		}
+	    }
+	  else if (rxb->regs_allocated != REGS_FIXED)
+	    return rx_search_error;
+	  
+	  if (regs->num_regs < search_state.num_regs + 1)
+	    {
+	      search_state.best_lpspace =
+		((regoff_t *)
+		 REGEX_ALLOCATE (search_state.num_regs * sizeof(regoff_t)));
+	      search_state.best_rpspace =
+		((regoff_t *)
+		 REGEX_ALLOCATE (search_state.num_regs * sizeof(regoff_t)));
+	      search_state.best_lparen = search_state.best_lpspace;
+	      search_state.best_rparen = search_state.best_rpspace;
+	    }
+	  else
+	    {
+	      search_state.best_lparen = regs->start;
+	      search_state.best_rparen = regs->end;
+	    }
+	}
+      
+      search_state.lparen =
+	(regoff_t *) REGEX_ALLOCATE (search_state.num_regs * sizeof(regoff_t));
+      search_state.rparen =
+	(regoff_t *) REGEX_ALLOCATE (search_state.num_regs * sizeof(regoff_t)); 
+      
+      if (! (   search_state.best_rparen
+	     && search_state.best_lparen
+	     && search_state.lparen && search_state.rparen))
+	return rx_search_error;
+      
+      search_state.best_last_l = search_state.best_last_r = -1;
+      
+      search_state.translate = (rxb->translate
+				? rxb->translate
+				: rx_id_translation);
+      
+      
+      
+      /*
+       * two nfa's were compiled.  
+       * `0' is complete.
+       * `1' faster but gets registers wrong and ends too soon.
+       */
+      search_state.nfa_choice = (regs && !rxb->least_subs) ? '\0' : '\1';
+      
+      /* we have the option to look for the best match or the first
+       * one we can find.  if the user isn't asking for register information,
+       * we don't need to find the best match.
+       */
+      search_state.first_found = !regs;
+      
+      if (range >= 0)
+	{
+	  search_state.outer_pos.search_end = startpos + range;
+	  search_state.outer_pos.search_direction = 1;
+	}
+      else
+	{
+	  search_state.outer_pos.search_end = startpos + range;
+	  search_state.outer_pos.search_direction = -1;
+	}
+      
+      /* the vacuous search always turns up nothing. */
+      if ((search_state.outer_pos.search_direction == 1)
+	  ? (startpos > search_state.outer_pos.search_end)
+	  : (startpos < search_state.outer_pos.search_end))
+	return rx_search_fail;
+      
+      /* now we build the starting state of the supernfa. */
+      {
+	struct rx_superset * start_contents;
+	struct rx_nfa_state_set * start_nfa_set;
+	
+	/* we presume here that the nfa start state has only one
+	 * possible future with no side effects.  
+	 */
+	start_nfa_set = rxb->start->futures->destset;
+	if (   rxb->rx.start_set
+	    && (rxb->rx.start_set->starts_for == &rxb->rx))
+	  start_contents = rxb->rx.start_set;
+	else
+	  {
+	    start_contents =
+	      rx_superstate_eclosure_union (&rxb->rx,
+					    rx_superset_cons (&rxb->rx, 0, 0),
+					    start_nfa_set);
+	    
+	    if (!start_contents)
+	      return rx_search_fail;
+	    
+	    start_contents->starts_for = &rxb->rx;
+	    rxb->rx.start_set = start_contents;
+	  }
+	if (   start_contents->superstate
+	    && (start_contents->superstate->rx_id == rxb->rx.rx_id))
+	  {
+	    search_state.start_super = start_contents->superstate;
+	    rx_lock_superstate (&rxb->rx, search_state.start_super);
+	  }
+	else
+	  {
+	    rx_protect_superset (&rxb->rx, start_contents);
+	    
+	    search_state.start_super = rx_superstate (&rxb->rx, start_contents);
+	    if (!search_state.start_super)
+	      return rx_search_fail;
+	    rx_lock_superstate (&rxb->rx, search_state.start_super);
+	    rx_release_superset (&rxb->rx, start_contents);
+	  }
+      }
+      
+      
+      /* The outer_pos tracks the position within the strings
+       * as seen by loop that calls fastmap_search.
+       *
+       * The caller supplied get_burst function actually 
+       * gives us pointers to chars.
+       * 
+       * Communication with the get_burst function is through an
+       * rx_string_position structure.  Here, the structure for
+       * outer_pos is initialized.   It is set to point to the
+       * NULL string, at an offset of STARTPOS.  STARTPOS is out
+       * of range of the NULL string, so the first call to 
+       * getburst will patch up the rx_string_position to point
+       * to valid characters.
+       */
+
+      (  search_state.outer_pos.string
+       = search_state.outer_pos.end
+       = 0);
+
+      search_state.outer_pos.offset = 0;
+      search_state.outer_pos.size = 0;
+      search_state.outer_pos.pos = (unsigned char *)startpos;
+      init_fastmap (rxb, &search_state);
+
+      search_state.fastmap_resume_pt = rx_fastmap_start;
+    case rx_outer_fastmap:
+      /* do { */
+    pseudo_do:
+      {
+	{
+	  int fastmap_state;
+	  fastmap_state = fastmap_search (rxb, stop, get_burst, app_closure,
+					  &search_state);
+	  switch (fastmap_state)
+	    {
+	    case rx_fastmap_continuation:
+	      pc = rx_outer_fastmap;
+	      goto return_continuation;
+	    case rx_fastmap_fail:
+	      goto finish;
+	    case rx_fastmap_ok:
+	      break;
+	    }
+	}
+	
+	/* now the fastmap loop has brought us to a plausible 
+	 * starting point for a match.  so, it's time to run the
+	 * nfa and see if a match occured.
+	 */
+	startpos = (  search_state.outer_pos.pos
+		    - search_state.outer_pos.string
+		    + search_state.outer_pos.offset);
+/*|*/	if ((range > 0) && (startpos == search_state.outer_pos.search_end))
+/*|*/	  goto finish;
+      }
+
+      search_state.test_match_resume_pt = rx_test_start;
+      /* do interrupted for entry point... */
+    case rx_outer_test:
+      /* ...do continued */
+      {
+	goto test_match;
+      test_returns_to_search:
+	switch (test_state)
+	  {
+	  case rx_test_continuation:
+	    pc = rx_outer_test;
+	    goto return_continuation;
+	  case rx_test_error:
+	    search_state.ret_val = rx_search_error;
+	    goto finish;
+	  case rx_test_fail:
+	    break;
+	  case rx_test_ok:
+	    goto finish;
+	  }
+	search_state.outer_pos.pos += search_state.outer_pos.search_direction;
+	startpos += search_state.outer_pos.search_direction;
+#if 0
+/*|*/	if (search_state.test_pos.pos < search_state.test_pos.end)
+/*|*/	  break;
+#endif
+      }
+      /* do interrupted for entry point... */
+    case rx_outer_restore_pos:
+      {
+	int x;
+	x = get_burst (&search_state.outer_pos, app_closure, stop);
+	switch (x)
+	  {
+	  case rx_get_burst_continuation:
+	    pc = rx_outer_restore_pos;
+	    goto return_continuation;
+	  case rx_get_burst_error:
+	    search_state.ret_val = rx_search_error;
+	    goto finish;
+	  case rx_get_burst_no_more:
+	    if (rxb->can_match_empty)
+	      break;
+	    goto finish;
+	  case rx_get_burst_ok:
+	    break;
+	  }
+      } /* } while (...see below...) */
+
+      if ((search_state.outer_pos.search_direction == 1)
+	  ? (startpos < search_state.outer_pos.search_end)
+	  : (startpos > search_state.outer_pos.search_end))
+	goto pseudo_do;
+
+	
+    finish:
+      uninit_fastmap (rxb, &search_state);
+      if (search_state.start_super)
+	rx_unlock_superstate (&rxb->rx, search_state.start_super);
+      
+#ifdef regex_malloc
+      if (search_state.lparen) free (search_state.lparen);
+      if (search_state.rparen) free (search_state.rparen);
+      if (search_state.best_lpspace) free (search_state.best_lpspace);
+      if (search_state.best_rpspace) free (search_state.best_rpspace);
+#endif
+      return search_state.ret_val;
+    }
+
+
+ test_match:
+  {
+    enum rx_test_match_entry test_pc;
+    int inx;
+    test_pc = search_state.test_match_resume_pt;
+    if (test_pc == rx_test_start)
+      {
+#ifdef RX_DEBUG
+	search_state.backtrack_depth = 0;
+#endif
+	search_state.last_l = search_state.last_r = 0;
+	search_state.lparen[0] = startpos;
+	search_state.super = search_state.start_super;
+	search_state.c = search_state.nfa_choice;
+	search_state.test_pos.pos = search_state.outer_pos.pos - 1;    
+	search_state.test_pos.string = search_state.outer_pos.string;
+	search_state.test_pos.end = search_state.outer_pos.end;
+	search_state.test_pos.offset = search_state.outer_pos.offset;
+	search_state.test_pos.size = search_state.outer_pos.size;
+	search_state.test_pos.search_direction = 1;
+	search_state.counter_stack = 0;
+	search_state.backtrack_stack = 0;
+	search_state.backtrack_frame_bytes =
+	  (sizeof (struct rx_backtrack_frame)
+	   + (rxb->match_regs_on_stack
+	      ? sizeof (regoff_t) * (search_state.num_regs + 1) * 2
+	      : 0));
+	search_state.chunk_bytes = search_state.backtrack_frame_bytes * 64;
+	search_state.test_ret = rx_test_line_finished;
+	search_state.could_have_continued = 0;
+      }  
+    /* This is while (1)...except that the body of the loop is interrupted 
+     * by some alternative entry points.
+     */
+  pseudo_while_1:
+    switch (test_pc)
+      {
+      case rx_test_cache_hit_loop:
+	goto resume_continuation_1;
+      case rx_test_backreference_check:
+	goto resume_continuation_2;
+      case rx_test_backtrack_return:
+	goto resume_continuation_3;
+      case rx_test_start:
+#ifdef RX_DEBUG
+	/* There is a search tree with every node as set of deterministic
+	 * transitions in the super nfa.  For every branch of a 
+	 * backtrack point is an edge in the tree.
+	 * This counts up a pre-order of nodes in that tree.
+	 * It's saved on the search stack and printed when debugging. 
+	 */
+	search_state.line_no = 0;
+	search_state.lines_found = 0;
+#endif
+	
+      top_of_cycle:
+	/* A superstate is basicly a transition table, indexed by 
+	 * characters from the string being tested, and containing 
+	 * RX_INX (`instruction frame') structures.
+	 */
+	search_state.ifr = &search_state.super->transitions [search_state.c];
+	
+      recurse_test_match:
+	/* This is the point to which control is sent when the
+	 * test matcher `recurses'.  Before jumping here, some variables
+	 * need to be saved on the stack and the next instruction frame
+	 * has to be computed.
+	 */
+	
+      restart:
+	/* Some instructions don't advance the matcher, but just
+	 * carry out some side effects and fetch a new instruction.
+	 * To dispatch that new instruction, `goto restart'.
+	 */
+	
+	{
+	  struct rx_inx * next_tr_table;
+	  struct rx_inx * this_tr_table;
+	  /* The fastest route through the loop is when the instruction 
+	   * is RX_NEXT_CHAR.  This case is detected when SEARCH_STATE.IFR->DATA
+	   * is non-zero.  In that case, it points to the next
+	   * superstate. 
+	   *
+	   * This allows us to not bother fetching the bytecode.
+	   */
+	  next_tr_table = (struct rx_inx *)search_state.ifr->data;
+	  this_tr_table = search_state.super->transitions;
+	  while (next_tr_table)
+	    {
+#ifdef RX_DEBUG_0
+	      if (rx_debug_trace)
+		{
+		  struct rx_superset * setp;
+		  
+		  fprintf (stderr, "%d %d>> re_next_char @ %d (%d)",
+			   search_state.line_no,
+			   search_state.backtrack_depth,
+			   (search_state.test_pos.pos - search_state.test_pos.string
+			    + search_state.test_pos.offset), search_state.c);
+		  
+		  search_state.super =
+		    ((struct rx_superstate *)
+		     ((char *)this_tr_table
+		      - ((unsigned long)
+			 ((struct rx_superstate *)0)->transitions)));
+		  
+		  setp = search_state.super->contents;
+		  fprintf (stderr, "   superstet (rx=%d, &=%x: ",
+			   rxb->rx.rx_id, setp);
+		  while (setp)
+		    {
+		      fprintf (stderr, "%d ", setp->id);
+		      setp = setp->cdr;
+		    }
+		  fprintf (stderr, "\n");
+		}
+#endif
+	      this_tr_table = next_tr_table;
+	      ++search_state.test_pos.pos;
+	      if (search_state.test_pos.pos == search_state.test_pos.end)
+		{
+		  int burst_state;
+		try_burst_1:
+		  burst_state = get_burst (&search_state.test_pos,
+					   app_closure, stop);
+		  switch (burst_state)
+		    {
+		    case rx_get_burst_continuation:
+		      search_state.saved_this_tr_table = this_tr_table;
+		      search_state.saved_next_tr_table = next_tr_table;
+		      test_pc = rx_test_cache_hit_loop;
+		      goto test_return_continuation;
+		      
+		    resume_continuation_1:
+		      /* Continuation one jumps here to do its work: */
+		      search_state.saved_this_tr_table = this_tr_table;
+		      search_state.saved_next_tr_table = next_tr_table;
+		      goto try_burst_1;
+		      
+		    case rx_get_burst_ok:
+		      /* get_burst succeeded...keep going */
+		      break;
+		      
+		    case rx_get_burst_no_more:
+		      search_state.test_ret = rx_test_line_finished;
+		      search_state.could_have_continued = 1;
+		      goto test_do_return;
+		      
+		    case rx_get_burst_error:
+		      /* An error... */
+		      search_state.test_ret = rx_test_internal_error;
+		      goto test_do_return;
+		    }
+		}
+	      search_state.c = *search_state.test_pos.pos;
+	      search_state.ifr = this_tr_table + search_state.c;
+	      next_tr_table = (struct rx_inx *)search_state.ifr->data;
+	    } /* Fast loop through cached transition tables */
+	  
+	  /* Here when we ran out of cached next-char transitions. 
+	   * So, it will be necessary to do a more expensive
+	   * dispatch on the current instruction.  The superstate
+	   * pointer is allowed to become invalid during next-char
+	   * transitions -- now we must bring it up to date.
+	   */
+	  search_state.super =
+	    ((struct rx_superstate *)
+	     ((char *)this_tr_table
+	      - ((unsigned long)
+		 ((struct rx_superstate *)0)->transitions)));
+	}
+	
+	/* We've encountered an instruction other than next-char.
+	 * Dispatch that instruction:
+	 */
+	inx = (int)search_state.ifr->inx;
+#ifdef RX_DEBUG_0
+	if (rx_debug_trace)
+	  {
+	    struct rx_superset * setp = search_state.super->contents;
+	    
+	    fprintf (stderr, "%d %d>> %s @ %d (%d)", search_state.line_no,
+		     search_state.backtrack_depth,
+		     inx_names[inx],
+		     (search_state.test_pos.pos - search_state.test_pos.string
+		      + (test_pos.half == 0 ? 0 : size1)), search_state.c);
+	    
+	    fprintf (stderr, "   superstet (rx=%d, &=%x: ",
+		     rxb->rx.rx_id, setp);
+	    while (setp)
+	      {
+		fprintf (stderr, "%d ", setp->id);
+		setp = setp->cdr;
+	      }
+	    fprintf (stderr, "\n");
+	  }
+#endif
+	switch ((enum rx_opcode)inx)
+	  {
+	  case rx_do_side_effects:
+	    
+	    /*  RX_DO_SIDE_EFFECTS occurs when we cross epsilon 
+	     *  edges associated with parentheses, backreferencing, etc.
+	     */
+	    {
+	      struct rx_distinct_future * df =
+		(struct rx_distinct_future *)search_state.ifr->data_2;
+	      struct rx_se_list * el = df->effects;
+	      /* Side effects come in lists.  This walks down
+	       * a list, dispatching.
+	       */
+	      while (el)
+		{
+		  long effect;
+		  effect = (long)el->car;
+		  if (effect < 0)
+		    {
+#ifdef RX_DEBUG_0
+		      if (rx_debug_trace)
+			{
+			  struct rx_superset * setp = search_state.super->contents;
+			  
+			  fprintf (stderr, "....%d %d>> %s\n", search_state.line_no,
+				   search_state.backtrack_depth,
+				   efnames[-effect]);
+			}
+#endif
+		      switch ((enum re_side_effects) effect)
+
+			{
+			case re_se_pushback:
+			  search_state.ifr = &df->future_frame;
+			  if (!search_state.ifr->data)
+			    {
+			      struct rx_superstate * sup;
+			      sup = search_state.super;
+			      rx_lock_superstate (rx, sup);
+			      if (!rx_handle_cache_miss (&rxb->rx,
+							 search_state.super,
+							 search_state.c,
+							 (search_state.ifr
+							  ->data_2)))
+				{
+				  rx_unlock_superstate (rx, sup);
+				  search_state.test_ret = rx_test_internal_error;
+				  goto test_do_return;
+				}
+			      rx_unlock_superstate (rx, sup);
+			    }
+			  /* --search_state.test_pos.pos; */
+			  search_state.c = 't';
+			  search_state.super
+			    = ((struct rx_superstate *)
+			       ((char *)search_state.ifr->data
+				- (long)(((struct rx_superstate *)0)
+					 ->transitions)));
+			  goto top_of_cycle;
+			  break;
+			case re_se_push0:
+			  {
+			    struct rx_counter_frame * old_cf
+			      = (search_state.counter_stack
+				 ? ((struct rx_counter_frame *)
+				    search_state.counter_stack->sp)
+				 : 0);
+			    struct rx_counter_frame * cf;
+			    PUSH (search_state.counter_stack,
+				  sizeof (struct rx_counter_frame));
+			    cf = ((struct rx_counter_frame *)
+				  search_state.counter_stack->sp);
+			    cf->tag = re_se_iter;
+			    cf->val = 0;
+			    cf->inherited_from = 0;
+			    cf->cdr = old_cf;
+			    break;
+			  }
+			case re_se_fail:
+			  goto test_do_return;
+			case re_se_begbuf:
+			  if (!AT_STRINGS_BEG ())
+			    goto test_do_return;
+			  break;
+			case re_se_endbuf:
+			  if (!AT_STRINGS_END ())
+			    goto test_do_return;
+			  break;
+			case re_se_wordbeg:
+			  if (   LETTER_P (&search_state.test_pos, 1)
+			      && (   AT_STRINGS_BEG()
+				  || !LETTER_P (&search_state.test_pos, 0)))
+			    break;
+			  else
+			    goto test_do_return;
+			case re_se_wordend:
+			  if (   !AT_STRINGS_BEG ()
+			      && LETTER_P (&search_state.test_pos, 0)
+			      && (AT_STRINGS_END ()
+				  || !LETTER_P (&search_state.test_pos, 1)))
+			    break;
+			  else
+			    goto test_do_return;
+			case re_se_wordbound:
+			  if (AT_WORD_BOUNDARY (&search_state.test_pos))
+			    break;
+			  else
+			    goto test_do_return;
+			case re_se_notwordbound:
+			  if (!AT_WORD_BOUNDARY (&search_state.test_pos))
+			    break;
+			  else
+			    goto test_do_return;
+			case re_se_hat:
+			  if (AT_STRINGS_BEG ())
+			    {
+			      if (rxb->not_bol)
+				goto test_do_return;
+			      else
+				break;
+			    }
+			  else
+			    {
+			      char pos_c = *search_state.test_pos.pos;
+			      if (   (SRCH_TRANSLATE (pos_c)
+				      == SRCH_TRANSLATE('\n'))
+				  && rxb->newline_anchor)
+				break;
+			      else
+				goto test_do_return;
+			    }
+			case re_se_dollar:
+			  if (AT_STRINGS_END ())
+			    {
+			      if (rxb->not_eol)
+				goto test_do_return;
+			      else
+				break;
+			    }
+			  else
+			    {
+			      if (   (   SRCH_TRANSLATE (fetch_char
+						    (&search_state.test_pos, 1,
+						     app_closure, stop))
+				      == SRCH_TRANSLATE ('\n'))
+				  && rxb->newline_anchor)
+				break;
+			      else
+				goto test_do_return;
+			    }
+			  
+			case re_se_try:
+			  /* This is the first side effect in every
+			   * expression.
+			   *
+			   *  FOR NO GOOD REASON...get rid of it...
+			   */
+			  break;
+			  
+			case re_se_pushpos:
+			  {
+			    int urhere =
+			      ((int)(search_state.test_pos.pos
+				     - search_state.test_pos.string)
+			       + search_state.test_pos.offset);
+			    struct rx_counter_frame * old_cf
+			      = (search_state.counter_stack
+				 ? ((struct rx_counter_frame *)
+				    search_state.counter_stack->sp)
+				 : 0);
+			    struct rx_counter_frame * cf;
+			    PUSH(search_state.counter_stack,
+				 sizeof (struct rx_counter_frame));
+			    cf = ((struct rx_counter_frame *)
+				  search_state.counter_stack->sp);
+			    cf->tag = re_se_pushpos;
+			    cf->val = urhere;
+			    cf->inherited_from = 0;
+			    cf->cdr = old_cf;
+			    break;
+			  }
+			  
+			case re_se_chkpos:
+			  {
+			    int urhere =
+			      ((int)(search_state.test_pos.pos
+				     - search_state.test_pos.string)
+			       + search_state.test_pos.offset);
+			    struct rx_counter_frame * cf
+			      = ((struct rx_counter_frame *)
+				 search_state.counter_stack->sp);
+			    if (cf->val == urhere)
+			      goto test_do_return;
+			    cf->val = urhere;
+			    break;
+			  }
+			  break;
+			  
+			case re_se_poppos:
+			  POP(search_state.counter_stack,
+			      sizeof (struct rx_counter_frame));
+			  break;
+			  
+			  
+			case re_se_at_dot:
+			case re_se_syntax:
+			case re_se_not_syntax:
+#ifdef emacs
+			  /* 
+			   * this release lacks emacs support
+			   */
+#endif
+			  break;
+			case re_se_win:
+			case re_se_lparen:
+			case re_se_rparen:
+			case re_se_backref:
+			case re_se_iter:
+			case re_se_end_iter:
+			case re_se_tv:
+			case re_floogle_flap:
+			  search_state.ret_val = 0;
+			  goto test_do_return;
+			}
+		    }
+		  else
+		    {
+#ifdef RX_DEBUG_0
+		      if (rx_debug_trace)
+			fprintf (stderr, "....%d %d>> %s %d %d\n", search_state.line_no,
+				 search_state.backtrack_depth,
+				 efnames2[rxb->se_params [effect].se],
+				 rxb->se_params [effect].op1,
+				 rxb->se_params [effect].op2);
+#endif
+		      switch (rxb->se_params [effect].se)
+			{
+			case re_se_win:
+			  /* This side effect indicates that we've 
+			   * found a match, though not necessarily the 
+			   * best match.  This is a fancy assignment to 
+			   * register 0 unless the caller didn't 
+			   * care about registers.  In which case,
+			   * this stops the match.
+			   */
+			  {
+			    int urhere =
+			      ((int)(search_state.test_pos.pos
+				     - search_state.test_pos.string)
+			       + search_state.test_pos.offset);
+			    
+			    if (   (search_state.best_last_r < 0)
+				|| (urhere + 1 > search_state.best_rparen[0]))
+			      {
+				/* Record the best known and keep
+				 * looking.
+				 */
+				int x;
+				for (x = 0; x <= search_state.last_l; ++x)
+				  search_state.best_lparen[x] = search_state.lparen[x];
+				search_state.best_last_l = search_state.last_l;
+				for (x = 0; x <= search_state.last_r; ++x)
+				  search_state.best_rparen[x] = search_state.rparen[x];
+				search_state.best_rparen[0] = urhere + 1;
+				search_state.best_last_r = search_state.last_r;
+			      }
+			    /* If we're not reporting the match-length 
+			     * or other register info, we need look no
+			     * further.
+			     */
+			    if (search_state.first_found)
+			      {
+				search_state.test_ret = rx_test_found_first;
+				goto test_do_return;
+			      }
+			  }
+			  break;
+			case re_se_lparen:
+			  {
+			    int urhere =
+			      ((int)(search_state.test_pos.pos
+				     - search_state.test_pos.string)
+			       + search_state.test_pos.offset);
+			    
+			    int reg = rxb->se_params [effect].op1;
+#if 0
+			    if (reg > search_state.last_l)
+#endif
+			      {
+				search_state.lparen[reg] = urhere + 1;
+				/* In addition to making this assignment,
+				 * we now know that lower numbered regs
+				 * that haven't already been assigned,
+				 * won't be.  We make sure they're
+				 * filled with -1, so they can be
+				 * recognized as unassigned.
+				 */
+				if (search_state.last_l < reg)
+				  while (++search_state.last_l < reg)
+				    search_state.lparen[search_state.last_l] = -1;
+			      }
+			    break;
+			  }
+			  
+			case re_se_rparen:
+			  {
+			    int urhere =
+			      ((int)(search_state.test_pos.pos
+				     - search_state.test_pos.string)
+			       + search_state.test_pos.offset);
+			    int reg = rxb->se_params [effect].op1;
+			    search_state.rparen[reg] = urhere + 1;
+			    if (search_state.last_r < reg)
+			      {
+				while (++search_state.last_r < reg)
+				  search_state.rparen[search_state.last_r]
+				    = -1;
+			      }
+			    break;
+			  }
+			  
+			case re_se_backref:
+			  {
+			    int reg = rxb->se_params [effect].op1;
+			    if (   reg > search_state.last_r
+				|| search_state.rparen[reg] < 0)
+			      goto test_do_return;
+			    
+			    {
+			      int backref_status;
+			    check_backreference:
+			      backref_status
+				= back_check (&search_state.test_pos,
+					      search_state.lparen[reg],
+					      search_state.rparen[reg],
+					      search_state.translate,
+					      app_closure,
+					      stop);
+			      switch (backref_status)
+				{
+				case rx_back_check_continuation:
+				  search_state.saved_reg = reg;
+				  test_pc = rx_test_backreference_check;
+				  goto test_return_continuation;
+				resume_continuation_2:
+				  reg = search_state.saved_reg;
+				  goto check_backreference;
+				case rx_back_check_fail:
+				  /* Fail */
+				  goto test_do_return;
+				case rx_back_check_pass:
+				  /* pass --
+				   * test_pos now advanced to last
+				   * char matched by backref
+				   */
+				  break;
+				}
+			    }
+			    break;
+			  }
+			case re_se_iter:
+			  {
+			    struct rx_counter_frame * csp
+			      = ((struct rx_counter_frame *)
+				 search_state.counter_stack->sp);
+			    if (csp->val == rxb->se_params[effect].op2)
+			      goto test_do_return;
+			    else
+			      ++csp->val;
+			    break;
+			  }
+			case re_se_end_iter:
+			  {
+			    struct rx_counter_frame * csp
+			      = ((struct rx_counter_frame *)
+				 search_state.counter_stack->sp);
+			    if (csp->val < rxb->se_params[effect].op1)
+			      goto test_do_return;
+			    else
+			      {
+				struct rx_counter_frame * source = csp;
+				while (source->inherited_from)
+				  source = source->inherited_from;
+				if (!source || !source->cdr)
+				  {
+				    POP(search_state.counter_stack,
+					sizeof(struct rx_counter_frame));
+				  }
+				else
+				  {
+				    source = source->cdr;
+				    csp->val = source->val;
+				    csp->tag = source->tag;
+				    csp->cdr = 0;
+				    csp->inherited_from = source;
+				  }
+			      }
+			    break;
+			  }
+			case re_se_tv:
+			  /* is a noop */
+			  break;
+			case re_se_try:
+			case re_se_pushback:
+			case re_se_push0:
+			case re_se_pushpos:
+			case re_se_chkpos:
+			case re_se_poppos:
+			case re_se_at_dot:
+			case re_se_syntax:
+			case re_se_not_syntax:
+			case re_se_begbuf:
+			case re_se_hat:
+			case re_se_wordbeg:
+			case re_se_wordbound:
+			case re_se_notwordbound:
+			case re_se_wordend:
+			case re_se_endbuf:
+			case re_se_dollar:
+			case re_se_fail:
+			case re_floogle_flap:
+			  search_state.ret_val = 0;
+			  goto test_do_return;
+			}
+		    }
+		  el = el->cdr;
+		}
+	      /* Now the side effects are done,
+	       * so get the next instruction.
+	       * and move on.
+	       */
+	      search_state.ifr = &df->future_frame;
+	      goto restart;
+	    }
+	    
+	  case rx_backtrack_point:
+	    {
+	      /* A backtrack point indicates that we've reached a
+	       * non-determinism in the superstate NFA.  This is a
+	       * loop that exhaustively searches the possibilities.
+	       *
+	       * A backtracking strategy is used.  We keep track of what
+	       * registers are valid so we can erase side effects.
+	       *
+	       * First, make sure there is some stack space to hold 
+	       * our state.
+	       */
+	      
+	      struct rx_backtrack_frame * bf;
+	      
+	      PUSH(search_state.backtrack_stack,
+		   search_state.backtrack_frame_bytes);
+#ifdef RX_DEBUG_0
+	      ++search_state.backtrack_depth;
+#endif
+	      
+	      bf = ((struct rx_backtrack_frame *)
+		    search_state.backtrack_stack->sp);
+	      {
+		bf->stk_super = search_state.super;
+		/* We prevent the current superstate from being
+		 * deleted from the superstate cache.
+		 */
+		rx_lock_superstate (&rxb->rx, search_state.super);
+#ifdef RX_DEBUG_0
+		bf->stk_search_state.line_no = search_state.line_no;
+#endif
+		bf->stk_c = search_state.c;
+		bf->stk_test_pos = search_state.test_pos;
+		bf->stk_last_l = search_state.last_l;
+		bf->stk_last_r = search_state.last_r;
+		bf->df = ((struct rx_super_edge *)
+			  search_state.ifr->data_2)->options;
+		bf->first_df = bf->df;
+		bf->counter_stack_sp = (search_state.counter_stack
+					? search_state.counter_stack->sp
+					: 0);
+		bf->stk_test_ret = search_state.test_ret;
+		if (rxb->match_regs_on_stack)
+		  {
+		    int x;
+		    regoff_t * stk =
+		      (regoff_t *)((char *)bf + sizeof (*bf));
+		    for (x = 0; x <= search_state.last_l; ++x)
+		      stk[x] = search_state.lparen[x];
+		    stk += x;
+		    for (x = 0; x <= search_state.last_r; ++x)
+		      stk[x] = search_state.rparen[x];
+		  }
+	      }
+	      
+	      /* Here is a while loop whose body is mainly a function
+	       * call and some code to handle a return from that
+	       * function.
+	       *
+	       * From here on for the rest of `case backtrack_point' it
+	       * is unsafe to assume that the search_state copies of 
+	       * variables saved on the backtracking stack are valid
+	       * -- so read their values from the backtracking stack.
+	       *
+	       * This lets us use one generation fewer stack saves in
+	       * the call-graph of a search.
+	       */
+	      
+	    while_non_det_options:
+#ifdef RX_DEBUG_0
+	      ++search_state.lines_found;
+	      if (rx_debug_trace)
+		fprintf (stderr, "@@@ %d calls %d @@@\n",
+			 search_state.line_no, search_state.lines_found);
+	      
+	      search_state.line_no = search_state.lines_found;
+#endif
+	      
+	      if (bf->df->next_same_super_edge[0] == bf->first_df)
+		{
+		  /* This is a tail-call optimization -- we don't recurse
+		   * for the last of the possible futures.
+		   */
+		  search_state.ifr = (bf->df->effects
+				      ? &bf->df->side_effects_frame
+				      : &bf->df->future_frame);
+		  
+		  rx_unlock_superstate (&rxb->rx, search_state.super);
+		  POP(search_state.backtrack_stack,
+		      search_state.backtrack_frame_bytes);
+#ifdef RX_DEBUG
+		  --search_state.backtrack_depth;
+#endif
+		  goto restart;
+		}
+	      else
+		{
+		  if (search_state.counter_stack)
+		    {
+		      struct rx_counter_frame * old_cf
+			= ((struct rx_counter_frame *)search_state.counter_stack->sp);
+		      struct rx_counter_frame * cf;
+		      PUSH(search_state.counter_stack, sizeof (struct rx_counter_frame));
+		      cf = ((struct rx_counter_frame *)search_state.counter_stack->sp);
+		      cf->tag = old_cf->tag;
+		      cf->val = old_cf->val;
+		      cf->inherited_from = old_cf;
+		      cf->cdr = 0;
+		    }			
+		  /* `Call' this test-match block */
+		  search_state.ifr = (bf->df->effects
+				      ? &bf->df->side_effects_frame
+				      : &bf->df->future_frame);
+		  goto recurse_test_match;
+		}
+	      
+	      /* Returns in this block are accomplished by
+	       * goto test_do_return.  There are two cases.
+	       * If there is some search-stack left,
+	       * then it is a return from a `recursive' call.
+	       * If there is no search-stack left, then
+	       * we should return to the fastmap/search loop.
+	       */
+	      
+	    test_do_return:
+	      
+	      if (!search_state.backtrack_stack)
+		{
+#ifdef RX_DEBUG_0
+		  if (rx_debug_trace)
+		    fprintf (stderr, "!!! %d bails returning %d !!!\n",
+			     search_state.line_no, search_state.test_ret);
+#endif
+		  
+		  /* No more search-stack -- this test is done. */
+		  if (search_state.test_ret)
+		    goto return_from_test_match;
+		  else
+		    goto error_in_testing_match;
+		}
+	      
+	      /* Returning from a recursive call to 
+	       * the test match block:
+	       */
+	      
+	      bf = ((struct rx_backtrack_frame *)
+		    search_state.backtrack_stack->sp);
+#ifdef RX_DEBUG_0
+	      if (rx_debug_trace)
+		fprintf (stderr, "+++ %d returns %d (to %d)+++\n",
+			 search_state.line_no,
+			 search_state.test_ret,
+			 bf->stk_search_state.line_no);
+#endif
+	      
+	      while (search_state.counter_stack
+		     && (!bf->counter_stack_sp
+			 || (bf->counter_stack_sp
+			     != search_state.counter_stack->sp)))
+		{
+		  POP(search_state.counter_stack,
+		      sizeof (struct rx_counter_frame));
+		}
+	      
+	      if (search_state.test_ret == rx_test_error)
+		{
+		  POP (search_state.backtrack_stack,
+		       search_state.backtrack_frame_bytes);
+		  goto test_do_return;
+		}
+	      
+	      /* If a non-longest match was found and that is good 
+	       * enough, return immediately.
+	       */
+	      if (   (search_state.test_ret == rx_test_found_first)
+		  && search_state.first_found)
+		{
+		  rx_unlock_superstate (&rxb->rx, bf->stk_super);
+		  POP (search_state.backtrack_stack,
+		       search_state.backtrack_frame_bytes);
+		  goto test_do_return;
+		}
+	      
+	      search_state.test_ret = bf->stk_test_ret;
+	      search_state.last_l = bf->stk_last_l;
+	      search_state.last_r = bf->stk_last_r;
+	      bf->df = bf->df->next_same_super_edge[0];
+	      search_state.super = bf->stk_super;
+	      search_state.c = bf->stk_c;
+#ifdef RX_DEBUG_0
+	      search_state.line_no = bf->stk_search_state.line_no;
+#endif
+	      
+	      if (rxb->match_regs_on_stack)
+		{
+		  int x;
+		  regoff_t * stk =
+		    (regoff_t *)((char *)bf + sizeof (*bf));
+		  for (x = 0; x <= search_state.last_l; ++x)
+		    search_state.lparen[x] = stk[x];
+		  stk += x;
+		  for (x = 0; x <= search_state.last_r; ++x)
+		    search_state.rparen[x] = stk[x];
+		}
+	      
+	      {
+		int x;
+	      try_burst_2:
+		x = get_burst (&bf->stk_test_pos, app_closure, stop);
+		switch (x)
+		  {
+		  case rx_get_burst_continuation:
+		    search_state.saved_bf = bf;
+		    test_pc = rx_test_backtrack_return;
+		    goto test_return_continuation;
+		  resume_continuation_3:
+		    bf = search_state.saved_bf;
+		    goto try_burst_2;
+		  case rx_get_burst_no_more:
+		    /* Since we've been here before, it is some kind of
+		     * error that we can't return.
+		     */
+		  case rx_get_burst_error:
+		    search_state.test_ret = rx_test_internal_error;
+		    goto test_do_return;
+		  case rx_get_burst_ok:
+		    break;
+		  }
+	      }
+	      search_state.test_pos = bf->stk_test_pos;
+	      goto while_non_det_options;
+	    }
+	    
+	    
+	  case rx_cache_miss:
+	    /* Because the superstate NFA is lazily constructed,
+	     * and in fact may erode from underneath us, we sometimes
+	     * have to construct the next instruction from the hard way.
+	     * This invokes one step in the lazy-conversion.
+	     */
+	    search_state.ifr = rx_handle_cache_miss (&rxb->rx,
+						     search_state.super,
+						     search_state.c,
+						     search_state.ifr->data_2);
+	    if (!search_state.ifr)
+	      {
+		search_state.test_ret = rx_test_internal_error;
+		goto test_do_return;
+	      }
+	    goto restart;
+	    
+	  case rx_backtrack:
+	    /* RX_BACKTRACK means that we've reached the empty
+	     * superstate, indicating that match can't succeed
+	     * from this point.
+	     */
+	    goto test_do_return;
+	    
+	  case rx_next_char:
+	  case rx_error_inx:
+	  case rx_num_instructions:
+	    search_state.ret_val = 0;
+	    goto test_do_return;
+	  }
+	goto pseudo_while_1;
+      }
+    
+    /* Healthy exits from the test-match loop do a 
+     * `goto return_from_test_match'   On the other hand, 
+     * we might end up here.
+     */
+  error_in_testing_match:
+    test_state = rx_test_error;
+    goto test_returns_to_search;
+    
+    /***** fastmap/search loop body
+     *	      considering the results testing for a match
+     */
+    
+  return_from_test_match:
+    
+    if (search_state.best_last_l >= 0)
+      {
+	if (regs && (regs->start != search_state.best_lparen))
+	  {
+	    bcopy (search_state.best_lparen, regs->start,
+		   regs->num_regs * sizeof (int));
+	    bcopy (search_state.best_rparen, regs->end,
+		   regs->num_regs * sizeof (int));
+	  }
+	if (regs && !rxb->no_sub)
+	  {
+	    int q;
+	    int bound = (regs->num_regs > search_state.num_regs
+			 ? regs->num_regs
+			 : search_state.num_regs);
+	    regoff_t * s = regs->start;
+	    regoff_t * e = regs->end;
+	    for (q = search_state.best_last_l + 1;  q < bound; ++q)
+	      s[q] = e[q] = -1;
+	  }
+	search_state.ret_val = search_state.best_lparen[0];
+	test_state = rx_test_ok;
+	goto test_returns_to_search;
+      }
+    else
+      {
+	test_state = rx_test_fail;
+	goto test_returns_to_search;
+      }
+    
+  test_return_continuation:
+    search_state.test_match_resume_pt = test_pc;
+    test_state = rx_test_continuation;
+    goto test_returns_to_search;
+  }
+}
+
+
+
+#endif /* RX_WANT_RX_DEFS */
+
+
+
+#else /* RX_WANT_SE_DEFS */
+  /* Integers are used to represent side effects.
+   *
+   * Simple side effects are given negative integer names by these enums.
+   * 
+   * Non-negative names are reserved for complex effects.
+   *
+   * Complex effects are those that take arguments.  For example, 
+   * a register assignment associated with a group is complex because
+   * it requires an argument to tell which group is being matched.
+   * 
+   * The integer name of a complex effect is an index into rxb->se_params.
+   */
+ 
+  RX_DEF_SE(1, re_se_try, = -1)		/* Epsilon from start state */
+
+  RX_DEF_SE(0, re_se_pushback, = re_se_try - 1)
+  RX_DEF_SE(0, re_se_push0, = re_se_pushback -1)
+  RX_DEF_SE(0, re_se_pushpos, = re_se_push0 - 1)
+  RX_DEF_SE(0, re_se_chkpos, = re_se_pushpos -1)
+  RX_DEF_SE(0, re_se_poppos, = re_se_chkpos - 1)
+
+  RX_DEF_SE(1, re_se_at_dot, = re_se_poppos - 1)	/* Emacs only */
+  RX_DEF_SE(0, re_se_syntax, = re_se_at_dot - 1) /* Emacs only */
+  RX_DEF_SE(0, re_se_not_syntax, = re_se_syntax - 1) /* Emacs only */
+
+  RX_DEF_SE(1, re_se_begbuf, = re_se_not_syntax - 1) /* match beginning of buffer */
+  RX_DEF_SE(1, re_se_hat, = re_se_begbuf - 1) /* match beginning of line */
+
+  RX_DEF_SE(1, re_se_wordbeg, = re_se_hat - 1) 
+  RX_DEF_SE(1, re_se_wordbound, = re_se_wordbeg - 1)
+  RX_DEF_SE(1, re_se_notwordbound, = re_se_wordbound - 1)
+
+  RX_DEF_SE(1, re_se_wordend, = re_se_notwordbound - 1)
+  RX_DEF_SE(1, re_se_endbuf, = re_se_wordend - 1)
+
+  /* This fails except at the end of a line. 
+   * It deserves to go here since it is typicly one of the last steps 
+   * in a match.
+   */
+  RX_DEF_SE(1, re_se_dollar, = re_se_endbuf - 1)
+
+  /* Simple effects: */
+  RX_DEF_SE(1, re_se_fail, = re_se_dollar - 1)
+
+  /* Complex effects.  These are used in the 'se' field of 
+   * a struct re_se_params.  Indexes into the se array
+   * are stored as instructions on nfa edges.
+   */
+  RX_DEF_CPLX_SE(1, re_se_win, = 0)
+  RX_DEF_CPLX_SE(1, re_se_lparen, = re_se_win + 1)
+  RX_DEF_CPLX_SE(1, re_se_rparen, = re_se_lparen + 1)
+  RX_DEF_CPLX_SE(0, re_se_backref, = re_se_rparen + 1)
+  RX_DEF_CPLX_SE(0, re_se_iter, = re_se_backref + 1) 
+  RX_DEF_CPLX_SE(0, re_se_end_iter, = re_se_iter + 1)
+  RX_DEF_CPLX_SE(0, re_se_tv, = re_se_end_iter + 1)
+
+#endif
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/simplefrenchstem.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/simplefrenchstem.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/simplefrenchstem.c	(revision 14757)
@@ -0,0 +1,70 @@
+/**************************************************************************
+ *
+ * simplefrenchstem.c -- a simple french stemmer
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "simplefrenchstem.h"
+
+
+
+/* =========================================================================
+ * Function: simplefrenchstem
+ * Description: a simple french stemmer
+ * Input: a word string with the length in the first byte
+ * Output: the stemmed word
+ * ========================================================================= */
+
+void simplefrenchstem (unsigned char *word) {      
+  unsigned short out[256]; /* temp space */
+  unsigned short *wordstart; /* points to first letter of word */
+  int last;                  /* last points to the last character */
+
+  /* decode */
+  utf8_word_to_unicode (word, out, 255);
+  wordstart = out + 1;
+  last = out[0]-1;
+  
+
+  if (last > 4) {
+    if (wordstart[last]=='x') {
+      if (wordstart[last-1]=='u' && wordstart[last-2]=='a') {
+	wordstart[last-1]='l';
+      }
+      last--;
+
+    } else {
+      if (last>=0 && wordstart[last]=='s') last--;
+      if (last>=0 && wordstart[last]=='r') last--;
+      if (last>=0 && wordstart[last]=='e') last--;
+
+      /* letter with accent e + ' -- there are two possible encodings  */
+      if (last>=0 && wordstart[last]==0xe9) { 
+	last--;
+      } else if (last>=1 && wordstart[last-1]=='e' && wordstart[last]==0x301) {
+	last -= 2; 
+      }
+
+      if (last >= 1 && wordstart[last]==wordstart[last-1]) last--;
+    }  /* end else */
+
+    out[0] = (unsigned char)(last+1);
+  } /* end if (len > 4) */
+
+  /* re-code, make sure the result is not longer than the input */
+  unicode_to_utf8_word (out, word, word[0]+1);
+}
Index: /indexers/branches/3.03a/mg/lib/simplefrenchstem.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/simplefrenchstem.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/simplefrenchstem.h	(revision 14757)
@@ -0,0 +1,26 @@
+/**************************************************************************
+ *
+ * simplefrenchstem.h -- a simple french stemmer
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef SIMPLEFRENCHSTEM_H
+#define SIMPLEFRENCHSTEM_H
+
+void simplefrenchstem (unsigned char *word);
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/sptree.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/sptree.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/sptree.c	(revision 14757)
@@ -0,0 +1,374 @@
+/**************************************************************************
+ *
+ * sptree.c -- Splay tree code
+ * Copyright (C) 1994  Gary Eddy, Alistair Moffat and Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+
+#include	"sysfuncs.h"
+#include	"sptree.h"
+
+#define TRACE(w)
+
+#define POOL_SIZE 1024
+
+
+typedef struct node_rec node;
+
+struct node_rec
+  {
+    node *left, *rght;
+    node *par;
+    char *datsun;
+  };
+
+struct pool
+  {
+    int length, pos;
+    struct pool *next;
+    node nodes[POOL_SIZE];
+  };
+
+static node *SP_splay ();
+
+#define	CNULL	((char *) NULL)
+#define	NNULL	((node *) NULL)
+#define	SNULL	((Splay_Tree *) NULL)
+
+
+/*
+ *    createset():
+ *              allocates memory for and initialises a set.
+ *
+ *      Accesses outside variables:     none
+ *
+ *      Return value...:                none
+ */
+
+Splay_Tree *
+SP_createset (int (*cmp) (void *, void *))
+{
+  Splay_Tree *S;
+
+  if (!(S = (Splay_Tree *) malloc (sizeof (Splay_Tree))))
+    return (SNULL);
+  S->cmp = cmp;
+  S->root = CNULL;
+  S->no_of_items = 0;
+  S->mem_in_use = sizeof (Splay_Tree);
+  S->pool = NULL;
+  S->pool_chunks = 1024;
+  return S;
+}				/* createset() */
+
+
+
+static node *
+SP_get_node (Splay_Tree * S)
+{
+  struct pool *p = S->pool;
+  if (!p || p->pos == p->length)
+    {
+      p = malloc (sizeof (struct pool));
+      if (!p)
+	return NULL;
+      S->mem_in_use += sizeof (struct pool);
+      p->length = POOL_SIZE;
+      p->pos = 0;
+      p->next = S->pool;
+      S->pool = p;
+    }
+  return &(p->nodes[p->pos++]);
+}
+
+
+
+/*
+ *    SP_freeset():
+ *              free the memory allocated to a splay tree. Note this Does not
+ *              free the data in the tree you must do this yourself.
+ *
+ *      Accesses outside variables:     none
+ *
+ *      Return value...:                none
+ */
+
+void 
+SP_freeset (Splay_Tree * S)
+{
+  while (S->pool)
+    {
+      struct pool *p = S->pool;
+      S->pool = p->next;
+      free (p);
+    }
+  free (S);
+}
+
+
+/*
+ *    insert():
+ *              inserts the item given into the set given in the order
+ *              specified by the comparison function in the set 
+ *              definition.
+ *
+ *      Accesses outside variables:     none
+ *
+ *      Return value...:                none
+ */
+
+
+void *
+SP_insert (void *item, Splay_Tree * S)
+{
+  int dir = 0;
+  register node *curr, *prev;
+  node *tmp;
+
+  prev = NNULL;
+  curr = (node *) S->root;
+  for (; curr;)
+    {
+      prev = curr;
+      dir = S->cmp (item, curr->datsun);
+      if (dir < 0)
+	curr = curr->left;
+      else
+	curr = curr->rght;
+    }
+  if (!(tmp = SP_get_node (S)))
+    return NULL;
+  tmp->datsun = item;
+
+  if (prev == NNULL)
+    S->root = (char *) tmp;
+  else if (dir < 0)
+    prev->left = tmp;
+  else
+    prev->rght = tmp;
+
+  tmp->par = prev;
+  tmp->left = NNULL;
+  tmp->rght = NNULL;
+  S->no_of_items++;
+  S->root = (char *) SP_splay (tmp);
+  return (tmp->datsun);
+}				/* insert() */
+
+/*
+ *    get_first():
+ *              returns a pointer to the first item in the set. If the set 
+ *              is empty a NULL pointer is returned.
+ *
+ *      Accesses outside variables:     none
+ */
+
+void *
+SP_get_first (Splay_Tree * S)
+{
+  node *curr, *prev;
+
+  for (curr = (node *) S->root, prev = NNULL; curr;
+       prev = curr, curr = curr->left)
+    ;				/* NULLBODY */
+
+  if (prev)
+    S->root = (char *) SP_splay (prev);
+  return (prev ? prev->datsun : CNULL);
+}				/* get_first() */
+
+/*
+ *    get_next():
+ *              returns the in-order successor of the currently fingered
+ *              item of the set. If no item is fingered or if there is 
+ *              no in-order successor a NULL pointer is returned.
+ *
+ *      Accesses outside variables:     none
+ */
+
+void *
+SP_get_next (Splay_Tree * S)
+{
+  node *curr, *prev;
+
+  curr = (node *) S->root;
+  if (!curr || !curr->rght)
+    return (CNULL);
+
+  for (prev = curr, curr = curr->rght; curr;
+       prev = curr, curr = curr->left)
+    ;				/* NULLBODY */
+
+  if (prev)
+    S->root = (char *) SP_splay (prev);
+  return (prev ? prev->datsun : CNULL);
+}				/* get_next() */
+
+/*
+ *    deletemin():
+ *              removes the first element in the set and returns a
+ *              pointer to it. If the set is empty a NULL pointer 
+ *              is returned.
+ *
+ *      Accesses outside variables:     none
+ */
+
+void *
+SP_deletemin (Splay_Tree * S)
+{
+  node *tmp;
+  char *dat;
+
+  dat = SP_get_first (S);
+  if (dat)
+    {
+      tmp = (node *) S->root;
+      S->root = (char *) tmp->rght;
+      if (S->root)
+	((node *) S->root)->par = NULL;
+    }
+  S->no_of_items--;
+  return dat;
+}				/* deletemin() */
+
+
+/*
+ *    member():
+ *              searches the given set for an item which matches (has
+ *              the same key) and returns a pointer to a copy of that item.
+ *              If no matching item is found a NULL pointer is 
+ *              returned.
+ *
+ *      Accesses outside variables:     none
+ */
+
+void *
+SP_member (void *dat, Splay_Tree * S)
+{
+  register node *curr;
+  register int dir;
+  static int calls = 0;
+
+  TRACE ("in member");
+  for (curr = (node *) S->root; curr;)
+    {
+      TRACE ("call to cmp");
+      dir = S->cmp (dat, curr->datsun);
+      TRACE ("out of cmp");
+      if (dir < 0)
+	curr = curr->left;
+      else if (dir > 0)
+	curr = curr->rght;
+      else
+	{
+	  /* splay occasionaly to speed up execution */
+	  if ((calls++ % 4) == 0 && curr)
+	    S->root = (char *) SP_splay (curr);
+	  TRACE ("out of member");
+	  return (curr->datsun);
+	}
+    }
+  TRACE ("out of member");
+  return (CNULL);
+}				/* member() */
+
+#define	ROTATEL(p,q) 					\
+	do{						\
+		p->par = q->par;			\
+		q->par = p;				\
+		q->rght = p->left;			\
+		if(q->rght)				\
+			q->rght->par = q;		\
+		p->left = q;				\
+		if(p->par)				\
+			if(q == p->par->left)		\
+				p->par->left = p;	\
+			else				\
+				p->par->rght = p;	\
+	}while(0)
+
+#define	ROTATER(p,q) 					\
+	do{						\
+		p->par = q->par;			\
+		q->par = p;				\
+		q->left = p->rght;			\
+		if(q->left)				\
+			q->left->par = q;		\
+		p->rght = q;				\
+		if(p->par)				\
+			if(q == p->par->left)		\
+				p->par->left = p;	\
+			else				\
+				p->par->rght = p;	\
+	}while(0)
+
+
+/*
+ *    splay():
+ *              i
+ *
+ *      Accesses outside variables:     i
+ *
+ *      Return value...:                i
+ */
+
+static node *
+SP_splay (p)
+     register node *p;
+{
+  register node *q, *g;
+
+  q = p->par;
+  /* splay the tree about p */
+  while (q != NNULL)
+    {
+      g = q->par;
+      if (p == q->left)
+	{
+	  if (g == NNULL)
+	    ROTATER (p, q);
+	  else if (q == g->left)
+	    {
+	      ROTATER (q, g);
+	      ROTATER (p, q);
+	    }
+	  else
+	    {
+	      ROTATER (p, q);
+	      ROTATEL (p, g);
+	    }
+	}
+      else
+	{
+	  if (g == NNULL)
+	    ROTATEL (p, q);
+	  else if (q == g->rght)
+	    {
+	      ROTATEL (q, g);
+	      ROTATEL (p, q);
+	    }
+	  else
+	    {
+	      ROTATEL (p, q);
+	      ROTATER (p, g);
+	    }
+	}
+      q = p->par;
+    }
+  return (p);
+}
Index: /indexers/branches/3.03a/mg/lib/sptree.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/sptree.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/sptree.h	(revision 14757)
@@ -0,0 +1,45 @@
+/**************************************************************************
+ *
+ * sptree.h -- Splay tree code
+ * Copyright (C) 1994  Gary Eddy and Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+
+#ifndef SPTREE_H
+#define SPTREE_H
+
+typedef struct set_rec Splay_Tree;
+
+struct set_rec
+  {
+    int no_of_items;
+    unsigned long mem_in_use;
+    int (*cmp) (void *, void *);
+    void *root;
+    void *pool;
+    int pool_chunks;
+  };
+
+Splay_Tree *SP_createset (int (*cmp) (void *, void *));
+void *SP_insert (void *item, Splay_Tree * S);
+void *SP_get_first (Splay_Tree * S);
+void *SP_get_next (Splay_Tree * S);
+void *SP_deletemin (Splay_Tree * S);
+void *SP_member (void *dat, Splay_Tree * S);
+void SP_freeset (Splay_Tree * S);
+#endif
Index: /indexers/branches/3.03a/mg/lib/strcasecmp.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/strcasecmp.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/strcasecmp.c	(revision 14757)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of California at Berkeley. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific written prior permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcasecmp.c	5.5 (Berkeley) 11/24/87";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static unsigned char charmap[] = {
+	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+	'\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
+	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+int
+strcasecmp(s1, s2)
+    char *s1, *s2;
+{
+    register unsigned char u1, u2;
+
+    for (;;) {
+	u1 = (unsigned char) *s1++;
+	u2 = (unsigned char) *s2++;
+	if (charmap[u1] != charmap[u2]) {
+	    return charmap[u1] - charmap[u2];
+	}
+	if (u1 == '\0') {
+	    return 0;
+	}
+    }
+}
+
Index: /indexers/branches/3.03a/mg/lib/strstr.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/strstr.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/strstr.c	(revision 14757)
@@ -0,0 +1,44 @@
+/* strstr.c -- return the offset of one string within another
+   Copyright (C) 1989, 1990 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 program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Written by Mike Rendell <michael@cs.mun.ca>.  */
+
+/* Return the starting address of string S2 in S1;
+   return 0 if it is not found. */
+
+char *
+strstr (s1, s2)
+     char *s1;
+     char *s2;
+{
+  int i;
+  char *p1;
+  char *p2;
+  char *s = s1;
+
+  for (p2 = s2, i = 0; *s; p2 = s2, i++, s++)
+    {
+      for (p1 = s; *p1 && *p2 && *p1 == *p2; p1++, p2++)
+	;
+      if (!*p2)
+	break;
+    }
+  if (!*p2)
+    return s1 + i;
+
+  return 0;
+}
Index: /indexers/branches/3.03a/mg/lib/timing.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/timing.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/timing.c	(revision 14757)
@@ -0,0 +1,217 @@
+/**************************************************************************
+ *
+ * timing.c -- Program timing routines
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "timing.h"
+
+
+/*
+ * Return the time in seconds since 00:00:00 GMT, Jan. 1, 1970 to the
+ * best precision possible
+ *
+ */
+double 
+RealTime (void)
+{
+  return ((double) time (NULL));
+}
+
+
+
+/*
+ * Return the amount of system and user CPU used by the process to date to 
+ * the best precision possible. If user is non-null then it is initialised to 
+ * the user time. If sys is non-null then it is initialised to the system time.
+ *
+ */
+double 
+CPUTime (double *user, double *sys)
+{
+
+#if defined(HAVE_TIMES)
+
+  struct tms buffer;
+  static double clk_tck = 0;
+  double u, s;
+
+  times (&buffer);
+
+  if (clk_tck == 0)
+    clk_tck = CLK_TCK;
+
+  u = (double) buffer.tms_utime / clk_tck;
+  s = (double) buffer.tms_stime / clk_tck;
+  if (user)
+    *user = u;
+  if (sys)
+    *sys = s;
+  return u + s;
+
+#elif defined(HAVE_GETRUSAGE)
+
+  struct rusage ruse;
+  getrusage (RUSAGE_SELF, &ruse);
+  if (user)
+    *user = (double) ruse.ru_utime.tv_sec +
+      (double) ruse.ru_utime.tv_usec / 1000000;
+  if (sys)
+    *sys = (double) ruse.ru_stime.tv_sec +
+      (double) ruse.ru_stime.tv_usec / 1000000;
+  return ((double) ruse.ru_utime.tv_sec + ruse.ru_stime.tv_sec +
+	((double) ruse.ru_utime.tv_usec + ruse.ru_stime.tv_usec) / 1000000);
+
+#else
+
+  /* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+  if (user) *user = 0.0;
+  if (sys) *sys = 0.0;
+  return 0.0;
+#else
+  -->Can NOT find a system time routine to use ! !!
+#endif  /* __WIN32__ */
+
+#endif
+
+}
+
+
+
+
+/*
+ * Get the Real and CPU time and store them in a ProgTime structure
+ */
+void 
+GetTime (ProgTime * StartTime)
+{
+  StartTime->RealTime = RealTime ();
+  StartTime->CPUTime = CPUTime (NULL, NULL);
+}
+
+
+
+
+/*
+ * Display the Real and CPU time elapsed since the StartTime anf FinishTime 
+ * structures were initialised. If FinishTime is NULL then FinishTime is
+ * Now.
+ */
+char *
+ElapsedTime (ProgTime * StartTime,
+	     ProgTime * FinishTime)
+{
+  static char buf[50];
+  double Real, CPU, hour, min, sec;
+  if (!FinishTime)
+    {
+      Real = RealTime () - StartTime->RealTime;
+      CPU = CPUTime (NULL, NULL) - StartTime->CPUTime;
+    }
+  else
+    {
+      Real = FinishTime->RealTime - StartTime->RealTime;
+      CPU = FinishTime->CPUTime - StartTime->CPUTime;
+    }
+  hour = floor (CPU / 3600);
+  min = floor ((CPU - hour * 3600) / 60);
+  sec = CPU - hour * 3600 - min * 60;
+  sprintf (buf, "%02.0f:%02.0f:%05.2f cpu, %02d:%02d:%02d elapsed.",
+	   hour, min, sec,
+	   ((int) ceil (Real)) / 3600,
+	   (((int) ceil (Real)) % 3600) / 60, ((int) ceil (Real)) % 60);
+  return (buf);
+}
+
+
+#define MILLION 1000000
+
+/* ===============================================================================
+ * Function: cputime_string
+ * Description:
+ *      Prints out given cpu time into a string buffer.
+ * Input: cpu-time in clock_t or timeval format
+ * Output: pointer to internal buffer 
+ * =============================================================================== */
+
+#ifdef HAVE_TIMES
+char *
+cputime_string (clock_t clk)
+{
+  static char buf[15];
+  double CPU, hour, min, sec;
+
+  CPU = (double) clk / (double) CLK_TCK;
+  hour = floor (CPU / 3600);
+  min = floor ((CPU - hour * 3600) / 60);
+  sec = CPU - hour * 3600 - min * 60;
+  sprintf (buf, "%02.0f:%02.0f:%05.2f", hour, min, sec);
+  return (buf);
+}
+#else
+char *
+cputime_string (struct timeval *t)
+{
+  static char buf[15];
+  double CPU, hour, min, sec;
+
+  CPU = (double) t->tv_sec + (double) t->tv_usec / MILLION;
+  hour = floor (CPU / 3600);
+  min = floor ((CPU - hour * 3600) / 60);
+  sec = CPU - hour * 3600 - min * 60;
+  sprintf (buf, "%02.0f:%02.0f:%05.2f", hour, min, sec);
+  return (buf);
+}
+#endif
+
+
+
+/* ===============================================================================
+ * Function: time_normalise
+ * Description:
+ *      If the micro-second component is negative or over a million,
+ *      then must take the over/under flow and add it to the second component.
+ * Usage:
+ *      Use this routine when you have just been doing straight addition and
+ *      subtraction on the micro-second component. For this could lead to a
+ *      negative number or over a million.
+ *
+ * =============================================================================== */
+
+#ifndef HAVE_TIMES
+
+#ifndef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+static 
+#endif
+void
+time_normalise (struct timeval *t)
+{
+  while (t->tv_usec < 0)
+    {
+      t->tv_usec += MILLION;
+      t->tv_sec--;
+    }
+  while (t->tv_usec > MILLION)
+    {
+      t->tv_usec -= MILLION;
+      t->tv_sec++;
+    }
+}
+#endif
Index: /indexers/branches/3.03a/mg/lib/timing.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/timing.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/timing.h	(revision 14757)
@@ -0,0 +1,73 @@
+/**************************************************************************
+ *
+ * timing.h -- Program timing routines
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_TIMING
+#define H_TIMING
+
+
+#ifdef HAVE_TIMES
+# if TIME_WITH_SYS_TIME
+#  include <sys/times.h>
+#  include <time.h>
+#  ifndef CLK_TCK
+#   define CLK_TCK sysconf(_SC_CLK_TCK)
+#  endif
+# else
+#  if HAVE_SYS_TIME_H
+#   include <sys/time.h>
+#  else
+#   include <time.h>
+#  endif
+# endif
+#else
+/* [RPAP - Feb 97: WIN32 Port] */
+# ifdef __WIN32__
+   struct timeval { long tv_sec, tv_usec; };
+# else
+#  include <sys/time.h>
+#  include <sys/resource.h>
+# endif
+#endif
+
+
+typedef struct
+  {
+    double RealTime, CPUTime;
+  }
+ProgTime;
+
+double RealTime (void);
+
+double CPUTime (double *user, double *sys);
+
+void GetTime (ProgTime * StartTime);
+
+/* FinishTime may be NULL */
+char *ElapsedTime (ProgTime * StartTime, ProgTime * FinishTime);
+
+#ifdef HAVE_TIMES
+char *cputime_string (clock_t clk);
+#else
+void time_normalise (struct timeval *t);
+char *cputime_string (struct timeval *t);
+#endif
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/unitool.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/unitool.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/unitool.c	(revision 14757)
@@ -0,0 +1,1758 @@
+#include "unitool.h"
+#include "sysfuncs.h"
+
+
+/* unicode_cat_data is a combination of the letter, digit, and
+ * space information in a form that is quick to look up.
+ * The information about each byte is stored in two bits
+ *
+ * 00 - neither letter, digit or space
+ * 01 - letter
+ * 10 - space
+ * 11 - digit
+ *
+ * You can test for letter | space by looking at the right
+ * column
+ */
+unsigned long *unicode_cat_data=NULL;
+
+
+typedef struct unidecompose {
+  unsigned short ch;
+  unsigned short str[3];
+} unidecompose;
+
+typedef struct unirelate {
+  unsigned short ch1;
+  unsigned short ch2;
+} unirelate;
+
+typedef struct unirange {
+  unsigned short first;
+  unsigned short last;
+} unirange;
+
+
+
+/* This decomposition data only includes canonical decompositional
+ * characters.  Any unused bytes are set to 0x0. */
+
+#define NUM_DECOMPOSE_INFO 1269
+static const unidecompose decompose_info[NUM_DECOMPOSE_INFO] = {
+  {0xC0,0x41,0x300,0x0}, {0xC1,0x41,0x301,0x0}, {0xC2,0x41,0x302,0x0}, 
+  {0xC3,0x41,0x303,0x0}, {0xC4,0x41,0x308,0x0}, {0xC5,0x41,0x30A,0x0}, 
+  {0xC7,0x43,0x327,0x0}, {0xC8,0x45,0x300,0x0}, {0xC9,0x45,0x301,0x0}, 
+  {0xCA,0x45,0x302,0x0}, {0xCB,0x45,0x308,0x0}, {0xCC,0x49,0x300,0x0}, 
+  {0xCD,0x49,0x301,0x0}, {0xCE,0x49,0x302,0x0}, {0xCF,0x49,0x308,0x0}, 
+  {0xD1,0x4E,0x303,0x0}, {0xD2,0x4F,0x300,0x0}, {0xD3,0x4F,0x301,0x0}, 
+  {0xD4,0x4F,0x302,0x0}, {0xD5,0x4F,0x303,0x0}, {0xD6,0x4F,0x308,0x0}, 
+  {0xD9,0x55,0x300,0x0}, {0xDA,0x55,0x301,0x0}, {0xDB,0x55,0x302,0x0}, 
+  {0xDC,0x55,0x308,0x0}, {0xDD,0x59,0x301,0x0}, {0xE0,0x61,0x300,0x0}, 
+  {0xE1,0x61,0x301,0x0}, {0xE2,0x61,0x302,0x0}, {0xE3,0x61,0x303,0x0}, 
+  {0xE4,0x61,0x308,0x0}, {0xE5,0x61,0x30A,0x0}, {0xE7,0x63,0x327,0x0}, 
+  {0xE8,0x65,0x300,0x0}, {0xE9,0x65,0x301,0x0}, {0xEA,0x65,0x302,0x0}, 
+  {0xEB,0x65,0x308,0x0}, {0xEC,0x69,0x300,0x0}, {0xED,0x69,0x301,0x0}, 
+  {0xEE,0x69,0x302,0x0}, {0xEF,0x69,0x308,0x0}, {0xF1,0x6E,0x303,0x0}, 
+  {0xF2,0x6F,0x300,0x0}, {0xF3,0x6F,0x301,0x0}, {0xF4,0x6F,0x302,0x0}, 
+  {0xF5,0x6F,0x303,0x0}, {0xF6,0x6F,0x308,0x0}, {0xF9,0x75,0x300,0x0}, 
+  {0xFA,0x75,0x301,0x0}, {0xFB,0x75,0x302,0x0}, {0xFC,0x75,0x308,0x0}, 
+  {0xFD,0x79,0x301,0x0}, {0xFF,0x79,0x308,0x0}, {0x100,0x41,0x304,0x0}, 
+  {0x101,0x61,0x304,0x0}, {0x102,0x41,0x306,0x0}, {0x103,0x61,0x306,0x0}, 
+  {0x104,0x41,0x328,0x0}, {0x105,0x61,0x328,0x0}, {0x106,0x43,0x301,0x0}, 
+  {0x107,0x63,0x301,0x0}, {0x108,0x43,0x302,0x0}, {0x109,0x63,0x302,0x0}, 
+  {0x10A,0x43,0x307,0x0}, {0x10B,0x63,0x307,0x0}, {0x10C,0x43,0x30C,0x0}, 
+  {0x10D,0x63,0x30C,0x0}, {0x10E,0x44,0x30C,0x0}, {0x10F,0x64,0x30C,0x0}, 
+  {0x112,0x45,0x304,0x0}, {0x113,0x65,0x304,0x0}, {0x114,0x45,0x306,0x0}, 
+  {0x115,0x65,0x306,0x0}, {0x116,0x45,0x307,0x0}, {0x117,0x65,0x307,0x0}, 
+  {0x118,0x45,0x328,0x0}, {0x119,0x65,0x328,0x0}, {0x11A,0x45,0x30C,0x0}, 
+  {0x11B,0x65,0x30C,0x0}, {0x11C,0x47,0x302,0x0}, {0x11D,0x67,0x302,0x0}, 
+  {0x11E,0x47,0x306,0x0}, {0x11F,0x67,0x306,0x0}, {0x120,0x47,0x307,0x0}, 
+  {0x121,0x67,0x307,0x0}, {0x122,0x47,0x327,0x0}, {0x123,0x67,0x327,0x0}, 
+  {0x124,0x48,0x302,0x0}, {0x125,0x68,0x302,0x0}, {0x128,0x49,0x303,0x0}, 
+  {0x129,0x69,0x303,0x0}, {0x12A,0x49,0x304,0x0}, {0x12B,0x69,0x304,0x0}, 
+  {0x12C,0x49,0x306,0x0}, {0x12D,0x69,0x306,0x0}, {0x12E,0x49,0x328,0x0}, 
+  {0x12F,0x69,0x328,0x0}, {0x130,0x49,0x307,0x0}, {0x134,0x4A,0x302,0x0}, 
+  {0x135,0x6A,0x302,0x0}, {0x136,0x4B,0x327,0x0}, {0x137,0x6B,0x327,0x0}, 
+  {0x139,0x4C,0x301,0x0}, {0x13A,0x6C,0x301,0x0}, {0x13B,0x4C,0x327,0x0}, 
+  {0x13C,0x6C,0x327,0x0}, {0x13D,0x4C,0x30C,0x0}, {0x13E,0x6C,0x30C,0x0}, 
+  {0x143,0x4E,0x301,0x0}, {0x144,0x6E,0x301,0x0}, {0x145,0x4E,0x327,0x0}, 
+  {0x146,0x6E,0x327,0x0}, {0x147,0x4E,0x30C,0x0}, {0x148,0x6E,0x30C,0x0}, 
+  {0x14C,0x4F,0x304,0x0}, {0x14D,0x6F,0x304,0x0}, {0x14E,0x4F,0x306,0x0}, 
+  {0x14F,0x6F,0x306,0x0}, {0x150,0x4F,0x30B,0x0}, {0x151,0x6F,0x30B,0x0}, 
+  {0x154,0x52,0x301,0x0}, {0x155,0x72,0x301,0x0}, {0x156,0x52,0x327,0x0}, 
+  {0x157,0x72,0x327,0x0}, {0x158,0x52,0x30C,0x0}, {0x159,0x72,0x30C,0x0}, 
+  {0x15A,0x53,0x301,0x0}, {0x15B,0x73,0x301,0x0}, {0x15C,0x53,0x302,0x0}, 
+  {0x15D,0x73,0x302,0x0}, {0x15E,0x53,0x327,0x0}, {0x15F,0x73,0x327,0x0}, 
+  {0x160,0x53,0x30C,0x0}, {0x161,0x73,0x30C,0x0}, {0x162,0x54,0x327,0x0}, 
+  {0x163,0x74,0x327,0x0}, {0x164,0x54,0x30C,0x0}, {0x165,0x74,0x30C,0x0}, 
+  {0x168,0x55,0x303,0x0}, {0x169,0x75,0x303,0x0}, {0x16A,0x55,0x304,0x0}, 
+  {0x16B,0x75,0x304,0x0}, {0x16C,0x55,0x306,0x0}, {0x16D,0x75,0x306,0x0}, 
+  {0x16E,0x55,0x30A,0x0}, {0x16F,0x75,0x30A,0x0}, {0x170,0x55,0x30B,0x0}, 
+  {0x171,0x75,0x30B,0x0}, {0x172,0x55,0x328,0x0}, {0x173,0x75,0x328,0x0}, 
+  {0x174,0x57,0x302,0x0}, {0x175,0x77,0x302,0x0}, {0x176,0x59,0x302,0x0}, 
+  {0x177,0x79,0x302,0x0}, {0x178,0x59,0x308,0x0}, {0x179,0x5A,0x301,0x0}, 
+  {0x17A,0x7A,0x301,0x0}, {0x17B,0x5A,0x307,0x0}, {0x17C,0x7A,0x307,0x0}, 
+  {0x17D,0x5A,0x30C,0x0}, {0x17E,0x7A,0x30C,0x0}, {0x1A0,0x4F,0x31B,0x0}, 
+  {0x1A1,0x6F,0x31B,0x0}, {0x1AF,0x55,0x31B,0x0}, {0x1B0,0x75,0x31B,0x0}, 
+  {0x1CD,0x41,0x30C,0x0}, {0x1CE,0x61,0x30C,0x0}, {0x1CF,0x49,0x30C,0x0}, 
+  {0x1D0,0x69,0x30C,0x0}, {0x1D1,0x4F,0x30C,0x0}, {0x1D2,0x6F,0x30C,0x0}, 
+  {0x1D3,0x55,0x30C,0x0}, {0x1D4,0x75,0x30C,0x0}, {0x1D5,0xDC,0x304,0x0}, 
+  {0x1D6,0xFC,0x304,0x0}, {0x1D7,0xDC,0x301,0x0}, {0x1D8,0xFC,0x301,0x0}, 
+  {0x1D9,0xDC,0x30C,0x0}, {0x1DA,0xFC,0x30C,0x0}, {0x1DB,0xDC,0x300,0x0}, 
+  {0x1DC,0xFC,0x300,0x0}, {0x1DE,0xC4,0x304,0x0}, {0x1DF,0xE4,0x304,0x0}, 
+  {0x1E0,0x41,0x307,0x304}, {0x1E1,0x61,0x307,0x304}, {0x1E2,0xC6,0x304,0x0}, 
+  {0x1E3,0xE6,0x304,0x0}, {0x1E6,0x47,0x30C,0x0}, {0x1E7,0x67,0x30C,0x0}, 
+  {0x1E8,0x4B,0x30C,0x0}, {0x1E9,0x6B,0x30C,0x0}, {0x1EA,0x4F,0x328,0x0}, 
+  {0x1EB,0x6F,0x328,0x0}, {0x1EC,0x1EA,0x304,0x0}, {0x1ED,0x1EB,0x304,0x0}, 
+  {0x1EE,0x1B7,0x30C,0x0}, {0x1EF,0x292,0x30C,0x0}, {0x1F0,0x6A,0x30C,0x0}, 
+  {0x1F4,0x47,0x301,0x0}, {0x1F5,0x67,0x301,0x0}, {0x1FA,0xC5,0x301,0x0}, 
+  {0x1FB,0xE5,0x301,0x0}, {0x1FC,0xC6,0x301,0x0}, {0x1FD,0xE6,0x301,0x0}, 
+  {0x1FE,0xD8,0x301,0x0}, {0x1FF,0xF8,0x301,0x0}, {0x200,0x41,0x30F,0x0}, 
+  {0x201,0x61,0x30F,0x0}, {0x202,0x41,0x311,0x0}, {0x203,0x61,0x311,0x0}, 
+  {0x204,0x45,0x30F,0x0}, {0x205,0x65,0x30F,0x0}, {0x206,0x45,0x311,0x0}, 
+  {0x207,0x65,0x311,0x0}, {0x208,0x49,0x30F,0x0}, {0x209,0x69,0x30F,0x0}, 
+  {0x20A,0x49,0x311,0x0}, {0x20B,0x69,0x311,0x0}, {0x20C,0x4F,0x30F,0x0}, 
+  {0x20D,0x6F,0x30F,0x0}, {0x20E,0x4F,0x311,0x0}, {0x20F,0x6F,0x311,0x0}, 
+  {0x210,0x52,0x30F,0x0}, {0x211,0x72,0x30F,0x0}, {0x212,0x52,0x311,0x0}, 
+  {0x213,0x72,0x311,0x0}, {0x214,0x55,0x30F,0x0}, {0x215,0x75,0x30F,0x0}, 
+  {0x216,0x55,0x311,0x0}, {0x217,0x75,0x311,0x0}, {0x310,0x306,0x307,0x0}, 
+  {0x340,0x300,0x0,0x0}, {0x341,0x301,0x0,0x0}, {0x343,0x313,0x0,0x0}, 
+  {0x344,0x308,0x30D,0x0}, {0x374,0x2B9,0x0,0x0}, {0x37E,0x3B,0x0,0x0}, 
+  {0x385,0xA8,0x30D,0x0}, {0x386,0x391,0x30D,0x0}, {0x387,0xB7,0x0,0x0}, 
+  {0x388,0x395,0x30D,0x0}, {0x389,0x397,0x30D,0x0}, {0x38A,0x399,0x30D,0x0}, 
+  {0x38C,0x39F,0x30D,0x0}, {0x38E,0x3A5,0x30D,0x0}, {0x38F,0x3A9,0x30D,0x0}, 
+  {0x390,0x3B9,0x344,0x0}, {0x3AA,0x399,0x308,0x0}, {0x3AB,0x3A5,0x308,0x0}, 
+  {0x3AC,0x3B1,0x30D,0x0}, {0x3AD,0x3B5,0x30D,0x0}, {0x3AE,0x3B7,0x30D,0x0}, 
+  {0x3AF,0x3B9,0x30D,0x0}, {0x3B0,0x3C5,0x344,0x0}, {0x3CA,0x3B9,0x308,0x0}, 
+  {0x3CB,0x3C5,0x308,0x0}, {0x3CC,0x3BF,0x30D,0x0}, {0x3CD,0x3C5,0x30D,0x0}, 
+  {0x3CE,0x3C9,0x30D,0x0}, {0x3D3,0x3D2,0x30D,0x0}, {0x3D4,0x3D2,0x308,0x0}, 
+  {0x401,0x415,0x308,0x0}, {0x403,0x413,0x301,0x0}, {0x407,0x406,0x308,0x0}, 
+  {0x40C,0x41A,0x301,0x0}, {0x40E,0x423,0x306,0x0}, {0x419,0x418,0x306,0x0}, 
+  {0x439,0x438,0x306,0x0}, {0x451,0x435,0x308,0x0}, {0x453,0x433,0x301,0x0}, 
+  {0x457,0x456,0x308,0x0}, {0x45C,0x43A,0x301,0x0}, {0x45E,0x443,0x306,0x0}, 
+  {0x476,0x474,0x30F,0x0}, {0x477,0x475,0x30F,0x0}, {0x4C1,0x416,0x306,0x0}, 
+  {0x4C2,0x436,0x306,0x0}, {0x4D0,0x410,0x306,0x0}, {0x4D1,0x430,0x306,0x0}, 
+  {0x4D2,0x410,0x308,0x0}, {0x4D3,0x430,0x308,0x0}, {0x4D6,0x415,0x306,0x0}, 
+  {0x4D7,0x435,0x306,0x0}, {0x4DA,0x4D8,0x308,0x0}, {0x4DB,0x4D9,0x308,0x0}, 
+  {0x4DC,0x416,0x308,0x0}, {0x4DD,0x436,0x308,0x0}, {0x4DE,0x417,0x308,0x0}, 
+  {0x4DF,0x437,0x308,0x0}, {0x4E2,0x418,0x304,0x0}, {0x4E3,0x438,0x304,0x0}, 
+  {0x4E4,0x418,0x308,0x0}, {0x4E5,0x438,0x308,0x0}, {0x4E6,0x41E,0x308,0x0}, 
+  {0x4E7,0x43E,0x308,0x0}, {0x4EA,0x4E8,0x308,0x0}, {0x4EB,0x4E9,0x308,0x0}, 
+  {0x4EE,0x423,0x304,0x0}, {0x4EF,0x443,0x304,0x0}, {0x4F0,0x423,0x308,0x0}, 
+  {0x4F1,0x443,0x308,0x0}, {0x4F2,0x423,0x30B,0x0}, {0x4F3,0x443,0x30B,0x0}, 
+  {0x4F4,0x427,0x308,0x0}, {0x4F5,0x447,0x308,0x0}, {0x4F8,0x42B,0x308,0x0}, 
+  {0x4F9,0x44B,0x308,0x0}, {0x929,0x928,0x93C,0x0}, {0x931,0x930,0x93C,0x0}, 
+  {0x934,0x933,0x93C,0x0}, {0x958,0x915,0x93C,0x0}, {0x959,0x916,0x93C,0x0}, 
+  {0x95A,0x917,0x93C,0x0}, {0x95B,0x91C,0x93C,0x0}, {0x95C,0x921,0x93C,0x0}, 
+  {0x95D,0x922,0x93C,0x0}, {0x95E,0x92B,0x93C,0x0}, {0x95F,0x92F,0x93C,0x0}, 
+  {0x9B0,0x9AC,0x9BC,0x0}, {0x9CB,0x9C7,0x9BE,0x0}, {0x9CC,0x9C7,0x9D7,0x0}, 
+  {0x9DC,0x9A1,0x9BC,0x0}, {0x9DD,0x9A2,0x9BC,0x0}, {0x9DF,0x9AF,0x9BC,0x0}, 
+  {0xA59,0xA16,0xA3C,0x0}, {0xA5A,0xA17,0xA3C,0x0}, {0xA5B,0xA1C,0xA3C,0x0}, 
+  {0xA5C,0xA21,0xA3C,0x0}, {0xA5E,0xA2B,0xA3C,0x0}, {0xB48,0xB47,0xB56,0x0}, 
+  {0xB4B,0xB47,0xB3E,0x0}, {0xB4C,0xB47,0xB57,0x0}, {0xB5C,0xB21,0xB3C,0x0}, 
+  {0xB5D,0xB22,0xB3C,0x0}, {0xB5F,0xB2F,0xB3C,0x0}, {0xB94,0xB92,0xBD7,0x0}, 
+  {0xBCA,0xBC6,0xBBE,0x0}, {0xBCB,0xBC7,0xBBE,0x0}, {0xBCC,0xBC6,0xBD7,0x0}, 
+  {0xC48,0xC46,0xC56,0x0}, {0xCC0,0xCBF,0xCD5,0x0}, {0xCC7,0xCC6,0xCD5,0x0}, 
+  {0xCC8,0xCC6,0xCD6,0x0}, {0xCCA,0xCC6,0xCC2,0x0}, {0xCCB,0xCC6,0xCC2,0xCD5}, 
+  {0xD4A,0xD46,0xD3E,0x0}, {0xD4B,0xD47,0xD3E,0x0}, {0xD4C,0xD46,0xD57,0x0}, 
+  {0xE33,0xE4D,0xE32,0x0}, {0xEB3,0xECD,0xEB2,0x0}, {0xF43,0xF42,0xFB7,0x0}, 
+  {0xF4D,0xF4C,0xFB7,0x0}, {0xF52,0xF51,0xFB7,0x0}, {0xF57,0xF56,0xFB7,0x0}, 
+  {0xF5C,0xF5B,0xFB7,0x0}, {0xF69,0xF40,0xFB5,0x0}, {0xF73,0xF72,0xF71,0x0}, 
+  {0xF75,0xF71,0xF74,0x0}, {0xF76,0xFB2,0xF80,0x0}, {0xF77,0xF76,0xF71,0x0}, 
+  {0xF78,0xFB3,0xF80,0x0}, {0xF79,0xF78,0xF71,0x0}, {0xF81,0xF80,0xF71,0x0}, 
+  {0xF93,0xF92,0xFB7,0x0}, {0xF9D,0xF9C,0xFB7,0x0}, {0xFA2,0xFA1,0xFB7,0x0}, 
+  {0xFA7,0xFA6,0xFB7,0x0}, {0xFAC,0xFAB,0xFB7,0x0}, {0xFB9,0xF90,0xFB5,0x0}, 
+  {0x1E00,0x41,0x325,0x0}, {0x1E01,0x61,0x325,0x0}, {0x1E02,0x42,0x307,0x0}, 
+  {0x1E03,0x62,0x307,0x0}, {0x1E04,0x42,0x323,0x0}, {0x1E05,0x62,0x323,0x0}, 
+  {0x1E06,0x42,0x331,0x0}, {0x1E07,0x62,0x331,0x0}, {0x1E08,0xC7,0x301,0x0}, 
+  {0x1E09,0xE7,0x301,0x0}, {0x1E0A,0x44,0x307,0x0}, {0x1E0B,0x64,0x307,0x0}, 
+  {0x1E0C,0x44,0x323,0x0}, {0x1E0D,0x64,0x323,0x0}, {0x1E0E,0x44,0x331,0x0}, 
+  {0x1E0F,0x64,0x331,0x0}, {0x1E10,0x44,0x327,0x0}, {0x1E11,0x64,0x327,0x0}, 
+  {0x1E12,0x44,0x32D,0x0}, {0x1E13,0x64,0x32D,0x0}, {0x1E14,0x112,0x300,0x0}, 
+  {0x1E15,0x113,0x300,0x0}, {0x1E16,0x112,0x301,0x0}, {0x1E17,0x113,0x301,0x0}, 
+  {0x1E18,0x45,0x32D,0x0}, {0x1E19,0x65,0x32D,0x0}, {0x1E1A,0x45,0x330,0x0}, 
+  {0x1E1B,0x65,0x330,0x0}, {0x1E1C,0x114,0x327,0x0}, {0x1E1D,0x115,0x327,0x0}, 
+  {0x1E1E,0x46,0x307,0x0}, {0x1E1F,0x66,0x307,0x0}, {0x1E20,0x47,0x304,0x0}, 
+  {0x1E21,0x67,0x304,0x0}, {0x1E22,0x48,0x307,0x0}, {0x1E23,0x68,0x307,0x0}, 
+  {0x1E24,0x48,0x323,0x0}, {0x1E25,0x68,0x323,0x0}, {0x1E26,0x48,0x308,0x0}, 
+  {0x1E27,0x68,0x308,0x0}, {0x1E28,0x48,0x327,0x0}, {0x1E29,0x68,0x327,0x0}, 
+  {0x1E2A,0x48,0x32E,0x0}, {0x1E2B,0x68,0x32E,0x0}, {0x1E2C,0x49,0x330,0x0}, 
+  {0x1E2D,0x69,0x330,0x0}, {0x1E2E,0xCF,0x301,0x0}, {0x1E2F,0xEF,0x301,0x0}, 
+  {0x1E30,0x4B,0x301,0x0}, {0x1E31,0x6B,0x301,0x0}, {0x1E32,0x4B,0x323,0x0}, 
+  {0x1E33,0x6B,0x323,0x0}, {0x1E34,0x4B,0x331,0x0}, {0x1E35,0x6B,0x331,0x0}, 
+  {0x1E36,0x4C,0x323,0x0}, {0x1E37,0x6C,0x323,0x0}, {0x1E38,0x1E36,0x304,0x0}, 
+  {0x1E39,0x1E37,0x304,0x0}, {0x1E3A,0x4C,0x331,0x0}, {0x1E3B,0x6C,0x331,0x0}, 
+  {0x1E3C,0x4C,0x32D,0x0}, {0x1E3D,0x6C,0x32D,0x0}, {0x1E3E,0x4D,0x301,0x0}, 
+  {0x1E3F,0x6D,0x301,0x0}, {0x1E40,0x4D,0x307,0x0}, {0x1E41,0x6D,0x307,0x0}, 
+  {0x1E42,0x4D,0x323,0x0}, {0x1E43,0x6D,0x323,0x0}, {0x1E44,0x4E,0x307,0x0}, 
+  {0x1E45,0x6E,0x307,0x0}, {0x1E46,0x4E,0x323,0x0}, {0x1E47,0x6E,0x323,0x0}, 
+  {0x1E48,0x4E,0x331,0x0}, {0x1E49,0x6E,0x331,0x0}, {0x1E4A,0x4E,0x32D,0x0}, 
+  {0x1E4B,0x6E,0x32D,0x0}, {0x1E4C,0xD5,0x301,0x0}, {0x1E4D,0xF5,0x301,0x0}, 
+  {0x1E4E,0xD5,0x308,0x0}, {0x1E4F,0xF5,0x308,0x0}, {0x1E50,0x14C,0x300,0x0}, 
+  {0x1E51,0x14D,0x300,0x0}, {0x1E52,0x14C,0x301,0x0}, {0x1E53,0x14D,0x301,0x0}, 
+  {0x1E54,0x50,0x301,0x0}, {0x1E55,0x70,0x301,0x0}, {0x1E56,0x50,0x307,0x0}, 
+  {0x1E57,0x70,0x307,0x0}, {0x1E58,0x52,0x307,0x0}, {0x1E59,0x72,0x307,0x0}, 
+  {0x1E5A,0x52,0x323,0x0}, {0x1E5B,0x72,0x323,0x0}, {0x1E5C,0x1E5A,0x304,0x0}, 
+  {0x1E5D,0x1E5B,0x304,0x0}, {0x1E5E,0x52,0x331,0x0}, {0x1E5F,0x72,0x331,0x0}, 
+  {0x1E60,0x53,0x307,0x0}, {0x1E61,0x73,0x307,0x0}, {0x1E62,0x53,0x323,0x0}, 
+  {0x1E63,0x73,0x323,0x0}, {0x1E64,0x15A,0x307,0x0}, {0x1E65,0x15B,0x307,0x0}, 
+  {0x1E66,0x160,0x307,0x0}, {0x1E67,0x161,0x307,0x0}, {0x1E68,0x1E62,0x307,0x0}, 
+  {0x1E69,0x1E63,0x307,0x0}, {0x1E6A,0x54,0x307,0x0}, {0x1E6B,0x74,0x307,0x0}, 
+  {0x1E6C,0x54,0x323,0x0}, {0x1E6D,0x74,0x323,0x0}, {0x1E6E,0x54,0x331,0x0}, 
+  {0x1E6F,0x74,0x331,0x0}, {0x1E70,0x54,0x32D,0x0}, {0x1E71,0x74,0x32D,0x0}, 
+  {0x1E72,0x55,0x324,0x0}, {0x1E73,0x75,0x324,0x0}, {0x1E74,0x55,0x330,0x0}, 
+  {0x1E75,0x75,0x330,0x0}, {0x1E76,0x55,0x32D,0x0}, {0x1E77,0x75,0x32D,0x0}, 
+  {0x1E78,0x168,0x301,0x0}, {0x1E79,0x169,0x301,0x0}, {0x1E7A,0x16A,0x308,0x0}, 
+  {0x1E7B,0x16B,0x308,0x0}, {0x1E7C,0x56,0x303,0x0}, {0x1E7D,0x76,0x303,0x0}, 
+  {0x1E7E,0x56,0x323,0x0}, {0x1E7F,0x76,0x323,0x0}, {0x1E80,0x57,0x300,0x0}, 
+  {0x1E81,0x77,0x300,0x0}, {0x1E82,0x57,0x301,0x0}, {0x1E83,0x77,0x301,0x0}, 
+  {0x1E84,0x57,0x308,0x0}, {0x1E85,0x77,0x308,0x0}, {0x1E86,0x57,0x307,0x0}, 
+  {0x1E87,0x77,0x307,0x0}, {0x1E88,0x57,0x323,0x0}, {0x1E89,0x77,0x323,0x0}, 
+  {0x1E8A,0x58,0x307,0x0}, {0x1E8B,0x78,0x307,0x0}, {0x1E8C,0x58,0x308,0x0}, 
+  {0x1E8D,0x78,0x308,0x0}, {0x1E8E,0x59,0x307,0x0}, {0x1E8F,0x79,0x307,0x0}, 
+  {0x1E90,0x5A,0x302,0x0}, {0x1E91,0x7A,0x302,0x0}, {0x1E92,0x5A,0x323,0x0}, 
+  {0x1E93,0x7A,0x323,0x0}, {0x1E94,0x5A,0x331,0x0}, {0x1E95,0x7A,0x331,0x0}, 
+  {0x1E96,0x68,0x331,0x0}, {0x1E97,0x74,0x308,0x0}, {0x1E98,0x77,0x30A,0x0}, 
+  {0x1E99,0x79,0x30A,0x0}, {0x1E9B,0x17F,0x307,0x0}, {0x1EA0,0x41,0x323,0x0}, 
+  {0x1EA1,0x61,0x323,0x0}, {0x1EA2,0x41,0x309,0x0}, {0x1EA3,0x61,0x309,0x0}, 
+  {0x1EA4,0xC2,0x301,0x0}, {0x1EA5,0xE2,0x301,0x0}, {0x1EA6,0xC2,0x300,0x0}, 
+  {0x1EA7,0xE2,0x300,0x0}, {0x1EA8,0xC2,0x309,0x0}, {0x1EA9,0xE2,0x309,0x0}, 
+  {0x1EAA,0xC2,0x303,0x0}, {0x1EAB,0xE2,0x303,0x0}, {0x1EAC,0xC2,0x323,0x0}, 
+  {0x1EAD,0xE2,0x323,0x0}, {0x1EAE,0x102,0x301,0x0}, {0x1EAF,0x103,0x301,0x0}, 
+  {0x1EB0,0x102,0x300,0x0}, {0x1EB1,0x103,0x300,0x0}, {0x1EB2,0x102,0x309,0x0}, 
+  {0x1EB3,0x103,0x309,0x0}, {0x1EB4,0x102,0x303,0x0}, {0x1EB5,0x103,0x303,0x0}, 
+  {0x1EB6,0x102,0x323,0x0}, {0x1EB7,0x103,0x323,0x0}, {0x1EB8,0x45,0x323,0x0}, 
+  {0x1EB9,0x65,0x323,0x0}, {0x1EBA,0x45,0x309,0x0}, {0x1EBB,0x65,0x309,0x0}, 
+  {0x1EBC,0x45,0x303,0x0}, {0x1EBD,0x65,0x303,0x0}, {0x1EBE,0xCA,0x301,0x0}, 
+  {0x1EBF,0xEA,0x301,0x0}, {0x1EC0,0xCA,0x300,0x0}, {0x1EC1,0xEA,0x300,0x0}, 
+  {0x1EC2,0xCA,0x309,0x0}, {0x1EC3,0xEA,0x309,0x0}, {0x1EC4,0xCA,0x303,0x0}, 
+  {0x1EC5,0xEA,0x303,0x0}, {0x1EC6,0xCA,0x323,0x0}, {0x1EC7,0xEA,0x323,0x0}, 
+  {0x1EC8,0x49,0x309,0x0}, {0x1EC9,0x69,0x309,0x0}, {0x1ECA,0x49,0x323,0x0}, 
+  {0x1ECB,0x69,0x323,0x0}, {0x1ECC,0x4F,0x323,0x0}, {0x1ECD,0x6F,0x323,0x0}, 
+  {0x1ECE,0x4F,0x309,0x0}, {0x1ECF,0x6F,0x309,0x0}, {0x1ED0,0xD4,0x301,0x0}, 
+  {0x1ED1,0xF4,0x301,0x0}, {0x1ED2,0xD4,0x300,0x0}, {0x1ED3,0xF4,0x300,0x0}, 
+  {0x1ED4,0xD4,0x309,0x0}, {0x1ED5,0xF4,0x309,0x0}, {0x1ED6,0xD4,0x303,0x0}, 
+  {0x1ED7,0xF4,0x303,0x0}, {0x1ED8,0xD4,0x323,0x0}, {0x1ED9,0xF4,0x323,0x0}, 
+  {0x1EDA,0x1A0,0x301,0x0}, {0x1EDB,0x1A1,0x301,0x0}, {0x1EDC,0x1A0,0x300,0x0}, 
+  {0x1EDD,0x1A1,0x300,0x0}, {0x1EDE,0x1A0,0x309,0x0}, {0x1EDF,0x1A1,0x309,0x0}, 
+  {0x1EE0,0x1A0,0x303,0x0}, {0x1EE1,0x1A1,0x303,0x0}, {0x1EE2,0x1A0,0x323,0x0}, 
+  {0x1EE3,0x1A1,0x323,0x0}, {0x1EE4,0x55,0x323,0x0}, {0x1EE5,0x75,0x323,0x0}, 
+  {0x1EE6,0x55,0x309,0x0}, {0x1EE7,0x75,0x309,0x0}, {0x1EE8,0x1AF,0x301,0x0}, 
+  {0x1EE9,0x1B0,0x301,0x0}, {0x1EEA,0x1AF,0x300,0x0}, {0x1EEB,0x1B0,0x300,0x0}, 
+  {0x1EEC,0x1AF,0x309,0x0}, {0x1EED,0x1B0,0x309,0x0}, {0x1EEE,0x1AF,0x303,0x0}, 
+  {0x1EEF,0x1B0,0x303,0x0}, {0x1EF0,0x1AF,0x323,0x0}, {0x1EF1,0x1B0,0x323,0x0}, 
+  {0x1EF2,0x59,0x300,0x0}, {0x1EF3,0x79,0x300,0x0}, {0x1EF4,0x59,0x323,0x0}, 
+  {0x1EF5,0x79,0x323,0x0}, {0x1EF6,0x59,0x309,0x0}, {0x1EF7,0x79,0x309,0x0}, 
+  {0x1EF8,0x59,0x303,0x0}, {0x1EF9,0x79,0x303,0x0}, {0x1F00,0x3B1,0x313,0x0}, 
+  {0x1F01,0x3B1,0x314,0x0}, {0x1F02,0x1F00,0x300,0x0}, {0x1F03,0x1F01,0x300,0x0}, 
+  {0x1F04,0x1F00,0x301,0x0}, {0x1F05,0x1F01,0x301,0x0}, {0x1F06,0x1F00,0x342,0x0}, 
+  {0x1F07,0x1F01,0x342,0x0}, {0x1F08,0x391,0x313,0x0}, {0x1F09,0x391,0x314,0x0}, 
+  {0x1F0A,0x1F08,0x300,0x0}, {0x1F0B,0x1F09,0x300,0x0}, {0x1F0C,0x1F08,0x301,0x0}, 
+  {0x1F0D,0x1F09,0x301,0x0}, {0x1F0E,0x1F08,0x342,0x0}, {0x1F0F,0x1F09,0x342,0x0}, 
+  {0x1F10,0x3B5,0x313,0x0}, {0x1F11,0x3B5,0x314,0x0}, {0x1F12,0x1F10,0x300,0x0}, 
+  {0x1F13,0x1F11,0x300,0x0}, {0x1F14,0x1F10,0x301,0x0}, {0x1F15,0x1F11,0x301,0x0}, 
+  {0x1F18,0x395,0x313,0x0}, {0x1F19,0x395,0x314,0x0}, {0x1F1A,0x1F18,0x300,0x0}, 
+  {0x1F1B,0x1F19,0x300,0x0}, {0x1F1C,0x1F18,0x301,0x0}, {0x1F1D,0x1F19,0x301,0x0}, 
+  {0x1F20,0x3B7,0x313,0x0}, {0x1F21,0x3B7,0x314,0x0}, {0x1F22,0x1F20,0x300,0x0}, 
+  {0x1F23,0x1F21,0x300,0x0}, {0x1F24,0x1F20,0x301,0x0}, {0x1F25,0x1F21,0x301,0x0}, 
+  {0x1F26,0x1F20,0x342,0x0}, {0x1F27,0x1F21,0x342,0x0}, {0x1F28,0x397,0x313,0x0}, 
+  {0x1F29,0x397,0x314,0x0}, {0x1F2A,0x1F28,0x300,0x0}, {0x1F2B,0x1F29,0x300,0x0}, 
+  {0x1F2C,0x1F28,0x301,0x0}, {0x1F2D,0x1F29,0x301,0x0}, {0x1F2E,0x1F28,0x342,0x0}, 
+  {0x1F2F,0x1F29,0x342,0x0}, {0x1F30,0x3B9,0x313,0x0}, {0x1F31,0x3B9,0x314,0x0}, 
+  {0x1F32,0x1F30,0x300,0x0}, {0x1F33,0x1F31,0x300,0x0}, {0x1F34,0x1F30,0x301,0x0}, 
+  {0x1F35,0x1F31,0x301,0x0}, {0x1F36,0x1F30,0x342,0x0}, {0x1F37,0x1F31,0x342,0x0}, 
+  {0x1F38,0x399,0x313,0x0}, {0x1F39,0x399,0x314,0x0}, {0x1F3A,0x1F38,0x300,0x0}, 
+  {0x1F3B,0x1F39,0x300,0x0}, {0x1F3C,0x1F38,0x301,0x0}, {0x1F3D,0x1F39,0x301,0x0}, 
+  {0x1F3E,0x1F38,0x342,0x0}, {0x1F3F,0x1F39,0x342,0x0}, {0x1F40,0x3BF,0x313,0x0}, 
+  {0x1F41,0x3BF,0x314,0x0}, {0x1F42,0x1F40,0x300,0x0}, {0x1F43,0x1F41,0x300,0x0}, 
+  {0x1F44,0x1F40,0x301,0x0}, {0x1F45,0x1F41,0x301,0x0}, {0x1F48,0x39F,0x313,0x0}, 
+  {0x1F49,0x39F,0x314,0x0}, {0x1F4A,0x1F48,0x300,0x0}, {0x1F4B,0x1F49,0x300,0x0}, 
+  {0x1F4C,0x1F48,0x301,0x0}, {0x1F4D,0x1F49,0x301,0x0}, {0x1F50,0x3C5,0x313,0x0}, 
+  {0x1F51,0x3C5,0x314,0x0}, {0x1F52,0x1F50,0x300,0x0}, {0x1F53,0x1F51,0x300,0x0}, 
+  {0x1F54,0x1F50,0x301,0x0}, {0x1F55,0x1F51,0x301,0x0}, {0x1F56,0x1F50,0x342,0x0}, 
+  {0x1F57,0x1F51,0x342,0x0}, {0x1F59,0x3A5,0x314,0x0}, {0x1F5B,0x1F59,0x300,0x0}, 
+  {0x1F5D,0x1F59,0x301,0x0}, {0x1F5F,0x1F59,0x342,0x0}, {0x1F60,0x3C9,0x313,0x0}, 
+  {0x1F61,0x3C9,0x314,0x0}, {0x1F62,0x1F60,0x300,0x0}, {0x1F63,0x1F61,0x300,0x0}, 
+  {0x1F64,0x1F60,0x301,0x0}, {0x1F65,0x1F61,0x301,0x0}, {0x1F66,0x1F60,0x342,0x0}, 
+  {0x1F67,0x1F61,0x342,0x0}, {0x1F68,0x3A9,0x313,0x0}, {0x1F69,0x3A9,0x314,0x0}, 
+  {0x1F6A,0x1F68,0x300,0x0}, {0x1F6B,0x1F69,0x300,0x0}, {0x1F6C,0x1F68,0x301,0x0}, 
+  {0x1F6D,0x1F69,0x301,0x0}, {0x1F6E,0x1F68,0x342,0x0}, {0x1F6F,0x1F69,0x342,0x0}, 
+  {0x1F70,0x3B1,0x300,0x0}, {0x1F71,0x3B1,0x301,0x0}, {0x1F72,0x3B5,0x300,0x0}, 
+  {0x1F73,0x3B5,0x301,0x0}, {0x1F74,0x3B7,0x300,0x0}, {0x1F75,0x3B7,0x301,0x0}, 
+  {0x1F76,0x3B9,0x300,0x0}, {0x1F77,0x3B9,0x301,0x0}, {0x1F78,0x3BF,0x300,0x0}, 
+  {0x1F79,0x3BF,0x301,0x0}, {0x1F7A,0x3C5,0x300,0x0}, {0x1F7B,0x3C5,0x301,0x0}, 
+  {0x1F7C,0x3C9,0x300,0x0}, {0x1F7D,0x3C9,0x301,0x0}, {0x1F80,0x1F00,0x345,0x0}, 
+  {0x1F81,0x1F01,0x345,0x0}, {0x1F82,0x1F02,0x345,0x0}, {0x1F83,0x1F03,0x345,0x0}, 
+  {0x1F84,0x1F04,0x345,0x0}, {0x1F85,0x1F05,0x345,0x0}, {0x1F86,0x1F06,0x345,0x0}, 
+  {0x1F87,0x1F07,0x345,0x0}, {0x1F88,0x1F08,0x345,0x0}, {0x1F89,0x1F09,0x345,0x0}, 
+  {0x1F8A,0x1F0A,0x345,0x0}, {0x1F8B,0x1F0B,0x345,0x0}, {0x1F8C,0x1F0C,0x345,0x0}, 
+  {0x1F8D,0x1F0D,0x345,0x0}, {0x1F8E,0x1F0E,0x345,0x0}, {0x1F8F,0x1F0F,0x345,0x0}, 
+  {0x1F90,0x1F20,0x345,0x0}, {0x1F91,0x1F21,0x345,0x0}, {0x1F92,0x1F22,0x345,0x0}, 
+  {0x1F93,0x1F23,0x345,0x0}, {0x1F94,0x1F24,0x345,0x0}, {0x1F95,0x1F25,0x345,0x0}, 
+  {0x1F96,0x1F26,0x345,0x0}, {0x1F97,0x1F27,0x345,0x0}, {0x1F98,0x1F28,0x345,0x0}, 
+  {0x1F99,0x1F29,0x345,0x0}, {0x1F9A,0x1F2A,0x345,0x0}, {0x1F9B,0x1F2B,0x345,0x0}, 
+  {0x1F9C,0x1F2C,0x345,0x0}, {0x1F9D,0x1F2D,0x345,0x0}, {0x1F9E,0x1F2E,0x345,0x0}, 
+  {0x1F9F,0x1F2F,0x345,0x0}, {0x1FA0,0x1F60,0x345,0x0}, {0x1FA1,0x1F61,0x345,0x0}, 
+  {0x1FA2,0x1F62,0x345,0x0}, {0x1FA3,0x1F63,0x345,0x0}, {0x1FA4,0x1F64,0x345,0x0}, 
+  {0x1FA5,0x1F65,0x345,0x0}, {0x1FA6,0x1F66,0x345,0x0}, {0x1FA7,0x1F67,0x345,0x0}, 
+  {0x1FA8,0x1F68,0x345,0x0}, {0x1FA9,0x1F69,0x345,0x0}, {0x1FAA,0x1F6A,0x345,0x0}, 
+  {0x1FAB,0x1F6B,0x345,0x0}, {0x1FAC,0x1F6C,0x345,0x0}, {0x1FAD,0x1F6D,0x345,0x0}, 
+  {0x1FAE,0x1F6E,0x345,0x0}, {0x1FAF,0x1F6F,0x345,0x0}, {0x1FB0,0x3B1,0x306,0x0}, 
+  {0x1FB1,0x3B1,0x304,0x0}, {0x1FB2,0x1F70,0x345,0x0}, {0x1FB3,0x3B1,0x345,0x0}, 
+  {0x1FB4,0x1F71,0x345,0x0}, {0x1FB6,0x3B1,0x342,0x0}, {0x1FB7,0x1FB6,0x345,0x0}, 
+  {0x1FB8,0x391,0x306,0x0}, {0x1FB9,0x391,0x304,0x0}, {0x1FBA,0x391,0x300,0x0}, 
+  {0x1FBB,0x391,0x301,0x0}, {0x1FBC,0x391,0x345,0x0}, {0x1FBE,0x3B9,0x0,0x0}, 
+  {0x1FC1,0xA8,0x342,0x0}, {0x1FC2,0x1F74,0x345,0x0}, {0x1FC3,0x3B7,0x345,0x0}, 
+  {0x1FC4,0x1F75,0x345,0x0}, {0x1FC6,0x3B7,0x342,0x0}, {0x1FC7,0x1FC6,0x345,0x0}, 
+  {0x1FC8,0x395,0x300,0x0}, {0x1FC9,0x395,0x301,0x0}, {0x1FCA,0x397,0x300,0x0}, 
+  {0x1FCB,0x397,0x301,0x0}, {0x1FCC,0x397,0x345,0x0}, {0x1FCD,0x1FBF,0x300,0x0}, 
+  {0x1FCE,0x1FBF,0x301,0x0}, {0x1FCF,0x1FBF,0x342,0x0}, {0x1FD0,0x3B9,0x306,0x0}, 
+  {0x1FD1,0x3B9,0x304,0x0}, {0x1FD2,0x3CA,0x300,0x0}, {0x1FD3,0x3CA,0x301,0x0}, 
+  {0x1FD6,0x3B9,0x342,0x0}, {0x1FD7,0x3CA,0x342,0x0}, {0x1FD8,0x399,0x306,0x0}, 
+  {0x1FD9,0x399,0x304,0x0}, {0x1FDA,0x399,0x300,0x0}, {0x1FDB,0x399,0x301,0x0}, 
+  {0x1FDD,0x1FFE,0x300,0x0}, {0x1FDE,0x1FFE,0x301,0x0}, {0x1FDF,0x1FFE,0x342,0x0}, 
+  {0x1FE0,0x3C5,0x306,0x0}, {0x1FE1,0x3C5,0x304,0x0}, {0x1FE2,0x3CB,0x300,0x0}, 
+  {0x1FE3,0x3CB,0x301,0x0}, {0x1FE4,0x3C1,0x313,0x0}, {0x1FE5,0x3C1,0x314,0x0}, 
+  {0x1FE6,0x3C5,0x342,0x0}, {0x1FE7,0x3CB,0x342,0x0}, {0x1FE8,0x3A5,0x306,0x0}, 
+  {0x1FE9,0x3A5,0x304,0x0}, {0x1FEA,0x3A5,0x300,0x0}, {0x1FEB,0x3A5,0x301,0x0}, 
+  {0x1FEC,0x3A1,0x314,0x0}, {0x1FED,0xA8,0x300,0x0}, {0x1FEE,0xA8,0x301,0x0}, 
+  {0x1FEF,0x60,0x0,0x0}, {0x1FF2,0x1F7C,0x345,0x0}, {0x1FF3,0x3C9,0x345,0x0}, 
+  {0x1FF4,0x1F79,0x345,0x0}, {0x1FF6,0x3C9,0x342,0x0}, {0x1FF7,0x1FF6,0x345,0x0}, 
+  {0x1FF8,0x39F,0x300,0x0}, {0x1FF9,0x39F,0x301,0x0}, {0x1FFA,0x3A9,0x300,0x0}, 
+  {0x1FFB,0x3A9,0x301,0x0}, {0x1FFC,0x3A9,0x345,0x0}, {0x1FFD,0xB4,0x0,0x0}, 
+  {0x2000,0x2002,0x0,0x0}, {0x2001,0x2003,0x0,0x0}, {0x2126,0x3A9,0x0,0x0}, 
+  {0x212A,0x4B,0x0,0x0}, {0x212B,0xC5,0x0,0x0}, {0x2204,0x2203,0x338,0x0}, 
+  {0x2209,0x2208,0x338,0x0}, {0x220C,0x220B,0x338,0x0}, {0x2224,0x2223,0x338,0x0}, 
+  {0x2226,0x2225,0x338,0x0}, {0x2241,0x7E,0x338,0x0}, {0x2244,0x2243,0x338,0x0}, 
+  {0x2247,0x2245,0x338,0x0}, {0x2249,0x2248,0x338,0x0}, {0x2260,0x3D,0x338,0x0}, 
+  {0x2262,0x2261,0x338,0x0}, {0x226D,0x224D,0x338,0x0}, {0x226E,0x3C,0x338,0x0}, 
+  {0x226F,0x3E,0x338,0x0}, {0x2270,0x2264,0x338,0x0}, {0x2271,0x2265,0x338,0x0}, 
+  {0x2274,0x2272,0x338,0x0}, {0x2275,0x2273,0x338,0x0}, {0x2278,0x2276,0x338,0x0}, 
+  {0x2279,0x2277,0x338,0x0}, {0x2280,0x227A,0x338,0x0}, {0x2281,0x227B,0x338,0x0}, 
+  {0x2284,0x2282,0x338,0x0}, {0x2285,0x2283,0x338,0x0}, {0x2288,0x2286,0x338,0x0}, 
+  {0x2289,0x2287,0x338,0x0}, {0x22AC,0x22A2,0x338,0x0}, {0x22AD,0x22A8,0x338,0x0}, 
+  {0x22AE,0x22A9,0x338,0x0}, {0x22AF,0x22AB,0x338,0x0}, {0x22E0,0x227C,0x338,0x0}, 
+  {0x22E1,0x227D,0x338,0x0}, {0x22E2,0x2291,0x338,0x0}, {0x22E3,0x2292,0x338,0x0}, 
+  {0x22EA,0x22B2,0x338,0x0}, {0x22EB,0x22B3,0x338,0x0}, {0x22EC,0x22B4,0x338,0x0}, 
+  {0x22ED,0x22B5,0x338,0x0}, {0x2329,0x3008,0x0,0x0}, {0x232A,0x3009,0x0,0x0}, 
+  {0x304C,0x304B,0x3099,0x0}, {0x304E,0x304D,0x3099,0x0}, {0x3050,0x304F,0x3099,0x0}, 
+  {0x3052,0x3051,0x3099,0x0}, {0x3054,0x3053,0x3099,0x0}, {0x3056,0x3055,0x3099,0x0}, 
+  {0x3058,0x3057,0x3099,0x0}, {0x305A,0x3059,0x3099,0x0}, {0x305C,0x305B,0x3099,0x0}, 
+  {0x305E,0x305D,0x3099,0x0}, {0x3060,0x305F,0x3099,0x0}, {0x3062,0x3061,0x3099,0x0}, 
+  {0x3065,0x3064,0x3099,0x0}, {0x3067,0x3066,0x3099,0x0}, {0x3069,0x3068,0x3099,0x0}, 
+  {0x3070,0x306F,0x3099,0x0}, {0x3071,0x306F,0x309A,0x0}, {0x3073,0x3072,0x3099,0x0}, 
+  {0x3074,0x3072,0x309A,0x0}, {0x3076,0x3075,0x3099,0x0}, {0x3077,0x3075,0x309A,0x0}, 
+  {0x3079,0x3078,0x3099,0x0}, {0x307A,0x3078,0x309A,0x0}, {0x307C,0x307B,0x3099,0x0}, 
+  {0x307D,0x307B,0x309A,0x0}, {0x3094,0x3046,0x3099,0x0}, {0x309E,0x309D,0x3099,0x0}, 
+  {0x30AC,0x30AB,0x3099,0x0}, {0x30AE,0x30AD,0x3099,0x0}, {0x30B0,0x30AF,0x3099,0x0}, 
+  {0x30B2,0x30B1,0x3099,0x0}, {0x30B4,0x30B3,0x3099,0x0}, {0x30B6,0x30B5,0x3099,0x0}, 
+  {0x30B8,0x30B7,0x3099,0x0}, {0x30BA,0x30B9,0x3099,0x0}, {0x30BC,0x30BB,0x3099,0x0}, 
+  {0x30BE,0x30BD,0x3099,0x0}, {0x30C0,0x30BF,0x3099,0x0}, {0x30C2,0x30C1,0x3099,0x0}, 
+  {0x30C5,0x30C4,0x3099,0x0}, {0x30C7,0x30C6,0x3099,0x0}, {0x30C9,0x30C8,0x3099,0x0}, 
+  {0x30D0,0x30CF,0x3099,0x0}, {0x30D1,0x30CF,0x309A,0x0}, {0x30D3,0x30D2,0x3099,0x0}, 
+  {0x30D4,0x30D2,0x309A,0x0}, {0x30D6,0x30D5,0x3099,0x0}, {0x30D7,0x30D5,0x309A,0x0}, 
+  {0x30D9,0x30D8,0x3099,0x0}, {0x30DA,0x30D8,0x309A,0x0}, {0x30DC,0x30DB,0x3099,0x0}, 
+  {0x30DD,0x30DB,0x309A,0x0}, {0x30F4,0x30A6,0x3099,0x0}, {0x30F7,0x30EF,0x3099,0x0}, 
+  {0x30F8,0x30F0,0x3099,0x0}, {0x30F9,0x30F1,0x3099,0x0}, {0x30FA,0x30F2,0x3099,0x0}, 
+  {0x30FE,0x30FD,0x3099,0x0}, {0xF900,0x8C48,0x0,0x0}, {0xF901,0x66F4,0x0,0x0}, 
+  {0xF902,0x8ECA,0x0,0x0}, {0xF903,0x8CC8,0x0,0x0}, {0xF904,0x6ED1,0x0,0x0}, 
+  {0xF905,0x4E32,0x0,0x0}, {0xF906,0x53E5,0x0,0x0}, {0xF907,0x9F9C,0x0,0x0}, 
+  {0xF908,0x9F9C,0x0,0x0}, {0xF909,0x5951,0x0,0x0}, {0xF90A,0x91D1,0x0,0x0}, 
+  {0xF90B,0x5587,0x0,0x0}, {0xF90C,0x5948,0x0,0x0}, {0xF90D,0x61F6,0x0,0x0}, 
+  {0xF90E,0x7669,0x0,0x0}, {0xF90F,0x7F85,0x0,0x0}, {0xF910,0x863F,0x0,0x0}, 
+  {0xF911,0x87BA,0x0,0x0}, {0xF912,0x88F8,0x0,0x0}, {0xF913,0x908F,0x0,0x0}, 
+  {0xF914,0x6A02,0x0,0x0}, {0xF915,0x6D1B,0x0,0x0}, {0xF916,0x70D9,0x0,0x0}, 
+  {0xF917,0x73DE,0x0,0x0}, {0xF918,0x843D,0x0,0x0}, {0xF919,0x916A,0x0,0x0}, 
+  {0xF91A,0x99F1,0x0,0x0}, {0xF91B,0x4E82,0x0,0x0}, {0xF91C,0x5375,0x0,0x0}, 
+  {0xF91D,0x6B04,0x0,0x0}, {0xF91E,0x721B,0x0,0x0}, {0xF91F,0x862D,0x0,0x0}, 
+  {0xF920,0x9E1E,0x0,0x0}, {0xF921,0x5D50,0x0,0x0}, {0xF922,0x6FEB,0x0,0x0}, 
+  {0xF923,0x85CD,0x0,0x0}, {0xF924,0x8964,0x0,0x0}, {0xF925,0x62C9,0x0,0x0}, 
+  {0xF926,0x81D8,0x0,0x0}, {0xF927,0x881F,0x0,0x0}, {0xF928,0x5ECA,0x0,0x0}, 
+  {0xF929,0x6717,0x0,0x0}, {0xF92A,0x6D6A,0x0,0x0}, {0xF92B,0x72FC,0x0,0x0}, 
+  {0xF92C,0x90CE,0x0,0x0}, {0xF92D,0x4F86,0x0,0x0}, {0xF92E,0x51B7,0x0,0x0}, 
+  {0xF92F,0x52DE,0x0,0x0}, {0xF930,0x64C4,0x0,0x0}, {0xF931,0x6AD3,0x0,0x0}, 
+  {0xF932,0x7210,0x0,0x0}, {0xF933,0x76E7,0x0,0x0}, {0xF934,0x8001,0x0,0x0}, 
+  {0xF935,0x8606,0x0,0x0}, {0xF936,0x865C,0x0,0x0}, {0xF937,0x8DEF,0x0,0x0}, 
+  {0xF938,0x9732,0x0,0x0}, {0xF939,0x9B6F,0x0,0x0}, {0xF93A,0x9DFA,0x0,0x0}, 
+  {0xF93B,0x788C,0x0,0x0}, {0xF93C,0x797F,0x0,0x0}, {0xF93D,0x7DA0,0x0,0x0}, 
+  {0xF93E,0x83C9,0x0,0x0}, {0xF93F,0x9304,0x0,0x0}, {0xF940,0x9E7F,0x0,0x0}, 
+  {0xF941,0x8AD6,0x0,0x0}, {0xF942,0x58DF,0x0,0x0}, {0xF943,0x5F04,0x0,0x0}, 
+  {0xF944,0x7C60,0x0,0x0}, {0xF945,0x807E,0x0,0x0}, {0xF946,0x7262,0x0,0x0}, 
+  {0xF947,0x78CA,0x0,0x0}, {0xF948,0x8CC2,0x0,0x0}, {0xF949,0x96F7,0x0,0x0}, 
+  {0xF94A,0x58D8,0x0,0x0}, {0xF94B,0x5C62,0x0,0x0}, {0xF94C,0x6A13,0x0,0x0}, 
+  {0xF94D,0x6DDA,0x0,0x0}, {0xF94E,0x6F0F,0x0,0x0}, {0xF94F,0x7D2F,0x0,0x0}, 
+  {0xF950,0x7E37,0x0,0x0}, {0xF951,0x96FB,0x0,0x0}, {0xF952,0x52D2,0x0,0x0}, 
+  {0xF953,0x808B,0x0,0x0}, {0xF954,0x51DC,0x0,0x0}, {0xF955,0x51CC,0x0,0x0}, 
+  {0xF956,0x7A1C,0x0,0x0}, {0xF957,0x7DBE,0x0,0x0}, {0xF958,0x83F1,0x0,0x0}, 
+  {0xF959,0x9675,0x0,0x0}, {0xF95A,0x8B80,0x0,0x0}, {0xF95B,0x62CF,0x0,0x0}, 
+  {0xF95C,0x6A02,0x0,0x0}, {0xF95D,0x8AFE,0x0,0x0}, {0xF95E,0x4E39,0x0,0x0}, 
+  {0xF95F,0x5BE7,0x0,0x0}, {0xF960,0x6012,0x0,0x0}, {0xF961,0x7387,0x0,0x0}, 
+  {0xF962,0x7570,0x0,0x0}, {0xF963,0x5317,0x0,0x0}, {0xF964,0x78FB,0x0,0x0}, 
+  {0xF965,0x4FBF,0x0,0x0}, {0xF966,0x5FA9,0x0,0x0}, {0xF967,0x4E0D,0x0,0x0}, 
+  {0xF968,0x6CCC,0x0,0x0}, {0xF969,0x6578,0x0,0x0}, {0xF96A,0x7D22,0x0,0x0}, 
+  {0xF96B,0x53C3,0x0,0x0}, {0xF96C,0x585E,0x0,0x0}, {0xF96D,0x7701,0x0,0x0}, 
+  {0xF96E,0x8449,0x0,0x0}, {0xF96F,0x8AAA,0x0,0x0}, {0xF970,0x6BBA,0x0,0x0}, 
+  {0xF971,0x8FB0,0x0,0x0}, {0xF972,0x6C88,0x0,0x0}, {0xF973,0x62FE,0x0,0x0}, 
+  {0xF974,0x82E5,0x0,0x0}, {0xF975,0x63A0,0x0,0x0}, {0xF976,0x7565,0x0,0x0}, 
+  {0xF977,0x4EAE,0x0,0x0}, {0xF978,0x5169,0x0,0x0}, {0xF979,0x51C9,0x0,0x0}, 
+  {0xF97A,0x6881,0x0,0x0}, {0xF97B,0x7CE7,0x0,0x0}, {0xF97C,0x826F,0x0,0x0}, 
+  {0xF97D,0x8AD2,0x0,0x0}, {0xF97E,0x91CF,0x0,0x0}, {0xF97F,0x52F5,0x0,0x0}, 
+  {0xF980,0x5442,0x0,0x0}, {0xF981,0x5973,0x0,0x0}, {0xF982,0x5EEC,0x0,0x0}, 
+  {0xF983,0x65C5,0x0,0x0}, {0xF984,0x6FFE,0x0,0x0}, {0xF985,0x792A,0x0,0x0}, 
+  {0xF986,0x95AD,0x0,0x0}, {0xF987,0x9A6A,0x0,0x0}, {0xF988,0x9E97,0x0,0x0}, 
+  {0xF989,0x9ECE,0x0,0x0}, {0xF98A,0x529B,0x0,0x0}, {0xF98B,0x66C6,0x0,0x0}, 
+  {0xF98C,0x6B77,0x0,0x0}, {0xF98D,0x8F62,0x0,0x0}, {0xF98E,0x5E74,0x0,0x0}, 
+  {0xF98F,0x6190,0x0,0x0}, {0xF990,0x6200,0x0,0x0}, {0xF991,0x649A,0x0,0x0}, 
+  {0xF992,0x6F23,0x0,0x0}, {0xF993,0x7149,0x0,0x0}, {0xF994,0x7489,0x0,0x0}, 
+  {0xF995,0x79CA,0x0,0x0}, {0xF996,0x7DF4,0x0,0x0}, {0xF997,0x806F,0x0,0x0}, 
+  {0xF998,0x8F26,0x0,0x0}, {0xF999,0x84EE,0x0,0x0}, {0xF99A,0x9023,0x0,0x0}, 
+  {0xF99B,0x934A,0x0,0x0}, {0xF99C,0x5217,0x0,0x0}, {0xF99D,0x52A3,0x0,0x0}, 
+  {0xF99E,0x54BD,0x0,0x0}, {0xF99F,0x70C8,0x0,0x0}, {0xF9A0,0x88C2,0x0,0x0}, 
+  {0xF9A1,0x8AAA,0x0,0x0}, {0xF9A2,0x5EC9,0x0,0x0}, {0xF9A3,0x5FF5,0x0,0x0}, 
+  {0xF9A4,0x637B,0x0,0x0}, {0xF9A5,0x6BAE,0x0,0x0}, {0xF9A6,0x7C3E,0x0,0x0}, 
+  {0xF9A7,0x7375,0x0,0x0}, {0xF9A8,0x4EE4,0x0,0x0}, {0xF9A9,0x56F9,0x0,0x0}, 
+  {0xF9AA,0x5BE7,0x0,0x0}, {0xF9AB,0x5DBA,0x0,0x0}, {0xF9AC,0x601C,0x0,0x0}, 
+  {0xF9AD,0x73B2,0x0,0x0}, {0xF9AE,0x7469,0x0,0x0}, {0xF9AF,0x7F9A,0x0,0x0}, 
+  {0xF9B0,0x8046,0x0,0x0}, {0xF9B1,0x9234,0x0,0x0}, {0xF9B2,0x96F6,0x0,0x0}, 
+  {0xF9B3,0x9748,0x0,0x0}, {0xF9B4,0x9818,0x0,0x0}, {0xF9B5,0x4F8B,0x0,0x0}, 
+  {0xF9B6,0x79AE,0x0,0x0}, {0xF9B7,0x91B4,0x0,0x0}, {0xF9B8,0x96B8,0x0,0x0}, 
+  {0xF9B9,0x60E1,0x0,0x0}, {0xF9BA,0x4E86,0x0,0x0}, {0xF9BB,0x50DA,0x0,0x0}, 
+  {0xF9BC,0x5BEE,0x0,0x0}, {0xF9BD,0x5C3F,0x0,0x0}, {0xF9BE,0x6599,0x0,0x0}, 
+  {0xF9BF,0x6A02,0x0,0x0}, {0xF9C0,0x71CE,0x0,0x0}, {0xF9C1,0x7642,0x0,0x0}, 
+  {0xF9C2,0x84FC,0x0,0x0}, {0xF9C3,0x907C,0x0,0x0}, {0xF9C4,0x9F8D,0x0,0x0}, 
+  {0xF9C5,0x6688,0x0,0x0}, {0xF9C6,0x962E,0x0,0x0}, {0xF9C7,0x5289,0x0,0x0}, 
+  {0xF9C8,0x677B,0x0,0x0}, {0xF9C9,0x67F3,0x0,0x0}, {0xF9CA,0x6D41,0x0,0x0}, 
+  {0xF9CB,0x6E9C,0x0,0x0}, {0xF9CC,0x7409,0x0,0x0}, {0xF9CD,0x7559,0x0,0x0}, 
+  {0xF9CE,0x786B,0x0,0x0}, {0xF9CF,0x7D10,0x0,0x0}, {0xF9D0,0x985E,0x0,0x0}, 
+  {0xF9D1,0x516D,0x0,0x0}, {0xF9D2,0x622E,0x0,0x0}, {0xF9D3,0x9678,0x0,0x0}, 
+  {0xF9D4,0x502B,0x0,0x0}, {0xF9D5,0x5D19,0x0,0x0}, {0xF9D6,0x6DEA,0x0,0x0}, 
+  {0xF9D7,0x8F2A,0x0,0x0}, {0xF9D8,0x5F8B,0x0,0x0}, {0xF9D9,0x6144,0x0,0x0}, 
+  {0xF9DA,0x6817,0x0,0x0}, {0xF9DB,0x7387,0x0,0x0}, {0xF9DC,0x9686,0x0,0x0}, 
+  {0xF9DD,0x5229,0x0,0x0}, {0xF9DE,0x540F,0x0,0x0}, {0xF9DF,0x5C65,0x0,0x0}, 
+  {0xF9E0,0x6613,0x0,0x0}, {0xF9E1,0x674E,0x0,0x0}, {0xF9E2,0x68A8,0x0,0x0}, 
+  {0xF9E3,0x6CE5,0x0,0x0}, {0xF9E4,0x7406,0x0,0x0}, {0xF9E5,0x75E2,0x0,0x0}, 
+  {0xF9E6,0x7F79,0x0,0x0}, {0xF9E7,0x88CF,0x0,0x0}, {0xF9E8,0x88E1,0x0,0x0}, 
+  {0xF9E9,0x91CC,0x0,0x0}, {0xF9EA,0x96E2,0x0,0x0}, {0xF9EB,0x533F,0x0,0x0}, 
+  {0xF9EC,0x6EBA,0x0,0x0}, {0xF9ED,0x541D,0x0,0x0}, {0xF9EE,0x71D0,0x0,0x0}, 
+  {0xF9EF,0x7498,0x0,0x0}, {0xF9F0,0x85FA,0x0,0x0}, {0xF9F1,0x96A3,0x0,0x0}, 
+  {0xF9F2,0x9C57,0x0,0x0}, {0xF9F3,0x9E9F,0x0,0x0}, {0xF9F4,0x6797,0x0,0x0}, 
+  {0xF9F5,0x6DCB,0x0,0x0}, {0xF9F6,0x81E8,0x0,0x0}, {0xF9F7,0x7ACB,0x0,0x0}, 
+  {0xF9F8,0x7B20,0x0,0x0}, {0xF9F9,0x7C92,0x0,0x0}, {0xF9FA,0x72C0,0x0,0x0}, 
+  {0xF9FB,0x7099,0x0,0x0}, {0xF9FC,0x8B58,0x0,0x0}, {0xF9FD,0x4EC0,0x0,0x0}, 
+  {0xF9FE,0x8336,0x0,0x0}, {0xF9FF,0x523A,0x0,0x0}, {0xFA00,0x5207,0x0,0x0}, 
+  {0xFA01,0x5EA6,0x0,0x0}, {0xFA02,0x62D3,0x0,0x0}, {0xFA03,0x7CD6,0x0,0x0}, 
+  {0xFA04,0x5B85,0x0,0x0}, {0xFA05,0x6D1E,0x0,0x0}, {0xFA06,0x66B4,0x0,0x0}, 
+  {0xFA07,0x8F3B,0x0,0x0}, {0xFA08,0x884C,0x0,0x0}, {0xFA09,0x964D,0x0,0x0}, 
+  {0xFA0A,0x898B,0x0,0x0}, {0xFA0B,0x5ED3,0x0,0x0}, {0xFA0C,0x5140,0x0,0x0}, 
+  {0xFA0D,0x55C0,0x0,0x0}, {0xFA10,0x585A,0x0,0x0}, {0xFA12,0x6674,0x0,0x0}, 
+  {0xFA15,0x51DE,0x0,0x0}, {0xFA16,0x732A,0x0,0x0}, {0xFA17,0x76CA,0x0,0x0}, 
+  {0xFA18,0x793C,0x0,0x0}, {0xFA19,0x795E,0x0,0x0}, {0xFA1A,0x7965,0x0,0x0}, 
+  {0xFA1B,0x798F,0x0,0x0}, {0xFA1C,0x9756,0x0,0x0}, {0xFA1D,0x7CBE,0x0,0x0}, 
+  {0xFA1E,0x7FBD,0x0,0x0}, {0xFA20,0x8612,0x0,0x0}, {0xFA22,0x8AF8,0x0,0x0}, 
+  {0xFA25,0x9038,0x0,0x0}, {0xFA26,0x90FD,0x0,0x0}, {0xFA2A,0x98EF,0x0,0x0}, 
+  {0xFA2B,0x98FC,0x0,0x0}, {0xFA2C,0x9928,0x0,0x0}, {0xFA2D,0x9DB4,0x0,0x0}, 
+  {0xFB1F,0x5F2,0x5B7,0x0}, {0xFB2A,0x5E9,0x5C1,0x0}, {0xFB2B,0x5E9,0x5C2,0x0}, 
+  {0xFB2C,0x5E9,0x5BC,0x5C1}, {0xFB2D,0x5E9,0x5BC,0x5C2}, {0xFB2E,0x5D0,0x5B7,0x0}, 
+  {0xFB2F,0x5D0,0x5B8,0x0}, {0xFB30,0x5D0,0x5BC,0x0}, {0xFB31,0x5D1,0x5BC,0x0}, 
+  {0xFB32,0x5D2,0x5BC,0x0}, {0xFB33,0x5D3,0x5BC,0x0}, {0xFB34,0x5D4,0x5BC,0x0}, 
+  {0xFB35,0x5D5,0x5BC,0x0}, {0xFB36,0x5D6,0x5BC,0x0}, {0xFB38,0x5D8,0x5BC,0x0}, 
+  {0xFB39,0x5D9,0x5BC,0x0}, {0xFB3A,0x5DA,0x5BC,0x0}, {0xFB3B,0x5DB,0x5BC,0x0}, 
+  {0xFB3C,0x5DC,0x5BC,0x0}, {0xFB3E,0x5DE,0x5BC,0x0}, {0xFB40,0x5E0,0x5BC,0x0}, 
+  {0xFB41,0x5E1,0x5BC,0x0}, {0xFB43,0x5E3,0x5BC,0x0}, {0xFB44,0x5E4,0x5BC,0x0}, 
+  {0xFB46,0x5E6,0x5BC,0x0}, {0xFB47,0x5E7,0x5BC,0x0}, {0xFB48,0x5E8,0x5BC,0x0}, 
+  {0xFB49,0x5E9,0x5BC,0x0}, {0xFB4A,0x5EA,0x5BC,0x0}, {0xFB4B,0x5D5,0x5B9,0x0}, 
+  {0xFB4C,0x5D1,0x5BF,0x0}, {0xFB4D,0x5DB,0x5BF,0x0}, {0xFB4E,0x5E4,0x5BF,0x0} 
+};
+
+
+/* All upper-case translations are included here */
+
+#define NUM_TOUPPER_INFO 677
+static const unirelate toupper_info[NUM_TOUPPER_INFO] = {
+  {0x61,0x41}, {0x62,0x42}, {0x63,0x43}, {0x64,0x44}, {0x65,0x45}, 
+  {0x66,0x46}, {0x67,0x47}, {0x68,0x48}, {0x69,0x49}, {0x6A,0x4A}, 
+  {0x6B,0x4B}, {0x6C,0x4C}, {0x6D,0x4D}, {0x6E,0x4E}, {0x6F,0x4F}, 
+  {0x70,0x50}, {0x71,0x51}, {0x72,0x52}, {0x73,0x53}, {0x74,0x54}, 
+  {0x75,0x55}, {0x76,0x56}, {0x77,0x57}, {0x78,0x58}, {0x79,0x59}, 
+  {0x7A,0x5A}, {0xE0,0xC0}, {0xE1,0xC1}, {0xE2,0xC2}, {0xE3,0xC3}, 
+  {0xE4,0xC4}, {0xE5,0xC5}, {0xE6,0xC6}, {0xE7,0xC7}, {0xE8,0xC8}, 
+  {0xE9,0xC9}, {0xEA,0xCA}, {0xEB,0xCB}, {0xEC,0xCC}, {0xED,0xCD}, 
+  {0xEE,0xCE}, {0xEF,0xCF}, {0xF0,0xD0}, {0xF1,0xD1}, {0xF2,0xD2}, 
+  {0xF3,0xD3}, {0xF4,0xD4}, {0xF5,0xD5}, {0xF6,0xD6}, {0xF8,0xD8}, 
+  {0xF9,0xD9}, {0xFA,0xDA}, {0xFB,0xDB}, {0xFC,0xDC}, {0xFD,0xDD}, 
+  {0xFE,0xDE}, {0xFF,0x178}, {0x101,0x100}, {0x103,0x102}, {0x105,0x104}, 
+  {0x107,0x106}, {0x109,0x108}, {0x10B,0x10A}, {0x10D,0x10C}, {0x10F,0x10E}, 
+  {0x111,0x110}, {0x113,0x112}, {0x115,0x114}, {0x117,0x116}, {0x119,0x118}, 
+  {0x11B,0x11A}, {0x11D,0x11C}, {0x11F,0x11E}, {0x121,0x120}, {0x123,0x122}, 
+  {0x125,0x124}, {0x127,0x126}, {0x129,0x128}, {0x12B,0x12A}, {0x12D,0x12C}, 
+  {0x12F,0x12E}, {0x131,0x49}, {0x133,0x132}, {0x135,0x134}, {0x137,0x136}, 
+  {0x13A,0x139}, {0x13C,0x13B}, {0x13E,0x13D}, {0x140,0x13F}, {0x142,0x141}, 
+  {0x144,0x143}, {0x146,0x145}, {0x148,0x147}, {0x14B,0x14A}, {0x14D,0x14C}, 
+  {0x14F,0x14E}, {0x151,0x150}, {0x153,0x152}, {0x155,0x154}, {0x157,0x156}, 
+  {0x159,0x158}, {0x15B,0x15A}, {0x15D,0x15C}, {0x15F,0x15E}, {0x161,0x160}, 
+  {0x163,0x162}, {0x165,0x164}, {0x167,0x166}, {0x169,0x168}, {0x16B,0x16A}, 
+  {0x16D,0x16C}, {0x16F,0x16E}, {0x171,0x170}, {0x173,0x172}, {0x175,0x174}, 
+  {0x177,0x176}, {0x17A,0x179}, {0x17C,0x17B}, {0x17E,0x17D}, {0x17F,0x53}, 
+  {0x183,0x182}, {0x185,0x184}, {0x188,0x187}, {0x18C,0x18B}, {0x192,0x191}, 
+  {0x199,0x198}, {0x1A1,0x1A0}, {0x1A3,0x1A2}, {0x1A5,0x1A4}, {0x1A8,0x1A7}, 
+  {0x1AD,0x1AC}, {0x1B0,0x1AF}, {0x1B4,0x1B3}, {0x1B6,0x1B5}, {0x1B9,0x1B8}, 
+  {0x1BD,0x1BC}, {0x1C5,0x1C4}, {0x1C6,0x1C4}, {0x1C8,0x1C7}, {0x1C9,0x1C7}, 
+  {0x1CB,0x1CA}, {0x1CC,0x1CA}, {0x1CE,0x1CD}, {0x1D0,0x1CF}, {0x1D2,0x1D1}, 
+  {0x1D4,0x1D3}, {0x1D6,0x1D5}, {0x1D8,0x1D7}, {0x1DA,0x1D9}, {0x1DC,0x1DB}, 
+  {0x1DD,0x18E}, {0x1DF,0x1DE}, {0x1E1,0x1E0}, {0x1E3,0x1E2}, {0x1E5,0x1E4}, 
+  {0x1E7,0x1E6}, {0x1E9,0x1E8}, {0x1EB,0x1EA}, {0x1ED,0x1EC}, {0x1EF,0x1EE}, 
+  {0x1F2,0x1F1}, {0x1F3,0x1F1}, {0x1F5,0x1F4}, {0x1FB,0x1FA}, {0x1FD,0x1FC}, 
+  {0x1FF,0x1FE}, {0x201,0x200}, {0x203,0x202}, {0x205,0x204}, {0x207,0x206}, 
+  {0x209,0x208}, {0x20B,0x20A}, {0x20D,0x20C}, {0x20F,0x20E}, {0x211,0x210}, 
+  {0x213,0x212}, {0x215,0x214}, {0x217,0x216}, {0x253,0x181}, {0x254,0x186}, 
+  {0x256,0x189}, {0x257,0x18A}, {0x259,0x18F}, {0x25B,0x190}, {0x260,0x193}, 
+  {0x263,0x194}, {0x268,0x197}, {0x269,0x196}, {0x26F,0x19C}, {0x272,0x19D}, 
+  {0x275,0x19F}, {0x283,0x1A9}, {0x288,0x1AE}, {0x28A,0x1B1}, {0x28B,0x1B2}, 
+  {0x292,0x1B7}, {0x3AC,0x386}, {0x3AD,0x388}, {0x3AE,0x389}, {0x3AF,0x38A}, 
+  {0x3B1,0x391}, {0x3B2,0x392}, {0x3B3,0x393}, {0x3B4,0x394}, {0x3B5,0x395}, 
+  {0x3B6,0x396}, {0x3B7,0x397}, {0x3B8,0x398}, {0x3B9,0x399}, {0x3BA,0x39A}, 
+  {0x3BB,0x39B}, {0x3BC,0x39C}, {0x3BD,0x39D}, {0x3BE,0x39E}, {0x3BF,0x39F}, 
+  {0x3C0,0x3A0}, {0x3C1,0x3A1}, {0x3C2,0x3A3}, {0x3C3,0x3A3}, {0x3C4,0x3A4}, 
+  {0x3C5,0x3A5}, {0x3C6,0x3A6}, {0x3C7,0x3A7}, {0x3C8,0x3A8}, {0x3C9,0x3A9}, 
+  {0x3CA,0x3AA}, {0x3CB,0x3AB}, {0x3CC,0x38C}, {0x3CD,0x38E}, {0x3CE,0x38F}, 
+  {0x3D0,0x392}, {0x3D1,0x398}, {0x3D5,0x3A6}, {0x3D6,0x3A0}, {0x3E3,0x3E2}, 
+  {0x3E5,0x3E4}, {0x3E7,0x3E6}, {0x3E9,0x3E8}, {0x3EB,0x3EA}, {0x3ED,0x3EC}, 
+  {0x3EF,0x3EE}, {0x3F0,0x39A}, {0x3F1,0x3A1}, {0x3F2,0x3A3}, {0x430,0x410}, 
+  {0x431,0x411}, {0x432,0x412}, {0x433,0x413}, {0x434,0x414}, {0x435,0x415}, 
+  {0x436,0x416}, {0x437,0x417}, {0x438,0x418}, {0x439,0x419}, {0x43A,0x41A}, 
+  {0x43B,0x41B}, {0x43C,0x41C}, {0x43D,0x41D}, {0x43E,0x41E}, {0x43F,0x41F}, 
+  {0x440,0x420}, {0x441,0x421}, {0x442,0x422}, {0x443,0x423}, {0x444,0x424}, 
+  {0x445,0x425}, {0x446,0x426}, {0x447,0x427}, {0x448,0x428}, {0x449,0x429}, 
+  {0x44A,0x42A}, {0x44B,0x42B}, {0x44C,0x42C}, {0x44D,0x42D}, {0x44E,0x42E}, 
+  {0x44F,0x42F}, {0x451,0x401}, {0x452,0x402}, {0x453,0x403}, {0x454,0x404}, 
+  {0x455,0x405}, {0x456,0x406}, {0x457,0x407}, {0x458,0x408}, {0x459,0x409}, 
+  {0x45A,0x40A}, {0x45B,0x40B}, {0x45C,0x40C}, {0x45E,0x40E}, {0x45F,0x40F}, 
+  {0x461,0x460}, {0x463,0x462}, {0x465,0x464}, {0x467,0x466}, {0x469,0x468}, 
+  {0x46B,0x46A}, {0x46D,0x46C}, {0x46F,0x46E}, {0x471,0x470}, {0x473,0x472}, 
+  {0x475,0x474}, {0x477,0x476}, {0x479,0x478}, {0x47B,0x47A}, {0x47D,0x47C}, 
+  {0x47F,0x47E}, {0x481,0x480}, {0x491,0x490}, {0x493,0x492}, {0x495,0x494}, 
+  {0x497,0x496}, {0x499,0x498}, {0x49B,0x49A}, {0x49D,0x49C}, {0x49F,0x49E}, 
+  {0x4A1,0x4A0}, {0x4A3,0x4A2}, {0x4A5,0x4A4}, {0x4A7,0x4A6}, {0x4A9,0x4A8}, 
+  {0x4AB,0x4AA}, {0x4AD,0x4AC}, {0x4AF,0x4AE}, {0x4B1,0x4B0}, {0x4B3,0x4B2}, 
+  {0x4B5,0x4B4}, {0x4B7,0x4B6}, {0x4B9,0x4B8}, {0x4BB,0x4BA}, {0x4BD,0x4BC}, 
+  {0x4BF,0x4BE}, {0x4C2,0x4C1}, {0x4C4,0x4C3}, {0x4C8,0x4C7}, {0x4CC,0x4CB}, 
+  {0x4D1,0x4D0}, {0x4D3,0x4D2}, {0x4D5,0x4D4}, {0x4D7,0x4D6}, {0x4D9,0x4D8}, 
+  {0x4DB,0x4DA}, {0x4DD,0x4DC}, {0x4DF,0x4DE}, {0x4E1,0x4E0}, {0x4E3,0x4E2}, 
+  {0x4E5,0x4E4}, {0x4E7,0x4E6}, {0x4E9,0x4E8}, {0x4EB,0x4EA}, {0x4EF,0x4EE}, 
+  {0x4F1,0x4F0}, {0x4F3,0x4F2}, {0x4F5,0x4F4}, {0x4F9,0x4F8}, {0x561,0x531}, 
+  {0x562,0x532}, {0x563,0x533}, {0x564,0x534}, {0x565,0x535}, {0x566,0x536}, 
+  {0x567,0x537}, {0x568,0x538}, {0x569,0x539}, {0x56A,0x53A}, {0x56B,0x53B}, 
+  {0x56C,0x53C}, {0x56D,0x53D}, {0x56E,0x53E}, {0x56F,0x53F}, {0x570,0x540}, 
+  {0x571,0x541}, {0x572,0x542}, {0x573,0x543}, {0x574,0x544}, {0x575,0x545}, 
+  {0x576,0x546}, {0x577,0x547}, {0x578,0x548}, {0x579,0x549}, {0x57A,0x54A}, 
+  {0x57B,0x54B}, {0x57C,0x54C}, {0x57D,0x54D}, {0x57E,0x54E}, {0x57F,0x54F}, 
+  {0x580,0x550}, {0x581,0x551}, {0x582,0x552}, {0x583,0x553}, {0x584,0x554}, 
+  {0x585,0x555}, {0x586,0x556}, {0x1E01,0x1E00}, {0x1E03,0x1E02}, {0x1E05,0x1E04}, 
+  {0x1E07,0x1E06}, {0x1E09,0x1E08}, {0x1E0B,0x1E0A}, {0x1E0D,0x1E0C}, {0x1E0F,0x1E0E}, 
+  {0x1E11,0x1E10}, {0x1E13,0x1E12}, {0x1E15,0x1E14}, {0x1E17,0x1E16}, {0x1E19,0x1E18}, 
+  {0x1E1B,0x1E1A}, {0x1E1D,0x1E1C}, {0x1E1F,0x1E1E}, {0x1E21,0x1E20}, {0x1E23,0x1E22}, 
+  {0x1E25,0x1E24}, {0x1E27,0x1E26}, {0x1E29,0x1E28}, {0x1E2B,0x1E2A}, {0x1E2D,0x1E2C}, 
+  {0x1E2F,0x1E2E}, {0x1E31,0x1E30}, {0x1E33,0x1E32}, {0x1E35,0x1E34}, {0x1E37,0x1E36}, 
+  {0x1E39,0x1E38}, {0x1E3B,0x1E3A}, {0x1E3D,0x1E3C}, {0x1E3F,0x1E3E}, {0x1E41,0x1E40}, 
+  {0x1E43,0x1E42}, {0x1E45,0x1E44}, {0x1E47,0x1E46}, {0x1E49,0x1E48}, {0x1E4B,0x1E4A}, 
+  {0x1E4D,0x1E4C}, {0x1E4F,0x1E4E}, {0x1E51,0x1E50}, {0x1E53,0x1E52}, {0x1E55,0x1E54}, 
+  {0x1E57,0x1E56}, {0x1E59,0x1E58}, {0x1E5B,0x1E5A}, {0x1E5D,0x1E5C}, {0x1E5F,0x1E5E}, 
+  {0x1E61,0x1E60}, {0x1E63,0x1E62}, {0x1E65,0x1E64}, {0x1E67,0x1E66}, {0x1E69,0x1E68}, 
+  {0x1E6B,0x1E6A}, {0x1E6D,0x1E6C}, {0x1E6F,0x1E6E}, {0x1E71,0x1E70}, {0x1E73,0x1E72}, 
+  {0x1E75,0x1E74}, {0x1E77,0x1E76}, {0x1E79,0x1E78}, {0x1E7B,0x1E7A}, {0x1E7D,0x1E7C}, 
+  {0x1E7F,0x1E7E}, {0x1E81,0x1E80}, {0x1E83,0x1E82}, {0x1E85,0x1E84}, {0x1E87,0x1E86}, 
+  {0x1E89,0x1E88}, {0x1E8B,0x1E8A}, {0x1E8D,0x1E8C}, {0x1E8F,0x1E8E}, {0x1E91,0x1E90}, 
+  {0x1E93,0x1E92}, {0x1E95,0x1E94}, {0x1E9B,0x1E60}, {0x1EA1,0x1EA0}, {0x1EA3,0x1EA2}, 
+  {0x1EA5,0x1EA4}, {0x1EA7,0x1EA6}, {0x1EA9,0x1EA8}, {0x1EAB,0x1EAA}, {0x1EAD,0x1EAC}, 
+  {0x1EAF,0x1EAE}, {0x1EB1,0x1EB0}, {0x1EB3,0x1EB2}, {0x1EB5,0x1EB4}, {0x1EB7,0x1EB6}, 
+  {0x1EB9,0x1EB8}, {0x1EBB,0x1EBA}, {0x1EBD,0x1EBC}, {0x1EBF,0x1EBE}, {0x1EC1,0x1EC0}, 
+  {0x1EC3,0x1EC2}, {0x1EC5,0x1EC4}, {0x1EC7,0x1EC6}, {0x1EC9,0x1EC8}, {0x1ECB,0x1ECA}, 
+  {0x1ECD,0x1ECC}, {0x1ECF,0x1ECE}, {0x1ED1,0x1ED0}, {0x1ED3,0x1ED2}, {0x1ED5,0x1ED4}, 
+  {0x1ED7,0x1ED6}, {0x1ED9,0x1ED8}, {0x1EDB,0x1EDA}, {0x1EDD,0x1EDC}, {0x1EDF,0x1EDE}, 
+  {0x1EE1,0x1EE0}, {0x1EE3,0x1EE2}, {0x1EE5,0x1EE4}, {0x1EE7,0x1EE6}, {0x1EE9,0x1EE8}, 
+  {0x1EEB,0x1EEA}, {0x1EED,0x1EEC}, {0x1EEF,0x1EEE}, {0x1EF1,0x1EF0}, {0x1EF3,0x1EF2}, 
+  {0x1EF5,0x1EF4}, {0x1EF7,0x1EF6}, {0x1EF9,0x1EF8}, {0x1F00,0x1F08}, {0x1F01,0x1F09}, 
+  {0x1F02,0x1F0A}, {0x1F03,0x1F0B}, {0x1F04,0x1F0C}, {0x1F05,0x1F0D}, {0x1F06,0x1F0E}, 
+  {0x1F07,0x1F0F}, {0x1F10,0x1F18}, {0x1F11,0x1F19}, {0x1F12,0x1F1A}, {0x1F13,0x1F1B}, 
+  {0x1F14,0x1F1C}, {0x1F15,0x1F1D}, {0x1F20,0x1F28}, {0x1F21,0x1F29}, {0x1F22,0x1F2A}, 
+  {0x1F23,0x1F2B}, {0x1F24,0x1F2C}, {0x1F25,0x1F2D}, {0x1F26,0x1F2E}, {0x1F27,0x1F2F}, 
+  {0x1F30,0x1F38}, {0x1F31,0x1F39}, {0x1F32,0x1F3A}, {0x1F33,0x1F3B}, {0x1F34,0x1F3C}, 
+  {0x1F35,0x1F3D}, {0x1F36,0x1F3E}, {0x1F37,0x1F3F}, {0x1F40,0x1F48}, {0x1F41,0x1F49}, 
+  {0x1F42,0x1F4A}, {0x1F43,0x1F4B}, {0x1F44,0x1F4C}, {0x1F45,0x1F4D}, {0x1F51,0x1F59}, 
+  {0x1F53,0x1F5B}, {0x1F55,0x1F5D}, {0x1F57,0x1F5F}, {0x1F60,0x1F68}, {0x1F61,0x1F69}, 
+  {0x1F62,0x1F6A}, {0x1F63,0x1F6B}, {0x1F64,0x1F6C}, {0x1F65,0x1F6D}, {0x1F66,0x1F6E}, 
+  {0x1F67,0x1F6F}, {0x1F70,0x1FBA}, {0x1F71,0x1FBB}, {0x1F72,0x1FC8}, {0x1F73,0x1FC9}, 
+  {0x1F74,0x1FCA}, {0x1F75,0x1FCB}, {0x1F76,0x1FDA}, {0x1F77,0x1FDB}, {0x1F78,0x1FF8}, 
+  {0x1F79,0x1FF9}, {0x1F7A,0x1FEA}, {0x1F7B,0x1FEB}, {0x1F7C,0x1FFA}, {0x1F7D,0x1FFB}, 
+  {0x1F80,0x1F88}, {0x1F81,0x1F89}, {0x1F82,0x1F8A}, {0x1F83,0x1F8B}, {0x1F84,0x1F8C}, 
+  {0x1F85,0x1F8D}, {0x1F86,0x1F8E}, {0x1F87,0x1F8F}, {0x1F90,0x1F98}, {0x1F91,0x1F99}, 
+  {0x1F92,0x1F9A}, {0x1F93,0x1F9B}, {0x1F94,0x1F9C}, {0x1F95,0x1F9D}, {0x1F96,0x1F9E}, 
+  {0x1F97,0x1F9F}, {0x1FA0,0x1FA8}, {0x1FA1,0x1FA9}, {0x1FA2,0x1FAA}, {0x1FA3,0x1FAB}, 
+  {0x1FA4,0x1FAC}, {0x1FA5,0x1FAD}, {0x1FA6,0x1FAE}, {0x1FA7,0x1FAF}, {0x1FB0,0x1FB8}, 
+  {0x1FB1,0x1FB9}, {0x1FB3,0x1FBC}, {0x1FC3,0x1FCC}, {0x1FD0,0x1FD8}, {0x1FD1,0x1FD9}, 
+  {0x1FE0,0x1FE8}, {0x1FE1,0x1FE9}, {0x1FE5,0x1FEC}, {0x1FF3,0x1FFC}, {0x2170,0x2160}, 
+  {0x2171,0x2161}, {0x2172,0x2162}, {0x2173,0x2163}, {0x2174,0x2164}, {0x2175,0x2165}, 
+  {0x2176,0x2166}, {0x2177,0x2167}, {0x2178,0x2168}, {0x2179,0x2169}, {0x217A,0x216A}, 
+  {0x217B,0x216B}, {0x217C,0x216C}, {0x217D,0x216D}, {0x217E,0x216E}, {0x217F,0x216F}, 
+  {0x24D0,0x24B6}, {0x24D1,0x24B7}, {0x24D2,0x24B8}, {0x24D3,0x24B9}, {0x24D4,0x24BA}, 
+  {0x24D5,0x24BB}, {0x24D6,0x24BC}, {0x24D7,0x24BD}, {0x24D8,0x24BE}, {0x24D9,0x24BF}, 
+  {0x24DA,0x24C0}, {0x24DB,0x24C1}, {0x24DC,0x24C2}, {0x24DD,0x24C3}, {0x24DE,0x24C4}, 
+  {0x24DF,0x24C5}, {0x24E0,0x24C6}, {0x24E1,0x24C7}, {0x24E2,0x24C8}, {0x24E3,0x24C9}, 
+  {0x24E4,0x24CA}, {0x24E5,0x24CB}, {0x24E6,0x24CC}, {0x24E7,0x24CD}, {0x24E8,0x24CE}, 
+  {0x24E9,0x24CF}, {0xFF41,0xFF21}, {0xFF42,0xFF22}, {0xFF43,0xFF23}, {0xFF44,0xFF24}, 
+  {0xFF45,0xFF25}, {0xFF46,0xFF26}, {0xFF47,0xFF27}, {0xFF48,0xFF28}, {0xFF49,0xFF29}, 
+  {0xFF4A,0xFF2A}, {0xFF4B,0xFF2B}, {0xFF4C,0xFF2C}, {0xFF4D,0xFF2D}, {0xFF4E,0xFF2E}, 
+  {0xFF4F,0xFF2F}, {0xFF50,0xFF30}, {0xFF51,0xFF31}, {0xFF52,0xFF32}, {0xFF53,0xFF33}, 
+  {0xFF54,0xFF34}, {0xFF55,0xFF35}, {0xFF56,0xFF36}, {0xFF57,0xFF37}, {0xFF58,0xFF38}, 
+  {0xFF59,0xFF39}, {0xFF5A,0xFF3A} 
+};
+
+
+
+/* All lower-case translations are included here */
+
+#define NUM_TOLOWER_INFO 705
+static const unirelate tolower_info[NUM_TOLOWER_INFO] = {
+  {0x41,0x61}, {0x42,0x62}, {0x43,0x63}, {0x44,0x64}, {0x45,0x65}, 
+  {0x46,0x66}, {0x47,0x67}, {0x48,0x68}, {0x49,0x69}, {0x4A,0x6A}, 
+  {0x4B,0x6B}, {0x4C,0x6C}, {0x4D,0x6D}, {0x4E,0x6E}, {0x4F,0x6F}, 
+  {0x50,0x70}, {0x51,0x71}, {0x52,0x72}, {0x53,0x73}, {0x54,0x74}, 
+  {0x55,0x75}, {0x56,0x76}, {0x57,0x77}, {0x58,0x78}, {0x59,0x79}, 
+  {0x5A,0x7A}, {0xC0,0xE0}, {0xC1,0xE1}, {0xC2,0xE2}, {0xC3,0xE3}, 
+  {0xC4,0xE4}, {0xC5,0xE5}, {0xC6,0xE6}, {0xC7,0xE7}, {0xC8,0xE8}, 
+  {0xC9,0xE9}, {0xCA,0xEA}, {0xCB,0xEB}, {0xCC,0xEC}, {0xCD,0xED}, 
+  {0xCE,0xEE}, {0xCF,0xEF}, {0xD0,0xF0}, {0xD1,0xF1}, {0xD2,0xF2}, 
+  {0xD3,0xF3}, {0xD4,0xF4}, {0xD5,0xF5}, {0xD6,0xF6}, {0xD8,0xF8}, 
+  {0xD9,0xF9}, {0xDA,0xFA}, {0xDB,0xFB}, {0xDC,0xFC}, {0xDD,0xFD}, 
+  {0xDE,0xFE}, {0x100,0x101}, {0x102,0x103}, {0x104,0x105}, {0x106,0x107}, 
+  {0x108,0x109}, {0x10A,0x10B}, {0x10C,0x10D}, {0x10E,0x10F}, {0x110,0x111}, 
+  {0x112,0x113}, {0x114,0x115}, {0x116,0x117}, {0x118,0x119}, {0x11A,0x11B}, 
+  {0x11C,0x11D}, {0x11E,0x11F}, {0x120,0x121}, {0x122,0x123}, {0x124,0x125}, 
+  {0x126,0x127}, {0x128,0x129}, {0x12A,0x12B}, {0x12C,0x12D}, {0x12E,0x12F}, 
+  {0x130,0x69}, {0x132,0x133}, {0x134,0x135}, {0x136,0x137}, {0x139,0x13A}, 
+  {0x13B,0x13C}, {0x13D,0x13E}, {0x13F,0x140}, {0x141,0x142}, {0x143,0x144}, 
+  {0x145,0x146}, {0x147,0x148}, {0x14A,0x14B}, {0x14C,0x14D}, {0x14E,0x14F}, 
+  {0x150,0x151}, {0x152,0x153}, {0x154,0x155}, {0x156,0x157}, {0x158,0x159}, 
+  {0x15A,0x15B}, {0x15C,0x15D}, {0x15E,0x15F}, {0x160,0x161}, {0x162,0x163}, 
+  {0x164,0x165}, {0x166,0x167}, {0x168,0x169}, {0x16A,0x16B}, {0x16C,0x16D}, 
+  {0x16E,0x16F}, {0x170,0x171}, {0x172,0x173}, {0x174,0x175}, {0x176,0x177}, 
+  {0x178,0xFF}, {0x179,0x17A}, {0x17B,0x17C}, {0x17D,0x17E}, {0x181,0x253}, 
+  {0x182,0x183}, {0x184,0x185}, {0x186,0x254}, {0x187,0x188}, {0x189,0x256}, 
+  {0x18A,0x257}, {0x18B,0x18C}, {0x18E,0x1DD}, {0x18F,0x259}, {0x190,0x25B}, 
+  {0x191,0x192}, {0x193,0x260}, {0x194,0x263}, {0x196,0x269}, {0x197,0x268}, 
+  {0x198,0x199}, {0x19C,0x26F}, {0x19D,0x272}, {0x19F,0x275}, {0x1A0,0x1A1}, 
+  {0x1A2,0x1A3}, {0x1A4,0x1A5}, {0x1A7,0x1A8}, {0x1A9,0x283}, {0x1AC,0x1AD}, 
+  {0x1AE,0x288}, {0x1AF,0x1B0}, {0x1B1,0x28A}, {0x1B2,0x28B}, {0x1B3,0x1B4}, 
+  {0x1B5,0x1B6}, {0x1B7,0x292}, {0x1B8,0x1B9}, {0x1BC,0x1BD}, {0x1C4,0x1C6}, 
+  {0x1C5,0x1C6}, {0x1C7,0x1C9}, {0x1C8,0x1C9}, {0x1CA,0x1CC}, {0x1CB,0x1CC}, 
+  {0x1CD,0x1CE}, {0x1CF,0x1D0}, {0x1D1,0x1D2}, {0x1D3,0x1D4}, {0x1D5,0x1D6}, 
+  {0x1D7,0x1D8}, {0x1D9,0x1DA}, {0x1DB,0x1DC}, {0x1DE,0x1DF}, {0x1E0,0x1E1}, 
+  {0x1E2,0x1E3}, {0x1E4,0x1E5}, {0x1E6,0x1E7}, {0x1E8,0x1E9}, {0x1EA,0x1EB}, 
+  {0x1EC,0x1ED}, {0x1EE,0x1EF}, {0x1F1,0x1F3}, {0x1F2,0x1F3}, {0x1F4,0x1F5}, 
+  {0x1FA,0x1FB}, {0x1FC,0x1FD}, {0x1FE,0x1FF}, {0x200,0x201}, {0x202,0x203}, 
+  {0x204,0x205}, {0x206,0x207}, {0x208,0x209}, {0x20A,0x20B}, {0x20C,0x20D}, 
+  {0x20E,0x20F}, {0x210,0x211}, {0x212,0x213}, {0x214,0x215}, {0x216,0x217}, 
+  {0x386,0x3AC}, {0x388,0x3AD}, {0x389,0x3AE}, {0x38A,0x3AF}, {0x38C,0x3CC}, 
+  {0x38E,0x3CD}, {0x38F,0x3CE}, {0x391,0x3B1}, {0x392,0x3B2}, {0x393,0x3B3}, 
+  {0x394,0x3B4}, {0x395,0x3B5}, {0x396,0x3B6}, {0x397,0x3B7}, {0x398,0x3B8}, 
+  {0x399,0x3B9}, {0x39A,0x3BA}, {0x39B,0x3BB}, {0x39C,0x3BC}, {0x39D,0x3BD}, 
+  {0x39E,0x3BE}, {0x39F,0x3BF}, {0x3A0,0x3C0}, {0x3A1,0x3C1}, {0x3A3,0x3C3}, 
+  {0x3A4,0x3C4}, {0x3A5,0x3C5}, {0x3A6,0x3C6}, {0x3A7,0x3C7}, {0x3A8,0x3C8}, 
+  {0x3A9,0x3C9}, {0x3AA,0x3CA}, {0x3AB,0x3CB}, {0x3E2,0x3E3}, {0x3E4,0x3E5}, 
+  {0x3E6,0x3E7}, {0x3E8,0x3E9}, {0x3EA,0x3EB}, {0x3EC,0x3ED}, {0x3EE,0x3EF}, 
+  {0x401,0x451}, {0x402,0x452}, {0x403,0x453}, {0x404,0x454}, {0x405,0x455}, 
+  {0x406,0x456}, {0x407,0x457}, {0x408,0x458}, {0x409,0x459}, {0x40A,0x45A}, 
+  {0x40B,0x45B}, {0x40C,0x45C}, {0x40E,0x45E}, {0x40F,0x45F}, {0x410,0x430}, 
+  {0x411,0x431}, {0x412,0x432}, {0x413,0x433}, {0x414,0x434}, {0x415,0x435}, 
+  {0x416,0x436}, {0x417,0x437}, {0x418,0x438}, {0x419,0x439}, {0x41A,0x43A}, 
+  {0x41B,0x43B}, {0x41C,0x43C}, {0x41D,0x43D}, {0x41E,0x43E}, {0x41F,0x43F}, 
+  {0x420,0x440}, {0x421,0x441}, {0x422,0x442}, {0x423,0x443}, {0x424,0x444}, 
+  {0x425,0x445}, {0x426,0x446}, {0x427,0x447}, {0x428,0x448}, {0x429,0x449}, 
+  {0x42A,0x44A}, {0x42B,0x44B}, {0x42C,0x44C}, {0x42D,0x44D}, {0x42E,0x44E}, 
+  {0x42F,0x44F}, {0x460,0x461}, {0x462,0x463}, {0x464,0x465}, {0x466,0x467}, 
+  {0x468,0x469}, {0x46A,0x46B}, {0x46C,0x46D}, {0x46E,0x46F}, {0x470,0x471}, 
+  {0x472,0x473}, {0x474,0x475}, {0x476,0x477}, {0x478,0x479}, {0x47A,0x47B}, 
+  {0x47C,0x47D}, {0x47E,0x47F}, {0x480,0x481}, {0x490,0x491}, {0x492,0x493}, 
+  {0x494,0x495}, {0x496,0x497}, {0x498,0x499}, {0x49A,0x49B}, {0x49C,0x49D}, 
+  {0x49E,0x49F}, {0x4A0,0x4A1}, {0x4A2,0x4A3}, {0x4A4,0x4A5}, {0x4A6,0x4A7}, 
+  {0x4A8,0x4A9}, {0x4AA,0x4AB}, {0x4AC,0x4AD}, {0x4AE,0x4AF}, {0x4B0,0x4B1}, 
+  {0x4B2,0x4B3}, {0x4B4,0x4B5}, {0x4B6,0x4B7}, {0x4B8,0x4B9}, {0x4BA,0x4BB}, 
+  {0x4BC,0x4BD}, {0x4BE,0x4BF}, {0x4C1,0x4C2}, {0x4C3,0x4C4}, {0x4C7,0x4C8}, 
+  {0x4CB,0x4CC}, {0x4D0,0x4D1}, {0x4D2,0x4D3}, {0x4D4,0x4D5}, {0x4D6,0x4D7}, 
+  {0x4D8,0x4D9}, {0x4DA,0x4DB}, {0x4DC,0x4DD}, {0x4DE,0x4DF}, {0x4E0,0x4E1}, 
+  {0x4E2,0x4E3}, {0x4E4,0x4E5}, {0x4E6,0x4E7}, {0x4E8,0x4E9}, {0x4EA,0x4EB}, 
+  {0x4EE,0x4EF}, {0x4F0,0x4F1}, {0x4F2,0x4F3}, {0x4F4,0x4F5}, {0x4F8,0x4F9}, 
+  {0x531,0x561}, {0x532,0x562}, {0x533,0x563}, {0x534,0x564}, {0x535,0x565}, 
+  {0x536,0x566}, {0x537,0x567}, {0x538,0x568}, {0x539,0x569}, {0x53A,0x56A}, 
+  {0x53B,0x56B}, {0x53C,0x56C}, {0x53D,0x56D}, {0x53E,0x56E}, {0x53F,0x56F}, 
+  {0x540,0x570}, {0x541,0x571}, {0x542,0x572}, {0x543,0x573}, {0x544,0x574}, 
+  {0x545,0x575}, {0x546,0x576}, {0x547,0x577}, {0x548,0x578}, {0x549,0x579}, 
+  {0x54A,0x57A}, {0x54B,0x57B}, {0x54C,0x57C}, {0x54D,0x57D}, {0x54E,0x57E}, 
+  {0x54F,0x57F}, {0x550,0x580}, {0x551,0x581}, {0x552,0x582}, {0x553,0x583}, 
+  {0x554,0x584}, {0x555,0x585}, {0x556,0x586}, {0x10A0,0x10D0}, {0x10A1,0x10D1}, 
+  {0x10A2,0x10D2}, {0x10A3,0x10D3}, {0x10A4,0x10D4}, {0x10A5,0x10D5}, {0x10A6,0x10D6}, 
+  {0x10A7,0x10D7}, {0x10A8,0x10D8}, {0x10A9,0x10D9}, {0x10AA,0x10DA}, {0x10AB,0x10DB}, 
+  {0x10AC,0x10DC}, {0x10AD,0x10DD}, {0x10AE,0x10DE}, {0x10AF,0x10DF}, {0x10B0,0x10E0}, 
+  {0x10B1,0x10E1}, {0x10B2,0x10E2}, {0x10B3,0x10E3}, {0x10B4,0x10E4}, {0x10B5,0x10E5}, 
+  {0x10B6,0x10E6}, {0x10B7,0x10E7}, {0x10B8,0x10E8}, {0x10B9,0x10E9}, {0x10BA,0x10EA}, 
+  {0x10BB,0x10EB}, {0x10BC,0x10EC}, {0x10BD,0x10ED}, {0x10BE,0x10EE}, {0x10BF,0x10EF}, 
+  {0x10C0,0x10F0}, {0x10C1,0x10F1}, {0x10C2,0x10F2}, {0x10C3,0x10F3}, {0x10C4,0x10F4}, 
+  {0x10C5,0x10F5}, {0x1E00,0x1E01}, {0x1E02,0x1E03}, {0x1E04,0x1E05}, {0x1E06,0x1E07}, 
+  {0x1E08,0x1E09}, {0x1E0A,0x1E0B}, {0x1E0C,0x1E0D}, {0x1E0E,0x1E0F}, {0x1E10,0x1E11}, 
+  {0x1E12,0x1E13}, {0x1E14,0x1E15}, {0x1E16,0x1E17}, {0x1E18,0x1E19}, {0x1E1A,0x1E1B}, 
+  {0x1E1C,0x1E1D}, {0x1E1E,0x1E1F}, {0x1E20,0x1E21}, {0x1E22,0x1E23}, {0x1E24,0x1E25}, 
+  {0x1E26,0x1E27}, {0x1E28,0x1E29}, {0x1E2A,0x1E2B}, {0x1E2C,0x1E2D}, {0x1E2E,0x1E2F}, 
+  {0x1E30,0x1E31}, {0x1E32,0x1E33}, {0x1E34,0x1E35}, {0x1E36,0x1E37}, {0x1E38,0x1E39}, 
+  {0x1E3A,0x1E3B}, {0x1E3C,0x1E3D}, {0x1E3E,0x1E3F}, {0x1E40,0x1E41}, {0x1E42,0x1E43}, 
+  {0x1E44,0x1E45}, {0x1E46,0x1E47}, {0x1E48,0x1E49}, {0x1E4A,0x1E4B}, {0x1E4C,0x1E4D}, 
+  {0x1E4E,0x1E4F}, {0x1E50,0x1E51}, {0x1E52,0x1E53}, {0x1E54,0x1E55}, {0x1E56,0x1E57}, 
+  {0x1E58,0x1E59}, {0x1E5A,0x1E5B}, {0x1E5C,0x1E5D}, {0x1E5E,0x1E5F}, {0x1E60,0x1E61}, 
+  {0x1E62,0x1E63}, {0x1E64,0x1E65}, {0x1E66,0x1E67}, {0x1E68,0x1E69}, {0x1E6A,0x1E6B}, 
+  {0x1E6C,0x1E6D}, {0x1E6E,0x1E6F}, {0x1E70,0x1E71}, {0x1E72,0x1E73}, {0x1E74,0x1E75}, 
+  {0x1E76,0x1E77}, {0x1E78,0x1E79}, {0x1E7A,0x1E7B}, {0x1E7C,0x1E7D}, {0x1E7E,0x1E7F}, 
+  {0x1E80,0x1E81}, {0x1E82,0x1E83}, {0x1E84,0x1E85}, {0x1E86,0x1E87}, {0x1E88,0x1E89}, 
+  {0x1E8A,0x1E8B}, {0x1E8C,0x1E8D}, {0x1E8E,0x1E8F}, {0x1E90,0x1E91}, {0x1E92,0x1E93}, 
+  {0x1E94,0x1E95}, {0x1EA0,0x1EA1}, {0x1EA2,0x1EA3}, {0x1EA4,0x1EA5}, {0x1EA6,0x1EA7}, 
+  {0x1EA8,0x1EA9}, {0x1EAA,0x1EAB}, {0x1EAC,0x1EAD}, {0x1EAE,0x1EAF}, {0x1EB0,0x1EB1}, 
+  {0x1EB2,0x1EB3}, {0x1EB4,0x1EB5}, {0x1EB6,0x1EB7}, {0x1EB8,0x1EB9}, {0x1EBA,0x1EBB}, 
+  {0x1EBC,0x1EBD}, {0x1EBE,0x1EBF}, {0x1EC0,0x1EC1}, {0x1EC2,0x1EC3}, {0x1EC4,0x1EC5}, 
+  {0x1EC6,0x1EC7}, {0x1EC8,0x1EC9}, {0x1ECA,0x1ECB}, {0x1ECC,0x1ECD}, {0x1ECE,0x1ECF}, 
+  {0x1ED0,0x1ED1}, {0x1ED2,0x1ED3}, {0x1ED4,0x1ED5}, {0x1ED6,0x1ED7}, {0x1ED8,0x1ED9}, 
+  {0x1EDA,0x1EDB}, {0x1EDC,0x1EDD}, {0x1EDE,0x1EDF}, {0x1EE0,0x1EE1}, {0x1EE2,0x1EE3}, 
+  {0x1EE4,0x1EE5}, {0x1EE6,0x1EE7}, {0x1EE8,0x1EE9}, {0x1EEA,0x1EEB}, {0x1EEC,0x1EED}, 
+  {0x1EEE,0x1EEF}, {0x1EF0,0x1EF1}, {0x1EF2,0x1EF3}, {0x1EF4,0x1EF5}, {0x1EF6,0x1EF7}, 
+  {0x1EF8,0x1EF9}, {0x1F08,0x1F00}, {0x1F09,0x1F01}, {0x1F0A,0x1F02}, {0x1F0B,0x1F03}, 
+  {0x1F0C,0x1F04}, {0x1F0D,0x1F05}, {0x1F0E,0x1F06}, {0x1F0F,0x1F07}, {0x1F18,0x1F10}, 
+  {0x1F19,0x1F11}, {0x1F1A,0x1F12}, {0x1F1B,0x1F13}, {0x1F1C,0x1F14}, {0x1F1D,0x1F15}, 
+  {0x1F28,0x1F20}, {0x1F29,0x1F21}, {0x1F2A,0x1F22}, {0x1F2B,0x1F23}, {0x1F2C,0x1F24}, 
+  {0x1F2D,0x1F25}, {0x1F2E,0x1F26}, {0x1F2F,0x1F27}, {0x1F38,0x1F30}, {0x1F39,0x1F31}, 
+  {0x1F3A,0x1F32}, {0x1F3B,0x1F33}, {0x1F3C,0x1F34}, {0x1F3D,0x1F35}, {0x1F3E,0x1F36}, 
+  {0x1F3F,0x1F37}, {0x1F48,0x1F40}, {0x1F49,0x1F41}, {0x1F4A,0x1F42}, {0x1F4B,0x1F43}, 
+  {0x1F4C,0x1F44}, {0x1F4D,0x1F45}, {0x1F59,0x1F51}, {0x1F5B,0x1F53}, {0x1F5D,0x1F55}, 
+  {0x1F5F,0x1F57}, {0x1F68,0x1F60}, {0x1F69,0x1F61}, {0x1F6A,0x1F62}, {0x1F6B,0x1F63}, 
+  {0x1F6C,0x1F64}, {0x1F6D,0x1F65}, {0x1F6E,0x1F66}, {0x1F6F,0x1F67}, {0x1F88,0x1F80}, 
+  {0x1F89,0x1F81}, {0x1F8A,0x1F82}, {0x1F8B,0x1F83}, {0x1F8C,0x1F84}, {0x1F8D,0x1F85}, 
+  {0x1F8E,0x1F86}, {0x1F8F,0x1F87}, {0x1F98,0x1F90}, {0x1F99,0x1F91}, {0x1F9A,0x1F92}, 
+  {0x1F9B,0x1F93}, {0x1F9C,0x1F94}, {0x1F9D,0x1F95}, {0x1F9E,0x1F96}, {0x1F9F,0x1F97}, 
+  {0x1FA8,0x1FA0}, {0x1FA9,0x1FA1}, {0x1FAA,0x1FA2}, {0x1FAB,0x1FA3}, {0x1FAC,0x1FA4}, 
+  {0x1FAD,0x1FA5}, {0x1FAE,0x1FA6}, {0x1FAF,0x1FA7}, {0x1FB8,0x1FB0}, {0x1FB9,0x1FB1}, 
+  {0x1FBA,0x1F70}, {0x1FBB,0x1F71}, {0x1FBC,0x1FB3}, {0x1FC8,0x1F72}, {0x1FC9,0x1F73}, 
+  {0x1FCA,0x1F74}, {0x1FCB,0x1F75}, {0x1FCC,0x1FC3}, {0x1FD8,0x1FD0}, {0x1FD9,0x1FD1}, 
+  {0x1FDA,0x1F76}, {0x1FDB,0x1F77}, {0x1FE8,0x1FE0}, {0x1FE9,0x1FE1}, {0x1FEA,0x1F7A}, 
+  {0x1FEB,0x1F7B}, {0x1FEC,0x1FE5}, {0x1FF8,0x1F78}, {0x1FF9,0x1F79}, {0x1FFA,0x1F7C}, 
+  {0x1FFB,0x1F7D}, {0x1FFC,0x1FF3}, {0x2160,0x2170}, {0x2161,0x2171}, {0x2162,0x2172}, 
+  {0x2163,0x2173}, {0x2164,0x2174}, {0x2165,0x2175}, {0x2166,0x2176}, {0x2167,0x2177}, 
+  {0x2168,0x2178}, {0x2169,0x2179}, {0x216A,0x217A}, {0x216B,0x217B}, {0x216C,0x217C}, 
+  {0x216D,0x217D}, {0x216E,0x217E}, {0x216F,0x217F}, {0x24B6,0x24D0}, {0x24B7,0x24D1}, 
+  {0x24B8,0x24D2}, {0x24B9,0x24D3}, {0x24BA,0x24D4}, {0x24BB,0x24D5}, {0x24BC,0x24D6}, 
+  {0x24BD,0x24D7}, {0x24BE,0x24D8}, {0x24BF,0x24D9}, {0x24C0,0x24DA}, {0x24C1,0x24DB}, 
+  {0x24C2,0x24DC}, {0x24C3,0x24DD}, {0x24C4,0x24DE}, {0x24C5,0x24DF}, {0x24C6,0x24E0}, 
+  {0x24C7,0x24E1}, {0x24C8,0x24E2}, {0x24C9,0x24E3}, {0x24CA,0x24E4}, {0x24CB,0x24E5}, 
+  {0x24CC,0x24E6}, {0x24CD,0x24E7}, {0x24CE,0x24E8}, {0x24CF,0x24E9}, {0xFF21,0xFF41}, 
+  {0xFF22,0xFF42}, {0xFF23,0xFF43}, {0xFF24,0xFF44}, {0xFF25,0xFF45}, {0xFF26,0xFF46}, 
+  {0xFF27,0xFF47}, {0xFF28,0xFF48}, {0xFF29,0xFF49}, {0xFF2A,0xFF4A}, {0xFF2B,0xFF4B}, 
+  {0xFF2C,0xFF4C}, {0xFF2D,0xFF4D}, {0xFF2E,0xFF4E}, {0xFF2F,0xFF4F}, {0xFF30,0xFF50}, 
+  {0xFF31,0xFF51}, {0xFF32,0xFF52}, {0xFF33,0xFF53}, {0xFF34,0xFF54}, {0xFF35,0xFF55}, 
+  {0xFF36,0xFF56}, {0xFF37,0xFF57}, {0xFF38,0xFF58}, {0xFF39,0xFF59}, {0xFF3A,0xFF5A}
+};
+
+
+
+#define NUM_TOSIMPLIFIED_INFO 2145
+static const unirelate tosimplified_info[NUM_TOSIMPLIFIED_INFO] = {
+  {0x4E48,0x9EBD}, {0x4E82,0x4E71}, {0x4E9E,0x4E9A}, {0x4F47,0x4F2B}, {0x4F59,0x9980}, 
+  {0x4F86,0x6765}, {0x4F96,0x4ED1}, {0x4FE0,0x4FA0}, {0x5000,0x4F25}, {0x5006,0x4FE9}, 
+  {0x5009,0x4ED3}, {0x500B,0x4E2A}, {0x5011,0x4EEC}, {0x502B,0x4F26}, {0x5049,0x4F1F}, 
+  {0x5074,0x4FA7}, {0x5075,0x4FA6}, {0x5096,0x4F27}, {0x5098,0x4F1E}, {0x5099,0x5907}, 
+  {0x50AD,0x4F63}, {0x50B3,0x4F20}, {0x50B4,0x4F1B}, {0x50B5,0x503A}, {0x50B7,0x4F24}, 
+  {0x50BE,0x503E}, {0x50C2,0x507B}, {0x50C5,0x4EC5}, {0x50C9,0x4F65}, {0x50D1,0x4FA8}, 
+  {0x50D5,0x4EC6}, {0x50DE,0x4F2A}, {0x50E5,0x4FA5}, {0x50E8,0x507E}, {0x50F9,0x4EF7}, 
+  {0x5100,0x4EEA}, {0x5102,0x4FAC}, {0x5104,0x4EBF}, {0x5108,0x4FA9}, {0x5109,0x4FED}, 
+  {0x5110,0x50A7}, {0x5114,0x4FE6}, {0x5115,0x4FAA}, {0x511F,0x507F}, {0x512A,0x4F18}, 
+  {0x5132,0x50A8}, {0x5137,0x4FEA}, {0x513A,0x50A9}, {0x513B,0x50A5}, {0x513C,0x4FE8}, 
+  {0x5152,0x513F}, {0x5169,0x4E24}, {0x51C8,0x51C0}, {0x51CD,0x51BB}, {0x51F1,0x51EF}, 
+  {0x5244,0x522D}, {0x5247,0x5219}, {0x525B,0x521A}, {0x526E,0x5250}, {0x5274,0x5240}, 
+  {0x5275,0x521B}, {0x5283,0x5212}, {0x5287,0x5267}, {0x5289,0x5218}, {0x528A,0x523D}, 
+  {0x528C,0x523F}, {0x528D,0x5251}, {0x5291,0x5242}, {0x52C1,0x52B2}, {0x52D5,0x52A8}, 
+  {0x52D9,0x52A1}, {0x52DB,0x52CB}, {0x52DD,0x80DC}, {0x52DE,0x52B3}, {0x52E2,0x52BF}, 
+  {0x52F1,0x52A2}, {0x52F5,0x52B1}, {0x52F8,0x529D}, {0x532D,0x5326}, {0x532F,0x6C47}, 
+  {0x5331,0x532E}, {0x5340,0x533A}, {0x5354,0x534F}, {0x5399,0x538D}, {0x53A0,0x5395}, 
+  {0x53AD,0x538C}, {0x53B2,0x5389}, {0x53B4,0x53A3}, {0x53C3,0x53C2}, {0x53E2,0x4E1B}, 
+  {0x540E,0x5F8C}, {0x54BC,0x5459}, {0x54E1,0x5458}, {0x5504,0x5457}, {0x554F,0x95EE}, 
+  {0x5553,0x542F}, {0x555E,0x54D1}, {0x559A,0x5524}, {0x55AA,0x4E27}, {0x55AC,0x4E54}, 
+  {0x55AE,0x5355}, {0x55B2,0x54DF}, {0x55C6,0x545B}, {0x55C7,0x556C}, {0x55CE,0x5417}, 
+  {0x55DA,0x545C}, {0x55E9,0x5522}, {0x55F6,0x54D4}, {0x5606,0x53F9}, {0x560D,0x55BD}, 
+  {0x5614,0x5455}, {0x5616,0x5567}, {0x5617,0x5C1D}, {0x561C,0x551B}, {0x5629,0x54D7}, 
+  {0x562E,0x5520}, {0x562F,0x5578}, {0x5630,0x53FD}, {0x5635,0x54D3}, {0x5638,0x5452}, 
+  {0x565D,0x549D}, {0x5660,0x54D2}, {0x5665,0x54DD}, {0x5666,0x54D5}, {0x566F,0x55F3}, 
+  {0x5672,0x54D9}, {0x5674,0x55B7}, {0x5678,0x5428}, {0x5680,0x549B}, {0x5687,0x5413}, 
+  {0x568C,0x54DC}, {0x5695,0x565C}, {0x5699,0x556E}, {0x56A6,0x5456}, {0x56A8,0x5499}, 
+  {0x56B3,0x55BE}, {0x56B4,0x4E25}, {0x56B6,0x5624}, {0x56C0,0x556D}, {0x56C1,0x55EB}, 
+  {0x56C2,0x56A3}, {0x56C5,0x5181}, {0x56C8,0x5453}, {0x56D1,0x5631}, {0x5707,0x56F5}, 
+  {0x570B,0x56FD}, {0x570D,0x56F4}, {0x5712,0x56ED}, {0x5713,0x5706}, {0x5716,0x56FE}, 
+  {0x5718,0x56E2}, {0x57E1,0x57AD}, {0x57F7,0x6267}, {0x5805,0x575A}, {0x580A,0x57A9}, 
+  {0x5816,0x57B4}, {0x581D,0x57DA}, {0x582F,0x5C27}, {0x5831,0x62A5}, {0x5834,0x573A}, 
+  {0x584A,0x5757}, {0x584B,0x8314}, {0x584F,0x57B2}, {0x5852,0x57D8}, {0x5857,0x6D82}, 
+  {0x5862,0x575E}, {0x5864,0x57D9}, {0x5875,0x5C18}, {0x5879,0x5811}, {0x588A,0x57AB}, 
+  {0x589C,0x5760}, {0x58AE,0x5815}, {0x58B3,0x575F}, {0x58BB,0x5899}, {0x58BE,0x57A6}, 
+  {0x58C7,0x575B}, {0x58D3,0x538B}, {0x58D8,0x5792}, {0x58D9,0x5739}, {0x58DA,0x5786}, 
+  {0x58DE,0x574F}, {0x58DF,0x5784}, {0x58E0,0x5785}, {0x58E2,0x575C}, {0x58E9,0x575D}, 
+  {0x58EF,0x58EE}, {0x58FA,0x58F6}, {0x58FD,0x5BFF}, {0x5922,0x68A6}, {0x593E,0x5939}, 
+  {0x5950,0x5942}, {0x5969,0x5941}, {0x596A,0x593A}, {0x596C,0x5956}, {0x596E,0x594B}, 
+  {0x599D,0x5986}, {0x5A41,0x5A04}, {0x5A66,0x5987}, {0x5A6D,0x5A05}, {0x5AA7,0x5A32}, 
+  {0x5ABD,0x5988}, {0x5AD7,0x59AA}, {0x5AF5,0x59A9}, {0x5AFB,0x5A34}, {0x5B00,0x59AB}, 
+  {0x5B08,0x5A06}, {0x5B0B,0x5A75}, {0x5B0C,0x5A07}, {0x5B19,0x5AF1}, {0x5B21,0x5AD2}, 
+  {0x5B2A,0x5AD4}, {0x5B30,0x5A74}, {0x5B38,0x5A76}, {0x5B4C,0x5A08}, {0x5B6B,0x5B59}, 
+  {0x5B78,0x5B66}, {0x5B7F,0x5B6A}, {0x5BE2,0x5BDD}, {0x5BE6,0x5B9E}, {0x5BE7,0x5B81}, 
+  {0x5BE9,0x5BA1}, {0x5BEB,0x5199}, {0x5BEC,0x5BBD}, {0x5BF5,0x5BA0}, {0x5BF6,0x5B9D}, 
+  {0x5C07,0x5C06}, {0x5C08,0x4E13}, {0x5C0B,0x5BFB}, {0x5C0D,0x5BF9}, {0x5C0E,0x5BFC}, 
+  {0x5C37,0x5C34}, {0x5C62,0x5C61}, {0x5C64,0x5C42}, {0x5C68,0x5C66}, {0x5C6C,0x5C5E}, 
+  {0x5CA1,0x5188}, {0x5CF4,0x5C98}, {0x5CF6,0x5C9B}, {0x5CFD,0x5CE1}, {0x5D0D,0x5D03}, 
+  {0x5D17,0x5C97}, {0x5D22,0x5CE5}, {0x5D2C,0x5CBD}, {0x5D50,0x5C9A}, {0x5D81,0x5D5D}, 
+  {0x5D84,0x5D2D}, {0x5D87,0x5C96}, {0x5D97,0x5D02}, {0x5DA0,0x5CE4}, {0x5DA7,0x5CC4}, 
+  {0x5DB8,0x5D58}, {0x5DBA,0x5CAD}, {0x5DBC,0x5C7F}, {0x5DCB,0x5CBF}, {0x5DD2,0x5CE6}, 
+  {0x5DD4,0x5DC5}, {0x5DF0,0x5DEF}, {0x5E25,0x5E05}, {0x5E2B,0x5E08}, {0x5E33,0x5E10}, 
+  {0x5E36,0x5E26}, {0x5E40,0x5E27}, {0x5E43,0x5E0F}, {0x5E57,0x5E3C}, {0x5E58,0x5E3B}, 
+  {0x5E5F,0x5E1C}, {0x5E63,0x5E01}, {0x5E6B,0x5E2E}, {0x5E6C,0x5E31}, {0x5E79,0x5E72}, 
+  {0x5E7E,0x51E0}, {0x5EAB,0x5E93}, {0x5EDF,0x5E99}, {0x5EE0,0x5382}, {0x5EE1,0x5E91}, 
+  {0x5EE2,0x5E9F}, {0x5EE3,0x5E7F}, {0x5EEC,0x5E90}, {0x5EF3,0x5385}, {0x5F33,0x5F2A}, 
+  {0x5F35,0x5F20}, {0x5F48,0x5F39}, {0x5F4C,0x5F25}, {0x5F4E,0x5F2F}, {0x5F8C,0x540E}, 
+  {0x5F91,0x5F84}, {0x5F9E,0x4ECE}, {0x5FA0,0x5F95}, {0x5FA9,0x590D}, {0x5FB9,0x5F7B}, 
+  {0x60B5,0x6005}, {0x60B6,0x95F7}, {0x60E1,0x6076}, {0x60F1,0x607C}, {0x60F2,0x607D}, 
+  {0x60FB,0x607B}, {0x611B,0x7231}, {0x611C,0x60EC}, {0x6134,0x6006}, {0x6137,0x607A}, 
+  {0x613E,0x5FFE}, {0x614B,0x6001}, {0x6158,0x60E8}, {0x615A,0x60ED}, {0x615F,0x6078}, 
+  {0x6163,0x60EF}, {0x6164,0x60AB}, {0x616A,0x6004}, {0x616B,0x6002}, {0x616E,0x8651}, 
+  {0x6173,0x60AD}, {0x6176,0x5E86}, {0x6182,0x5FE7}, {0x618A,0x60EB}, {0x6190,0x601C}, 
+  {0x6191,0x51ED}, {0x6192,0x6126}, {0x619A,0x60EE}, {0x61A4,0x6124}, {0x61AB,0x60AF}, 
+  {0x61AE,0x6003}, {0x61B2,0x5BAA}, {0x61B6,0x5FC6}, {0x61C7,0x6073}, {0x61C9,0x5E94}, 
+  {0x61CC,0x603F}, {0x61DF,0x603C}, {0x61E3,0x61D1}, {0x61E8,0x6079}, {0x61F2,0x60E9}, 
+  {0x61F6,0x61D2}, {0x61F7,0x6000}, {0x61F8,0x60AC}, {0x61FA,0x5FCF}, {0x61FC,0x60E7}, 
+  {0x61FE,0x6151}, {0x6200,0x604B}, {0x6207,0x6206}, {0x6214,0x620B}, {0x6227,0x6217}, 
+  {0x6229,0x622C}, {0x6230,0x6218}, {0x6232,0x620F}, {0x633E,0x631F}, {0x6368,0x820D}, 
+  {0x636B,0x626A}, {0x6383,0x626B}, {0x6384,0x62A1}, {0x6399,0x6323}, {0x63C0,0x62E3}, 
+  {0x63DA,0x626C}, {0x63DB,0x6362}, {0x63EE,0x6325}, {0x640D,0x635F}, {0x6417,0x6363}, 
+  {0x6436,0x62A2}, {0x6451,0x63B4}, {0x645C,0x63BC}, {0x645F,0x6402}, {0x646F,0x631A}, 
+  {0x6473,0x62A0}, {0x6476,0x629F}, {0x647B,0x63BA}, {0x6488,0x635E}, {0x6493,0x6320}, 
+  {0x649F,0x6322}, {0x64A3,0x63B8}, {0x64A5,0x62E8}, {0x64AB,0x629A}, {0x64B2,0x6251}, 
+  {0x64B3,0x63FF}, {0x64BB,0x631E}, {0x64BE,0x631D}, {0x64BF,0x6361}, {0x64C1,0x62E5}, 
+  {0x64C4,0x63B3}, {0x64C7,0x62E9}, {0x64CA,0x51FB}, {0x64CB,0x6321}, {0x64D4,0x62C5}, 
+  {0x64DA,0x636E}, {0x64E0,0x6324}, {0x64EC,0x62DF}, {0x64EF,0x6448}, {0x64F0,0x62E7}, 
+  {0x64F1,0x6401}, {0x64F2,0x63B7}, {0x64F4,0x6269}, {0x64F7,0x64B7}, {0x64FA,0x6446}, 
+  {0x64FB,0x64DE}, {0x64FC,0x64B8}, {0x64FE,0x6270}, {0x6504,0x6445}, {0x6506,0x64B5}, 
+  {0x650F,0x62E2}, {0x6514,0x62E6}, {0x6516,0x6484}, {0x6519,0x6400}, {0x651B,0x64BA}, 
+  {0x651D,0x6444}, {0x6522,0x6512}, {0x6523,0x631B}, {0x6524,0x644A}, {0x652A,0x6405}, 
+  {0x652C,0x63FD}, {0x6557,0x8D25}, {0x6575,0x654C}, {0x6578,0x6570}, {0x6582,0x655B}, 
+  {0x6583,0x6BD9}, {0x6595,0x6593}, {0x65AC,0x65A9}, {0x65B7,0x65AD}, {0x6642,0x65F6}, 
+  {0x6649,0x664B}, {0x665D,0x663C}, {0x6688,0x6655}, {0x6689,0x6656}, {0x66A2,0x7545}, 
+  {0x66AB,0x6682}, {0x66C4,0x6654}, {0x66C7,0x6619}, {0x66C9,0x6653}, {0x66D6,0x66A7}, 
+  {0x66E0,0x65F7}, {0x66EC,0x6652}, {0x66F8,0x4E66}, {0x6703,0x4F1A}, {0x6727,0x80E7}, 
+  {0x6771,0x4E1C}, {0x6898,0x67A7}, {0x689D,0x6761}, {0x689F,0x67AD}, {0x68C4,0x5F03}, 
+  {0x68D6,0x67A8}, {0x68D7,0x67A3}, {0x68DF,0x680B}, {0x68E7,0x6808}, {0x68F2,0x6816}, 
+  {0x690F,0x6860}, {0x694A,0x6768}, {0x6953,0x67AB}, {0x6968,0x6862}, {0x696D,0x4E1A}, 
+  {0x6975,0x6781}, {0x69AA,0x6769}, {0x69AE,0x8363}, {0x69BF,0x6864}, {0x69CB,0x6784}, 
+  {0x69CD,0x67AA}, {0x69E7,0x6920}, {0x69F3,0x6868}, {0x6A01,0x6869}, {0x6A02,0x4E50}, 
+  {0x6A05,0x679E}, {0x6A13,0x697C}, {0x6A19,0x6807}, {0x6A1E,0x67A2}, {0x6A23,0x6837}, 
+  {0x6A38,0x6734}, {0x6A39,0x6811}, {0x6A3A,0x6866}, {0x6A48,0x6861}, {0x6A4B,0x6865}, 
+  {0x6A5F,0x673A}, {0x6A62,0x692D}, {0x6A89,0x67FD}, {0x6A94,0x6863}, {0x6A9C,0x6867}, 
+  {0x6AA2,0x68C0}, {0x6AA3,0x6A2F}, {0x6AB3,0x69DF}, {0x6AB8,0x67E0}, {0x6ABB,0x69DB}, 
+  {0x6AC3,0x67DC}, {0x6AD3,0x6A79}, {0x6ADA,0x6988}, {0x6ADB,0x6809}, {0x6ADD,0x691F}, 
+  {0x6ADE,0x6A7C}, {0x6ADF,0x680E}, {0x6AE7,0x69E0}, {0x6AE8,0x680C}, {0x6AEA,0x67A5}, 
+  {0x6AEC,0x6987}, {0x6AF3,0x680A}, {0x6AF8,0x6989}, {0x6AFB,0x6A31}, {0x6B04,0x680F}, 
+  {0x6B0A,0x6743}, {0x6B0F,0x6924}, {0x6B12,0x683E}, {0x6B16,0x6984}, {0x6B1E,0x68C2}, 
+  {0x6B3D,0x94A6}, {0x6B50,0x6B27}, {0x6B5F,0x6B24}, {0x6B61,0x6B22}, {0x6B72,0x5C81}, 
+  {0x6B77,0x5386}, {0x6B78,0x5F52}, {0x6B98,0x6B8B}, {0x6B9E,0x6B92}, {0x6BA4,0x6B87}, 
+  {0x6BAB,0x6B9A}, {0x6BAE,0x6B93}, {0x6BAF,0x6BA1}, {0x6BB2,0x6B7C}, {0x6BBA,0x6740}, 
+  {0x6BBB,0x58F3}, {0x6BC6,0x6BB4}, {0x6BFF,0x6BF5}, {0x6C08,0x6BE1}, {0x6C0C,0x6C07}, 
+  {0x6C23,0x6C14}, {0x6C2B,0x6C22}, {0x6C2C,0x6C29}, {0x6D79,0x6D43}, {0x6D87,0x6CFE}, 
+  {0x6DEA,0x6CA6}, {0x6DF5,0x6E0A}, {0x6DF6,0x6D9E}, {0x6DFA,0x6D45}, {0x6E19,0x6DA3}, 
+  {0x6E26,0x6DA1}, {0x6E2C,0x6D4B}, {0x6E3E,0x6D51}, {0x6E5E,0x6D48}, {0x6E6F,0x6C64}, 
+  {0x6E96,0x51C6}, {0x6E9D,0x6C9F}, {0x6EC4,0x6CA7}, {0x6EC5,0x706D}, {0x6ECC,0x6DA4}, 
+  {0x6ECE,0x8365}, {0x6EEC,0x6CAA}, {0x6EEF,0x6EDE}, {0x6EF2,0x6E17}, {0x6EF7,0x5364}, 
+  {0x6EF8,0x6D52}, {0x6EFF,0x6EE1}, {0x6F01,0x6E14}, {0x6F1A,0x6CA4}, {0x6F22,0x6C49}, 
+  {0x6F23,0x6D9F}, {0x6F2C,0x6E0D}, {0x6F32,0x6DA8}, {0x6F38,0x6E10}, {0x6F3F,0x6D46}, 
+  {0x6F41,0x988D}, {0x6F51,0x6CFC}, {0x6F54,0x6D01}, {0x6F59,0x6CA9}, {0x6F5B,0x6F5C}, 
+  {0x6F64,0x6DA6}, {0x6F6F,0x6D54}, {0x6F70,0x6E83}, {0x6F77,0x6ED7}, {0x6F7F,0x6DA0}, 
+  {0x6F80,0x6DA9}, {0x6F86,0x6D47}, {0x6F87,0x6D9D}, {0x6F97,0x6DA7}, {0x6FA0,0x6E11}, 
+  {0x6FA4,0x6CFD}, {0x6FA9,0x6CF6}, {0x6FAE,0x6D4D}, {0x6FB1,0x6DC0}, {0x6FC1,0x6D4A}, 
+  {0x6FC3,0x6D53}, {0x6FD5,0x6E7F}, {0x6FD8,0x6CDE}, {0x6FDF,0x6D4E}, {0x6FE4,0x6D9B}, 
+  {0x6FEB,0x6EE5}, {0x6FF0,0x6F4D}, {0x6FF1,0x6EE8}, {0x6FFA,0x6E85}, {0x6FFC,0x6CFA}, 
+  {0x6FFE,0x6EE4}, {0x7005,0x6EE2}, {0x7006,0x6E0E}, {0x7009,0x6CFB}, {0x700B,0x6E16}, 
+  {0x700F,0x6D4F}, {0x7015,0x6FD2}, {0x7018,0x6CF8}, {0x701D,0x6CA5}, {0x701F,0x6F47}, 
+  {0x7020,0x6F46}, {0x7027,0x6CF7}, {0x7028,0x6FD1}, {0x7032,0x6F4B}, {0x703E,0x6F9C}, 
+  {0x7043,0x6CA3}, {0x7044,0x6EE0}, {0x7051,0x6D12}, {0x7055,0x6F13}, {0x7058,0x6EE9}, 
+  {0x705D,0x704F}, {0x7063,0x6E7E}, {0x7064,0x6EE6}, {0x7067,0x6EDF}, {0x70CF,0x4E4C}, 
+  {0x70F4,0x70C3}, {0x7121,0x65E0}, {0x7149,0x70BC}, {0x7152,0x709C}, {0x7162,0x8315}, 
+  {0x7165,0x7115}, {0x7169,0x70E6}, {0x716C,0x7080}, {0x7192,0x8367}, {0x7197,0x709D}, 
+  {0x71B1,0x70ED}, {0x71BE,0x70BD}, {0x71C1,0x70E8}, {0x71C8,0x706F}, {0x71D2,0x70E7}, 
+  {0x71D9,0x70EB}, {0x71DC,0x7116}, {0x71DF,0x8425}, {0x71E6,0x707F}, {0x71ED,0x70DB}, 
+  {0x71F4,0x70E9}, {0x71FC,0x70EC}, {0x71FE,0x7118}, {0x720D,0x70C1}, {0x7210,0x7089}, 
+  {0x721B,0x70C2}, {0x722D,0x4E89}, {0x7232,0x4E3A}, {0x723A,0x7237}, {0x723E,0x5C14}, 
+  {0x7258,0x724D}, {0x727D,0x7275}, {0x7296,0x8366}, {0x72A2,0x728A}, {0x72A7,0x727A}, 
+  {0x72C0,0x72B6}, {0x72F9,0x72ED}, {0x72FD,0x72C8}, {0x7319,0x72F0}, {0x7336,0x72B9}, 
+  {0x733B,0x72F2}, {0x7341,0x72B8}, {0x7344,0x72F1}, {0x7345,0x72EE}, {0x7368,0x72EC}, 
+  {0x736A,0x72EF}, {0x736B,0x7303}, {0x7370,0x72DE}, {0x7372,0x83B7}, {0x7375,0x730E}, 
+  {0x7377,0x72B7}, {0x7378,0x517D}, {0x737A,0x736D}, {0x737B,0x732E}, {0x737C,0x7315}, 
+  {0x7380,0x7321}, {0x73FE,0x73B0}, {0x743F,0x73F2}, {0x744B,0x73AE}, {0x7463,0x7410}, 
+  {0x7469,0x83B9}, {0x746A,0x739B}, {0x7489,0x740F}, {0x74A3,0x7391}, {0x74A6,0x7477}, 
+  {0x74B0,0x73AF}, {0x74BD,0x73BA}, {0x74CA,0x743C}, {0x74CF,0x73D1}, {0x74D4,0x748E}, 
+  {0x74DA,0x74D2}, {0x750C,0x74EF}, {0x7523,0x4EA7}, {0x755D,0x4EA9}, {0x7562,0x6BD5}, 
+  {0x756B,0x753B}, {0x7576,0x5F53}, {0x7587,0x7574}, {0x758A,0x53E0}, {0x75D9,0x75C9}, 
+  {0x7602,0x75D6}, {0x760B,0x75AF}, {0x760D,0x75A1}, {0x7613,0x75EA}, {0x761E,0x7617}, 
+  {0x7621,0x75AE}, {0x7627,0x759F}, {0x763B,0x7618}, {0x7642,0x7597}, {0x7646,0x75E8}, 
+  {0x7647,0x75EB}, {0x7649,0x7605}, {0x7658,0x75A0}, {0x765F,0x762A}, {0x7662,0x75D2}, 
+  {0x7664,0x7596}, {0x7665,0x75C7}, {0x7667,0x75AC}, {0x7669,0x765E}, {0x766C,0x7663}, 
+  {0x766D,0x763F}, {0x766E,0x763E}, {0x7670,0x75C8}, {0x7671,0x762B}, {0x7672,0x766B}, 
+  {0x767C,0x53D1}, {0x769A,0x7691}, {0x76B8,0x76B2}, {0x76BA,0x76B1}, {0x76DE,0x76CF}, 
+  {0x76E1,0x5C3D}, {0x76E3,0x76D1}, {0x76E4,0x76D8}, {0x76E7,0x5362}, {0x775C,0x7741}, 
+  {0x775E,0x7750}, {0x7798,0x770D}, {0x779E,0x7792}, {0x77BC,0x7751}, {0x77DA,0x77A9}, 
+  {0x77EF,0x77EB}, {0x7864,0x7856}, {0x7868,0x7817}, {0x786F,0x781A}, {0x78A9,0x7855}, 
+  {0x78AD,0x7800}, {0x78B8,0x781C}, {0x78BA,0x786E}, {0x78BC,0x7801}, {0x78DA,0x7816}, 
+  {0x78E3,0x789C}, {0x78E7,0x789B}, {0x78EF,0x77F6}, {0x78FD,0x7857}, {0x790E,0x7840}, 
+  {0x7919,0x788D}, {0x7926,0x77FF}, {0x792A,0x783A}, {0x792B,0x783E}, {0x792C,0x77FE}, 
+  {0x7931,0x783B}, {0x798D,0x7978}, {0x798E,0x796F}, {0x79AA,0x7985}, {0x79AE,0x793C}, 
+  {0x79B0,0x7962}, {0x79B1,0x7977}, {0x7A2E,0x79CD}, {0x7A31,0x79F0}, {0x7A4C,0x7A23}, 
+  {0x7A4D,0x79EF}, {0x7A4E,0x9896}, {0x7A61,0x7A51}, {0x7A62,0x79FD}, {0x7A69,0x7A33}, 
+  {0x7AA9,0x7A9D}, {0x7AAA,0x6D3C}, {0x7AAE,0x7A77}, {0x7AB6,0x7AAD}, {0x7ABA,0x7AA5}, 
+  {0x7AC4,0x7A9C}, {0x7AC5,0x7A8D}, {0x7AC7,0x7AA6}, {0x7AC8,0x7076}, {0x7ACA,0x7A83}, 
+  {0x7AEA,0x7AD6}, {0x7AF6,0x7ADE}, {0x7B46,0x7B14}, {0x7B67,0x7B15}, {0x7B8B,0x7B3A}, 
+  {0x7B8F,0x7B5D}, {0x7BC0,0x8282}, {0x7BC4,0x8303}, {0x7BC9,0x7B51}, {0x7BCB,0x7BA7}, 
+  {0x7BE4,0x7B03}, {0x7BE9,0x7B5B}, {0x7BF3,0x7B5A}, {0x7C00,0x7BA6}, {0x7C0D,0x7BD3}, 
+  {0x7C1E,0x7BAA}, {0x7C21,0x7B80}, {0x7C23,0x7BD1}, {0x7C2B,0x7BAB}, {0x7C3D,0x7B7E}, 
+  {0x7C3E,0x5E18}, {0x7C43,0x7BEE}, {0x7C4C,0x7B79}, {0x7C5C,0x7BA8}, {0x7C5F,0x7C41}, 
+  {0x7C60,0x7B3C}, {0x7C69,0x7B3E}, {0x7C6A,0x7C16}, {0x7C6C,0x7BF1}, {0x7C6E,0x7BA9}, 
+  {0x7CDD,0x7CC1}, {0x7CDE,0x7CAA}, {0x7CE7,0x7CAE}, {0x7CF2,0x7C9D}, {0x7CF4,0x7C74}, 
+  {0x7CF6,0x7C9C}, {0x7CF9,0x7E9F}, {0x7CFE,0x7EA0}, {0x7D00,0x7EAA}, {0x7D02,0x7EA3}, 
+  {0x7D04,0x7EA6}, {0x7D05,0x7EA2}, {0x7D06,0x7EA1}, {0x7D07,0x7EA5}, {0x7D08,0x7EA8}, 
+  {0x7D09,0x7EAB}, {0x7D0B,0x7EB9}, {0x7D0D,0x7EB3}, {0x7D10,0x7EBD}, {0x7D13,0x7EBE}, 
+  {0x7D14,0x7EAF}, {0x7D15,0x7EB0}, {0x7D17,0x7EB1}, {0x7D19,0x7EB8}, {0x7D1A,0x7EA7}, 
+  {0x7D1B,0x7EB7}, {0x7D1C,0x7EAD}, {0x7D21,0x7EBA}, {0x7D30,0x7EC6}, {0x7D31,0x7EC2}, 
+  {0x7D32,0x7EC1}, {0x7D33,0x7EC5}, {0x7D39,0x7ECD}, {0x7D3A,0x7EC0}, {0x7D3C,0x7ECB}, 
+  {0x7D3F,0x7ED0}, {0x7D40,0x7ECC}, {0x7D42,0x7EC8}, {0x7D44,0x7EC4}, {0x7D46,0x7ECA}, 
+  {0x7D4E,0x7ED7}, {0x7D50,0x7ED3}, {0x7D5D,0x7ED4}, {0x7D5E,0x7EDE}, {0x7D61,0x7EDC}, 
+  {0x7D62,0x7EDA}, {0x7D66,0x7ED9}, {0x7D68,0x7ED2}, {0x7D71,0x7EDF}, {0x7D72,0x4E1D}, 
+  {0x7D73,0x7EDB}, {0x7D76,0x7EDD}, {0x7D79,0x7EE2}, {0x7D81,0x7ED1}, {0x7D83,0x7EE1}, 
+  {0x7D86,0x7EE0}, {0x7D88,0x7EE8}, {0x7D89,0x7EE3}, {0x7D8F,0x7EE5}, {0x7D93,0x7ECF}, 
+  {0x7D9C,0x7EFC}, {0x7D9E,0x7F0D}, {0x7DA2,0x7EF8}, {0x7DA3,0x7EFB}, {0x7DAB,0x7EBF}, 
+  {0x7DAC,0x7EF6}, {0x7DAD,0x7EF4}, {0x7DB0,0x7EFE}, {0x7DB1,0x7EB2}, {0x7DB2,0x7F51}, 
+  {0x7DB3,0x7EF7}, {0x7DB4,0x7F00}, {0x7DB8,0x7EB6}, {0x7DB9,0x7EFA}, {0x7DBA,0x7EEE}, 
+  {0x7DBB,0x7EFD}, {0x7DBD,0x7EF0}, {0x7DBE,0x7EEB}, {0x7DBF,0x7EF5}, {0x7DC4,0x7EF2}, 
+  {0x7DC7,0x7F01}, {0x7DCA,0x7D27}, {0x7DCB,0x7EEF}, {0x7DD1,0x7EFF}, {0x7DD2,0x7EEA}, 
+  {0x7DD4,0x7EF1}, {0x7DD7,0x7F03}, {0x7DD8,0x7F04}, {0x7DD9,0x7F02}, {0x7DDD,0x7F09}, 
+  {0x7DDE,0x7F0E}, {0x7DE0,0x7F14}, {0x7DE1,0x7F17}, {0x7DE3,0x7F18}, {0x7DE6,0x7F0C}, 
+  {0x7DE8,0x7F16}, {0x7DE9,0x7F13}, {0x7DEC,0x7F05}, {0x7DEF,0x7EAC}, {0x7DF1,0x7F11}, 
+  {0x7DF2,0x7F08}, {0x7DF4,0x7EC3}, {0x7DF6,0x7F0F}, {0x7DF9,0x7F07}, {0x7E08,0x8426}, 
+  {0x7E09,0x7F19}, {0x7E0A,0x7F22}, {0x7E0B,0x7F12}, {0x7E10,0x7EC9}, {0x7E11,0x7F23}, 
+  {0x7E1B,0x7F1A}, {0x7E1D,0x7F1C}, {0x7E1E,0x7F1F}, {0x7E1F,0x7F1B}, {0x7E23,0x53BF}, 
+  {0x7E27,0x7EE6}, {0x7E2B,0x7F1D}, {0x7E2D,0x7F21}, {0x7E2E,0x7F29}, {0x7E31,0x7EB5}, 
+  {0x7E32,0x7F27}, {0x7E35,0x7F26}, {0x7E36,0x7D77}, {0x7E37,0x7F15}, {0x7E39,0x7F25}, 
+  {0x7E3D,0x603B}, {0x7E3E,0x7EE9}, {0x7E45,0x7F2B}, {0x7E46,0x7F2A}, {0x7E52,0x7F2F}, 
+  {0x7E54,0x7EC7}, {0x7E55,0x7F2E}, {0x7E5A,0x7F2D}, {0x7E5E,0x7ED5}, {0x7E62,0x7F0B}, 
+  {0x7E69,0x7EF3}, {0x7E6A,0x7ED8}, {0x7E6D,0x8327}, {0x7E6E,0x7F30}, {0x7E6F,0x7F33}, 
+  {0x7E70,0x7F32}, {0x7E73,0x7F34}, {0x7E79,0x7ECE}, {0x7E7C,0x7EE7}, {0x7E7D,0x7F24}, 
+  {0x7E7E,0x7F31}, {0x7E88,0x7F2C}, {0x7E8A,0x7EA9}, {0x7E8C,0x7EED}, {0x7E8F,0x7F20}, 
+  {0x7E93,0x7F28}, {0x7E96,0x7EA4}, {0x7E98,0x7F35}, {0x7E9C,0x7F06}, {0x7F4C,0x7F42}, 
+  {0x7F70,0x7F5A}, {0x7F77,0x7F62}, {0x7F85,0x7F57}, {0x7F86,0x7F74}, {0x7F88,0x7F81}, 
+  {0x7FA5,0x7F9F}, {0x7FA9,0x4E49}, {0x7FD2,0x4E60}, {0x7FF9,0x7FD8}, {0x802C,0x8027}, 
+  {0x802E,0x8022}, {0x8056,0x5723}, {0x805E,0x95FB}, {0x806F,0x8054}, {0x8070,0x806A}, 
+  {0x8072,0x58F0}, {0x8073,0x8038}, {0x8075,0x8069}, {0x8076,0x8042}, {0x8077,0x804C}, 
+  {0x8079,0x804D}, {0x807D,0x542C}, {0x807E,0x804B}, {0x8085,0x8083}, {0x8105,0x80C1}, 
+  {0x811B,0x80EB}, {0x8139,0x80C0}, {0x814E,0x80BE}, {0x8156,0x80E8}, {0x8161,0x8136}, 
+  {0x8166,0x8111}, {0x816B,0x80BF}, {0x8178,0x80A0}, {0x819A,0x80A4}, {0x81A0,0x80F6}, 
+  {0x81A9,0x817B}, {0x81BD,0x80C6}, {0x81BE,0x810D}, {0x81BF,0x8113}, {0x81C9,0x8138}, 
+  {0x81CD,0x8110}, {0x81CF,0x8191}, {0x81D8,0x814A}, {0x81DA,0x80EA}, {0x81DF,0x810F}, 
+  {0x81E0,0x8114}, {0x81E8,0x4E34}, {0x81FA,0x53F0}, {0x8207,0x4E0E}, {0x8208,0x5174}, 
+  {0x8209,0x4E3E}, {0x820A,0x65E7}, {0x8259,0x8231}, {0x8264,0x8223}, {0x8266,0x8230}, 
+  {0x826B,0x823B}, {0x8271,0x8270}, {0x8277,0x8273}, {0x82BB,0x520D}, {0x82E7,0x82CE}, 
+  {0x838A,0x5E84}, {0x8396,0x830E}, {0x83A2,0x835A}, {0x83A7,0x82CB}, {0x83EF,0x534E}, 
+  {0x8407,0x82CC}, {0x840A,0x83B1}, {0x842C,0x4E07}, {0x8435,0x83B4}, {0x8449,0x53F6}, 
+  {0x8452,0x836D}, {0x8464,0x836E}, {0x8466,0x82C7}, {0x8477,0x8364}, {0x8493,0x83BC}, 
+  {0x8494,0x83B3}, {0x84BC,0x82CD}, {0x84C0,0x836A}, {0x84CB,0x76D6}, {0x84EE,0x83B2}, 
+  {0x84EF,0x82C1}, {0x84FD,0x835C}, {0x851E,0x848C}, {0x8523,0x848B}, {0x8526,0x8311}, 
+  {0x852D,0x836B}, {0x8541,0x8368}, {0x8546,0x8487}, {0x854E,0x835E}, {0x8552,0x836C}, 
+  {0x8553,0x82B8}, {0x8555,0x83B8}, {0x8558,0x835B}, {0x8562,0x8489}, {0x8569,0x8361}, 
+  {0x856A,0x829C}, {0x856D,0x8427}, {0x8577,0x84E3}, {0x8588,0x835F}, {0x858A,0x84DF}, 
+  {0x858C,0x8297}, {0x8594,0x8537}, {0x859F,0x83B6}, {0x85A6,0x8350}, {0x85A9,0x8428}, 
+  {0x85BA,0x8360}, {0x85CD,0x84DD}, {0x85CE,0x8369}, {0x85DD,0x827A}, {0x85E5,0x836F}, 
+  {0x85EA,0x85AE}, {0x85F4,0x8574}, {0x85F6,0x82C8}, {0x85F9,0x853C}, {0x85FA,0x853A}, 
+  {0x8604,0x8572}, {0x8606,0x82A6}, {0x8607,0x82CF}, {0x860B,0x82F9}, {0x861A,0x85D3}, 
+  {0x861E,0x8539}, {0x8622,0x830F}, {0x862D,0x5170}, {0x863A,0x84E0}, {0x863F,0x841D}, 
+  {0x8655,0x5904}, {0x865C,0x864F}, {0x865F,0x53F7}, {0x8667,0x4E8F}, {0x86FA,0x86F1}, 
+  {0x8706,0x86AC}, {0x8755,0x8680}, {0x8766,0x867E}, {0x8778,0x8717}, {0x8784,0x86F3}, 
+  {0x879E,0x8682}, {0x87A2,0x8424}, {0x87BB,0x877C}, {0x87C4,0x86F0}, {0x87C8,0x8748}, 
+  {0x87CE,0x87A8}, {0x87E3,0x866E}, {0x87EC,0x8749}, {0x87EF,0x86F2}, {0x87F2,0x866B}, 
+  {0x87F6,0x86CF}, {0x87FB,0x8681}, {0x8805,0x8747}, {0x8806,0x867F}, {0x8810,0x86F4}, 
+  {0x8811,0x877E}, {0x881F,0x8721}, {0x8823,0x86CE}, {0x8831,0x86CA}, {0x8836,0x8695}, 
+  {0x883B,0x86EE}, {0x8846,0x4F17}, {0x8853,0x672F}, {0x885B,0x536B}, {0x885D,0x51B2}, 
+  {0x8879,0x53EA}, {0x88CA,0x8885}, {0x88CF,0x91CC}, {0x88DC,0x8865}, {0x88DD,0x88C5}, 
+  {0x8932,0x88E4}, {0x8933,0x88E2}, {0x8938,0x891B}, {0x893B,0x4EB5}, {0x8947,0x88E5}, 
+  {0x8956,0x8884}, {0x895D,0x88E3}, {0x8960,0x88C6}, {0x8964,0x8934}, {0x896A,0x889C}, 
+  {0x896F,0x886C}, {0x8972,0x88AD}, {0x898B,0x89C1}, {0x898F,0x89C4}, {0x8993,0x89C5}, 
+  {0x8996,0x89C6}, {0x8998,0x89C7}, {0x89A1,0x89CB}, {0x89A6,0x89CE}, {0x89AA,0x4EB2}, 
+  {0x89AC,0x89CA}, {0x89AF,0x89CF}, {0x89B2,0x89D0}, {0x89B7,0x89D1}, {0x89BA,0x89C9}, 
+  {0x89BD,0x89C8}, {0x89BF,0x89CC}, {0x89C0,0x89C2}, {0x89F4,0x89DE}, {0x89F6,0x89EF}, 
+  {0x89F8,0x89E6}, {0x8A01,0x8BA0}, {0x8A02,0x8BA2}, {0x8A03,0x8BA3}, {0x8A08,0x8BA1}, 
+  {0x8A0A,0x8BAF}, {0x8A0C,0x8BA7}, {0x8A0E,0x8BA8}, {0x8A10,0x8BA6}, {0x8A13,0x8BAD}, 
+  {0x8A15,0x8BAA}, {0x8A16,0x8BAB}, {0x8A18,0x8BB0}, {0x8A1B,0x8BB9}, {0x8A1D,0x8BB6}, 
+  {0x8A1F,0x8BBC}, {0x8A23,0x8BC0}, {0x8A25,0x8BB7}, {0x8A2A,0x8BBF}, {0x8A2D,0x8BBE}, 
+  {0x8A31,0x8BB8}, {0x8A34,0x8BC9}, {0x8A36,0x8BC3}, {0x8A3A,0x8BCA}, {0x8A41,0x8BC2}, 
+  {0x8A46,0x8BCB}, {0x8A4E,0x8BB5}, {0x8A50,0x8BC8}, {0x8A52,0x8BD2}, {0x8A54,0x8BCF}, 
+  {0x8A55,0x8BC4}, {0x8A58,0x8BCE}, {0x8A5B,0x8BC5}, {0x8A5E,0x8BCD}, {0x8A61,0x8BE9}, 
+  {0x8A62,0x8BE2}, {0x8A63,0x8BE3}, {0x8A66,0x8BD5}, {0x8A69,0x8BD7}, {0x8A6B,0x8BE7}, 
+  {0x8A6C,0x8BDF}, {0x8A6D,0x8BE1}, {0x8A6E,0x8BE0}, {0x8A70,0x8BD8}, {0x8A71,0x8BDD}, 
+  {0x8A72,0x8BE5}, {0x8A73,0x8BE6}, {0x8A75,0x8BDC}, {0x8A7C,0x8BD9}, {0x8A7F,0x8BD6}, 
+  {0x8A84,0x8BD4}, {0x8A85,0x8BDB}, {0x8A86,0x8BD3}, {0x8A87,0x5938}, {0x8A8D,0x8BA4}, 
+  {0x8A91,0x8BF3}, {0x8A92,0x8BF6}, {0x8A95,0x8BDE}, {0x8A98,0x8BF1}, {0x8A9A,0x8BEE}, 
+  {0x8A9E,0x8BED}, {0x8AA0,0x8BDA}, {0x8AA1,0x8BEB}, {0x8AA3,0x8BEC}, {0x8AA4,0x8BEF}, 
+  {0x8AA5,0x8BF0}, {0x8AA6,0x8BF5}, {0x8AA8,0x8BF2}, {0x8AAC,0x8BF4}, {0x8AB0,0x8C01}, 
+  {0x8AB2,0x8BFE}, {0x8AB6,0x8C07}, {0x8AB9,0x8BFD}, {0x8ABC,0x8C0A}, {0x8ABF,0x8C03}, 
+  {0x8AC2,0x8C04}, {0x8AC4,0x8C06}, {0x8AC7,0x8C08}, {0x8AC9,0x8BFF}, {0x8ACB,0x8BF7}, 
+  {0x8ACD,0x8BE4}, {0x8ACF,0x8BF9}, {0x8AD1,0x8BFC}, {0x8AD2,0x8C05}, {0x8AD6,0x8BBA}, 
+  {0x8AD7,0x8C02}, {0x8ADB,0x8C00}, {0x8ADC,0x8C0D}, {0x8ADE,0x8C1D}, {0x8AE2,0x8BE8}, 
+  {0x8AE4,0x8C14}, {0x8AE6,0x8C1B}, {0x8AE7,0x8C10}, {0x8AEB,0x8C0F}, {0x8AED,0x8C15}, 
+  {0x8AEE,0x8C18}, {0x8AF1,0x8BB3}, {0x8AF3,0x8C19}, {0x8AF6,0x8C0C}, {0x8AF7,0x8BBD}, 
+  {0x8AF8,0x8BF8}, {0x8AFA,0x8C1A}, {0x8AFC,0x8C16}, {0x8AFE,0x8BFA}, {0x8B00,0x8C0B}, 
+  {0x8B01,0x8C12}, {0x8B02,0x8C13}, {0x8B04,0x8A8A}, {0x8B05,0x8BCC}, {0x8B0A,0x8C0E}, 
+  {0x8B0E,0x8C1C}, {0x8B10,0x8C27}, {0x8B14,0x8C11}, {0x8B16,0x8C21}, {0x8B17,0x8C24}, 
+  {0x8B19,0x8C26}, {0x8B1A,0x8C25}, {0x8B1B,0x8BB2}, {0x8B1D,0x8C22}, {0x8B21,0x8C23}, 
+  {0x8B28,0x8C1F}, {0x8B2B,0x8C2A}, {0x8B2C,0x8C2C}, {0x8B2D,0x8C2B}, {0x8B33,0x8BB4}, 
+  {0x8B39,0x8C28}, {0x8B3E,0x8C29}, {0x8B49,0x8BC1}, {0x8B4E,0x8C32}, {0x8B4F,0x8BA5}, 
+  {0x8B56,0x8C2E}, {0x8B58,0x8BC6}, {0x8B59,0x8C2F}, {0x8B5A,0x8C2D}, {0x8B5C,0x8C31}, 
+  {0x8B6B,0x8C35}, {0x8B6F,0x8BD1}, {0x8B70,0x8BAE}, {0x8B74,0x8C34}, {0x8B77,0x62A4}, 
+  {0x8B7D,0x8A89}, {0x8B80,0x8BFB}, {0x8B8A,0x53D8}, {0x8B8E,0x96E0}, {0x8B92,0x8C17}, 
+  {0x8B93,0x8BA9}, {0x8B95,0x8C30}, {0x8B96,0x8C36}, {0x8B9C,0x8C20}, {0x8B9E,0x8C33}, 
+  {0x8C48,0x5C82}, {0x8C50,0x4E30}, {0x8C9D,0x8D1D}, {0x8C9E,0x8D1E}, {0x8CA0,0x8D1F}, 
+  {0x8CA1,0x8D22}, {0x8CA2,0x8D21}, {0x8CA7,0x8D2B}, {0x8CA8,0x8D27}, {0x8CA9,0x8D29}, 
+  {0x8CAA,0x8D2A}, {0x8CAB,0x8D2F}, {0x8CAC,0x8D23}, {0x8CAF,0x8D2E}, {0x8CB0,0x8D33}, 
+  {0x8CB2,0x8D40}, {0x8CB3,0x8D30}, {0x8CB4,0x8D35}, {0x8CB6,0x8D2C}, {0x8CB7,0x4E70}, 
+  {0x8CB8,0x8D37}, {0x8CBA,0x8D36}, {0x8CBB,0x8D39}, {0x8CBC,0x8D34}, {0x8CBD,0x8D3B}, 
+  {0x8CBF,0x8D38}, {0x8CC0,0x8D3A}, {0x8CC1,0x8D32}, {0x8CC2,0x8D42}, {0x8CC3,0x8D41}, 
+  {0x8CC4,0x8D3F}, {0x8CC5,0x8D45}, {0x8CC7,0x8D44}, {0x8CC8,0x8D3E}, {0x8CCA,0x8D3C}, 
+  {0x8CD1,0x8D48}, {0x8CD2,0x8D4A}, {0x8CD3,0x5BBE}, {0x8CD5,0x8D47}, {0x8CDA,0x8D49}, 
+  {0x8CDC,0x8D50}, {0x8CDE,0x8D4F}, {0x8CE0,0x8D54}, {0x8CE1,0x8D53}, {0x8CE2,0x8D24}, 
+  {0x8CE3,0x5356}, {0x8CE4,0x8D31}, {0x8CE6,0x8D4B}, {0x8CE7,0x8D55}, {0x8CEA,0x8D28}, 
+  {0x8CEB,0x8D4D}, {0x8CEC,0x8D26}, {0x8CED,0x8D4C}, {0x8CF4,0x8D56}, {0x8CFA,0x8D5A}, 
+  {0x8CFB,0x8D59}, {0x8CFC,0x8D2D}, {0x8CFD,0x8D5B}, {0x8CFE,0x8D5C}, {0x8D04,0x8D3D}, 
+  {0x8D05,0x8D58}, {0x8D08,0x8D60}, {0x8D0A,0x8D5E}, {0x8D0B,0x8D5D}, {0x8D0D,0x8D61}, 
+  {0x8D0F,0x8D62}, {0x8D10,0x8D46}, {0x8D16,0x8D4E}, {0x8D1B,0x8D63}, {0x8D1C,0x8D43}, 
+  {0x8D95,0x8D76}, {0x8D99,0x8D75}, {0x8DA8,0x8D8B}, {0x8DB2,0x8DB1}, {0x8E10,0x8DF5}, 
+  {0x8E34,0x8E0A}, {0x8E4C,0x8DC4}, {0x8E55,0x8DF8}, {0x8E63,0x8E52}, {0x8E7A,0x8DF7}, 
+  {0x8E89,0x8DB8}, {0x8E8A,0x8E0C}, {0x8E8B,0x8DFB}, {0x8E8D,0x8DC3}, {0x8E91,0x8E2F}, 
+  {0x8E92,0x8DDE}, {0x8E93,0x8E2C}, {0x8E9A,0x8DF9}, {0x8EA1,0x8E51}, {0x8EA5,0x8E7F}, 
+  {0x8EA6,0x8E9C}, {0x8EAA,0x8E8F}, {0x8EC0,0x8EAF}, {0x8ECA,0x8F66}, {0x8ECB,0x8F67}, 
+  {0x8ECC,0x8F68}, {0x8ECD,0x519B}, {0x8ED2,0x8F69}, {0x8ED4,0x8F6B}, {0x8EDB,0x8F6D}, 
+  {0x8EDF,0x8F6F}, {0x8EE4,0x8F77}, {0x8EEB,0x8F78}, {0x8EF2,0x8F71}, {0x8EF8,0x8F74}, 
+  {0x8EF9,0x8F75}, {0x8EFA,0x8F7A}, {0x8EFB,0x8F72}, {0x8EFC,0x8F76}, {0x8EFE,0x8F7C}, 
+  {0x8F03,0x8F83}, {0x8F05,0x8F82}, {0x8F07,0x8F81}, {0x8F09,0x8F7D}, {0x8F0A,0x8F7E}, 
+  {0x8F12,0x8F84}, {0x8F14,0x8F85}, {0x8F15,0x8F7B}, {0x8F1B,0x8F86}, {0x8F1C,0x8F8E}, 
+  {0x8F1D,0x8F89}, {0x8F1E,0x8F8B}, {0x8F1F,0x8F8D}, {0x8F25,0x8F8A}, {0x8F26,0x8F87}, 
+  {0x8F29,0x8F88}, {0x8F2A,0x8F6E}, {0x8F2F,0x8F91}, {0x8F33,0x8F8F}, {0x8F38,0x8F93}, 
+  {0x8F3B,0x8F90}, {0x8F3E,0x8F97}, {0x8F3F,0x8206}, {0x8F42,0x6BC2}, {0x8F44,0x8F96}, 
+  {0x8F45,0x8F95}, {0x8F46,0x8F98}, {0x8F49,0x8F6C}, {0x8F4D,0x8F99}, {0x8F4E,0x8F7F}, 
+  {0x8F54,0x8F9A}, {0x8F5F,0x8F70}, {0x8F61,0x8F94}, {0x8F62,0x8F79}, {0x8F64,0x8F73}, 
+  {0x8FA6,0x529E}, {0x8FAD,0x8F9E}, {0x8FAE,0x8FAB}, {0x8FAF,0x8FA9}, {0x8FB2,0x519C}, 
+  {0x9015,0x8FF3}, {0x9019,0x8FD9}, {0x9023,0x8FDE}, {0x9032,0x8FDB}, {0x904B,0x8FD0}, 
+  {0x904E,0x8FC7}, {0x9054,0x8FBE}, {0x9055,0x8FDD}, {0x905C,0x900A}, {0x905E,0x9012}, 
+  {0x9060,0x8FDC}, {0x9069,0x9002}, {0x9072,0x8FDF}, {0x9077,0x8FC1}, {0x9078,0x9009}, 
+  {0x907A,0x9057}, {0x907C,0x8FBD}, {0x9081,0x8FC8}, {0x9084,0x8FD8}, {0x9087,0x8FE9}, 
+  {0x908A,0x8FB9}, {0x908F,0x903B}, {0x9090,0x9026}, {0x90DF,0x90CF}, {0x90F5,0x90AE}, 
+  {0x9106,0x90D3}, {0x9109,0x4E61}, {0x9112,0x90B9}, {0x9114,0x90AC}, {0x9116,0x90E7}, 
+  {0x9127,0x9093}, {0x912D,0x90D1}, {0x9130,0x90BB}, {0x9132,0x90F8}, {0x9134,0x90BA}, 
+  {0x9136,0x90D0}, {0x913A,0x909D}, {0x9148,0x90E6}, {0x9196,0x915D}, {0x919C,0x4E11}, 
+  {0x91AB,0x533B}, {0x91AC,0x9171}, {0x91C0,0x917F}, {0x91C1,0x8845}, {0x91C3,0x917E}, 
+  {0x91C5,0x917D}, {0x91CB,0x91CA}, {0x91D2,0x9485}, {0x91D3,0x9486}, {0x91D4,0x9487}, 
+  {0x91D5,0x948C}, {0x91D7,0x948A}, {0x91D8,0x9489}, {0x91D9,0x948B}, {0x91DD,0x9488}, 
+  {0x91E3,0x9493}, {0x91E4,0x9490}, {0x91E7,0x948F}, {0x91E9,0x9492}, {0x91F5,0x9497}, 
+  {0x91F7,0x948D}, {0x91F9,0x9495}, {0x91FA,0x948E}, {0x9200,0x94AF}, {0x9201,0x94AB}, 
+  {0x9204,0x94AD}, {0x9208,0x949A}, {0x9209,0x94A0}, {0x920D,0x949D}, {0x920E,0x94A9}, 
+  {0x9210,0x94A4}, {0x9211,0x94A3}, {0x9214,0x949E}, {0x9215,0x94AE}, {0x921E,0x94A7}, 
+  {0x9223,0x9499}, {0x9225,0x94AC}, {0x9226,0x949B}, {0x9227,0x94AA}, {0x922E,0x94CC}, 
+  {0x9230,0x94C8}, {0x9233,0x94B6}, {0x9234,0x94C3}, {0x9237,0x94B4}, {0x9238,0x94B9}, 
+  {0x9239,0x94CD}, {0x923A,0x94B0}, {0x923D,0x94B8}, {0x923E,0x94C0}, {0x923F,0x94BF}, 
+  {0x9240,0x94BE}, {0x9245,0x949C}, {0x9248,0x94CA}, {0x9249,0x94C9}, {0x924D,0x94CB}, 
+  {0x9251,0x94C2}, {0x9255,0x94B7}, {0x9257,0x94B3}, {0x925A,0x94C6}, {0x925B,0x94C5}, 
+  {0x925E,0x94BA}, {0x9262,0x94B5}, {0x9266,0x94B2}, {0x926C,0x94BC}, {0x926D,0x94BD}, 
+  {0x9278,0x94F0}, {0x927A,0x94D2}, {0x927B,0x94EC}, {0x927F,0x94EA}, {0x9280,0x94F6}, 
+  {0x9283,0x94F3}, {0x9285,0x94DC}, {0x9291,0x94E3}, {0x9293,0x94E8}, {0x9296,0x94E2}, 
+  {0x9298,0x94ED}, {0x929A,0x94EB}, {0x929C,0x8854}, {0x92A0,0x94D1}, {0x92A3,0x94F7}, 
+  {0x92A5,0x94F1}, {0x92A6,0x94DF}, {0x92A8,0x94F5}, {0x92A9,0x94E5}, {0x92AA,0x94D5}, 
+  {0x92AB,0x94EF}, {0x92AC,0x94D0}, {0x92B1,0x94DE}, {0x92B7,0x9500}, {0x92B9,0x9508}, 
+  {0x92BB,0x9511}, {0x92BC,0x9509}, {0x92C1,0x94DD}, {0x92C3,0x9512}, {0x92C5,0x950C}, 
+  {0x92C7,0x94A1}, {0x92CC,0x94E4}, {0x92CF,0x94D7}, {0x92D2,0x950B}, {0x92DD,0x950A}, 
+  {0x92DF,0x9513}, {0x92E3,0x94D8}, {0x92E4,0x9504}, {0x92E5,0x9503}, {0x92E6,0x9514}, 
+  {0x92E8,0x9507}, {0x92EA,0x94FA}, {0x92ED,0x9510}, {0x92EE,0x94D6}, {0x92EF,0x9506}, 
+  {0x92F0,0x9502}, {0x92F1,0x94FD}, {0x92F6,0x950D}, {0x92F8,0x952F}, {0x92FC,0x94A2}, 
+  {0x9301,0x951E}, {0x9306,0x9516}, {0x9307,0x952B}, {0x9308,0x9529}, {0x9310,0x9525}, 
+  {0x9312,0x9515}, {0x9315,0x951F}, {0x9318,0x9524}, {0x9319,0x9531}, {0x931A,0x94EE}, 
+  {0x931B,0x951B}, {0x931F,0x952C}, {0x9320,0x952D}, {0x9322,0x94B1}, {0x9326,0x9526}, 
+  {0x9328,0x951A}, {0x932B,0x9521}, {0x932E,0x9522}, {0x932F,0x9519}, {0x9332,0x5F55}, 
+  {0x9333,0x9530}, {0x9338,0x94FC}, {0x9340,0x951D}, {0x9341,0x9528}, {0x9343,0x952A}, 
+  {0x9346,0x9494}, {0x9347,0x9534}, {0x934B,0x9505}, {0x934D,0x9540}, {0x9354,0x9537}, 
+  {0x9358,0x94E1}, {0x935B,0x953B}, {0x9364,0x9538}, {0x9365,0x9532}, {0x9369,0x9518}, 
+  {0x936C,0x9539}, {0x9370,0x953E}, {0x9375,0x952E}, {0x9376,0x9536}, {0x937A,0x9517}, 
+  {0x937E,0x953A}, {0x9382,0x9541}, {0x9384,0x953F}, {0x9387,0x9545}, {0x938A,0x9551}, 
+  {0x9396,0x9501}, {0x9398,0x9549}, {0x93A2,0x94A8}, {0x93A3,0x84E5}, {0x93A6,0x954F}, 
+  {0x93A7,0x94E0}, {0x93A9,0x94E9}, {0x93AA,0x953C}, {0x93AC,0x9550}, {0x93AE,0x9547}, 
+  {0x93B0,0x9552}, {0x93B3,0x954D}, {0x93B5,0x9553}, {0x93B8,0x954C}, {0x93BF,0x954E}, 
+  {0x93C3,0x955E}, {0x93C7,0x955F}, {0x93C8,0x94FE}, {0x93CC,0x9546}, {0x93CD,0x9559}, 
+  {0x93D1,0x955D}, {0x93D7,0x94FF}, {0x93D8,0x9535}, {0x93DC,0x9557}, {0x93DD,0x9558}, 
+  {0x93DE,0x955B}, {0x93DF,0x94F2}, {0x93E1,0x955C}, {0x93E2,0x9556}, {0x93E4,0x9542}, 
+  {0x93E8,0x933E}, {0x93F5,0x94E7}, {0x93F7,0x9564}, {0x93F9,0x956A}, {0x9403,0x94D9}, 
+  {0x940B,0x94F4}, {0x9410,0x9563}, {0x9412,0x94F9}, {0x9413,0x9566}, {0x9414,0x9561}, 
+  {0x9418,0x949F}, {0x9419,0x956B}, {0x941D,0x9562}, {0x9420,0x9568}, {0x9426,0x950E}, 
+  {0x9427,0x950F}, {0x9428,0x9544}, {0x942E,0x9570}, {0x9432,0x956F}, {0x9433,0x956D}, 
+  {0x9435,0x94C1}, {0x9438,0x94CE}, {0x943A,0x94DB}, {0x943F,0x9571}, {0x9444,0x94F8}, 
+  {0x944A,0x956C}, {0x944C,0x9554}, {0x9452,0x9274}, {0x9454,0x9572}, {0x9460,0x94C4}, 
+  {0x9463,0x9573}, {0x9465,0x9565}, {0x946D,0x9567}, {0x9470,0x94A5}, {0x9472,0x9576}, 
+  {0x9477,0x954A}, {0x9479,0x9569}, {0x947C,0x9523}, {0x947D,0x94BB}, {0x947E,0x92AE}, 
+  {0x947F,0x51FF}, {0x9577,0x957F}, {0x9580,0x95E8}, {0x9582,0x95E9}, {0x9583,0x95EA}, 
+  {0x9586,0x95EB}, {0x9589,0x95ED}, {0x958B,0x5F00}, {0x958C,0x95F6}, {0x958E,0x95F3}, 
+  {0x958F,0x95F0}, {0x9591,0x95F2}, {0x9593,0x95F4}, {0x9594,0x95F5}, {0x9598,0x95F8}, 
+  {0x95A1,0x9602}, {0x95A3,0x9601}, {0x95A5,0x9600}, {0x95A8,0x95FA}, {0x95A9,0x95FD}, 
+  {0x95AB,0x9603}, {0x95AC,0x9606}, {0x95AD,0x95FE}, {0x95B2,0x9605}, {0x95B6,0x960A}, 
+  {0x95B9,0x9609}, {0x95BB,0x960E}, {0x95BC,0x960F}, {0x95BD,0x960D}, {0x95BE,0x9608}, 
+  {0x95BF,0x960C}, {0x95C3,0x9612}, {0x95C8,0x95F1}, {0x95CA,0x9614}, {0x95CB,0x9615}, 
+  {0x95CC,0x9611}, {0x95D0,0x9617}, {0x95D4,0x9616}, {0x95D5,0x9619}, {0x95D6,0x95EF}, 
+  {0x95DC,0x5173}, {0x95DE,0x961A}, {0x95E1,0x9610}, {0x95E5,0x95FC}, {0x9658,0x9649}, 
+  {0x965D,0x9655}, {0x9663,0x9635}, {0x9670,0x9634}, {0x9673,0x9648}, {0x9678,0x9646}, 
+  {0x967D,0x9633}, {0x9689,0x9667}, {0x968A,0x961F}, {0x968E,0x9636}, {0x9695,0x9668}, 
+  {0x969B,0x9645}, {0x96A8,0x968F}, {0x96AA,0x9669}, {0x96B1,0x9690}, {0x96B4,0x9647}, 
+  {0x96B8,0x96B6}, {0x96D6,0x867D}, {0x96D9,0x53CC}, {0x96DB,0x96CF}, {0x96DC,0x6742}, 
+  {0x96E2,0x79BB}, {0x96E3,0x96BE}, {0x96F2,0x4E91}, {0x96FB,0x7535}, {0x9727,0x96FE}, 
+  {0x973D,0x9701}, {0x9742,0x96F3}, {0x9744,0x972D}, {0x9748,0x7075}, {0x975A,0x9753}, 
+  {0x975C,0x9759}, {0x9768,0x9765}, {0x978F,0x5DE9}, {0x97BD,0x9792}, {0x97C3,0x9791}, 
+  {0x97C9,0x97AF}, {0x97CB,0x97E6}, {0x97CC,0x97E7}, {0x97D3,0x97E9}, {0x97D9,0x97EA}, 
+  {0x97DC,0x97EC}, {0x97DE,0x97EB}, {0x97FF,0x54CD}, {0x9801,0x9875}, {0x9802,0x9876}, 
+  {0x9803,0x9877}, {0x9805,0x9879}, {0x9806,0x987A}, {0x9807,0x9878}, {0x9808,0x987B}, 
+  {0x980A,0x987C}, {0x980C,0x9882}, {0x980E,0x9880}, {0x980F,0x9883}, {0x9810,0x9884}, 
+  {0x9811,0x987D}, {0x9812,0x9881}, {0x9813,0x987F}, {0x9817,0x9887}, {0x9818,0x9886}, 
+  {0x981C,0x988C}, {0x9821,0x9889}, {0x9824,0x9890}, {0x9826,0x988F}, {0x982D,0x5934}, 
+  {0x9830,0x988A}, {0x9837,0x9894}, {0x9838,0x9888}, {0x983B,0x9891}, {0x983D,0x9893}, 
+  {0x9846,0x9897}, {0x984C,0x9898}, {0x984D,0x989D}, {0x984E,0x989A}, {0x9853,0x989B}, 
+  {0x9854,0x989C}, {0x9858,0x613F}, {0x9859,0x98A1}, {0x985B,0x98A0}, {0x985E,0x7C7B}, 
+  {0x9862,0x989F}, {0x9865,0x98A2}, {0x9867,0x987E}, {0x986B,0x98A4}, {0x986C,0x98A5}, 
+  {0x986F,0x663E}, {0x9870,0x98A6}, {0x9871,0x9885}, {0x9873,0x989E}, {0x9874,0x98A7}, 
+  {0x98A8,0x98CE}, {0x98AE,0x98D1}, {0x98AF,0x98D2}, {0x98B6,0x98D3}, {0x98BC,0x98D5}, 
+  {0x98C4,0x98D8}, {0x98C6,0x98D9}, {0x98C8,0x98DA}, {0x98DB,0x98DE}, {0x98E0,0x9963}, 
+  {0x98E9,0x9968}, {0x98EA,0x996A}, {0x98EB,0x996B}, {0x98ED,0x996C}, {0x98EF,0x996D}, 
+  {0x98F2,0x996E}, {0x98F4,0x9974}, {0x98FC,0x9972}, {0x98FD,0x9971}, {0x98FE,0x9970}, 
+  {0x9903,0x997A}, {0x9905,0x997C}, {0x9909,0x9977}, {0x990A,0x517B}, {0x990C,0x9975}, 
+  {0x9911,0x997D}, {0x9912,0x9981}, {0x9913,0x997F}, {0x9918,0x4F59}, {0x991B,0x9984}, 
+  {0x991E,0x996F}, {0x9921,0x9985}, {0x9928,0x9986}, {0x9933,0x9967}, {0x9937,0x9987}, 
+  {0x993C,0x9969}, {0x993E,0x998F}, {0x993F,0x998A}, {0x9943,0x998D}, {0x9945,0x9992}, 
+  {0x9948,0x9990}, {0x9949,0x9991}, {0x994A,0x9993}, {0x994B,0x9988}, {0x994C,0x9994}, 
+  {0x9951,0x9965}, {0x9952,0x9976}, {0x9957,0x98E8}, {0x995C,0x990D}, {0x995E,0x998B}, 
+  {0x9962,0x9995}, {0x99AC,0x9A6C}, {0x99AD,0x9A6D}, {0x99AE,0x51AF}, {0x99B1,0x9A6E}, 
+  {0x99B3,0x9A70}, {0x99B4,0x9A6F}, {0x99C1,0x9A73}, {0x99D0,0x9A7B}, {0x99D1,0x9A7D}, 
+  {0x99D2,0x9A79}, {0x99D4,0x9A75}, {0x99D5,0x9A7E}, {0x99D8,0x9A80}, {0x99D9,0x9A78}, 
+  {0x99DB,0x9A76}, {0x99DD,0x9A7C}, {0x99DF,0x9A77}, {0x99E1,0x9A82}, {0x99E2,0x9A88}, 
+  {0x99ED,0x9A87}, {0x99F1,0x9A86}, {0x99FF,0x9A8F}, {0x9A01,0x9A8B}, {0x9A05,0x9A93}, 
+  {0x9A0D,0x9A92}, {0x9A0E,0x9A91}, {0x9A0F,0x9A90}, {0x9A16,0x9A9B}, {0x9A19,0x9A97}, 
+  {0x9A2B,0x9A9E}, {0x9A2D,0x9A98}, {0x9A2E,0x9A9D}, {0x9A30,0x817E}, {0x9A36,0x9A7A}, 
+  {0x9A37,0x9A9A}, {0x9A38,0x9A9F}, {0x9A3E,0x9AA1}, {0x9A40,0x84E6}, {0x9A41,0x9A9C}, 
+  {0x9A42,0x9A96}, {0x9A43,0x9AA0}, {0x9A44,0x9AA2}, {0x9A45,0x9A71}, {0x9A4A,0x9A85}, 
+  {0x9A4D,0x9A81}, {0x9A4F,0x9AA3}, {0x9A55,0x9A84}, {0x9A57,0x9A8C}, {0x9A5A,0x60CA}, 
+  {0x9A5B,0x9A7F}, {0x9A5F,0x9AA4}, {0x9A62,0x9A74}, {0x9A64,0x9AA7}, {0x9A65,0x9AA5}, 
+  {0x9A6A,0x9A8A}, {0x9AAF,0x80AE}, {0x9ACF,0x9AC5}, {0x9AD4,0x4F53}, {0x9AD5,0x9ACC}, 
+  {0x9AD6,0x9ACB}, {0x9B06,0x677E}, {0x9B22,0x9B13}, {0x9B25,0x6597}, {0x9B27,0x95F9}, 
+  {0x9B29,0x960B}, {0x9B2E,0x9604}, {0x9B31,0x90C1}, {0x9B4E,0x9B49}, {0x9B58,0x9B47}, 
+  {0x9B5A,0x9C7C}, {0x9B6F,0x9C81}, {0x9B74,0x9C82}, {0x9B77,0x9C7F}, {0x9B81,0x9C85}, 
+  {0x9B83,0x9C86}, {0x9B8E,0x9C87}, {0x9B90,0x9C90}, {0x9B91,0x9C8D}, {0x9B92,0x9C8B}, 
+  {0x9B9A,0x9C92}, {0x9B9D,0x9C9E}, {0x9B9E,0x9C95}, {0x9BAA,0x9C94}, {0x9BAB,0x9C9B}, 
+  {0x9BAD,0x9C91}, {0x9BAE,0x9C9C}, {0x9BC0,0x9CA7}, {0x9BC1,0x9CA0}, {0x9BC7,0x9CA9}, 
+  {0x9BC9,0x9CA4}, {0x9BCA,0x9CA8}, {0x9BD4,0x9CBB}, {0x9BD6,0x9CAD}, {0x9BDB,0x9CB7}, 
+  {0x9BDD,0x9CB4}, {0x9BE1,0x9CB1}, {0x9BE2,0x9CB5}, {0x9BE4,0x9CB2}, {0x9BE7,0x9CB3}, 
+  {0x9BE8,0x9CB8}, {0x9BEA,0x9CAE}, {0x9BEB,0x9CB0}, {0x9BF0,0x9CB6}, {0x9BF4,0x9CBA}, 
+  {0x9BFD,0x9CAB}, {0x9BFF,0x9CCA}, {0x9C08,0x9CBD}, {0x9C09,0x9CC7}, {0x9C0D,0x9CC5}, 
+  {0x9C10,0x9CC4}, {0x9C12,0x9CC6}, {0x9C13,0x9CC3}, {0x9C20,0x9CCB}, {0x9C23,0x9CA5}, 
+  {0x9C25,0x9CCF}, {0x9C28,0x9CCE}, {0x9C29,0x9CD0}, {0x9C2D,0x9CCD}, {0x9C31,0x9CA2}, 
+  {0x9C32,0x9CCC}, {0x9C33,0x9CD3}, {0x9C35,0x9CD8}, {0x9C37,0x9CA6}, {0x9C39,0x9CA3}, 
+  {0x9C3B,0x9CD7}, {0x9C3E,0x9CD4}, {0x9C45,0x9CD9}, {0x9C48,0x9CD5}, {0x9C49,0x9CD6}, 
+  {0x9C52,0x9CDF}, {0x9C54,0x9CDD}, {0x9C56,0x9CDC}, {0x9C57,0x9CDE}, {0x9C58,0x9C9F}, 
+  {0x9C5D,0x9CBC}, {0x9C5F,0x9C8E}, {0x9C67,0x9CE2}, {0x9C6D,0x9C9A}, {0x9C78,0x9C88}, 
+  {0x9C7A,0x9CA1}, {0x9CE5,0x9E1F}, {0x9CE9,0x9E20}, {0x9CEC,0x51EB}, {0x9CF3,0x51E4}, 
+  {0x9CF4,0x9E23}, {0x9CF6,0x9E22}, {0x9D06,0x9E29}, {0x9D07,0x9E28}, {0x9D09,0x9E26}, 
+  {0x9D15,0x9E35}, {0x9D1B,0x9E33}, {0x9D1D,0x9E32}, {0x9D1F,0x9E31}, {0x9D23,0x9E2A}, 
+  {0x9D26,0x9E2F}, {0x9D28,0x9E2D}, {0x9D2F,0x9E38}, {0x9D30,0x9E39}, {0x9D3B,0x9E3F}, 
+  {0x9D3F,0x9E3D}, {0x9D42,0x9E3A}, {0x9D51,0x9E43}, {0x9D52,0x9E46}, {0x9D53,0x9E41}, 
+  {0x9D5C,0x9E48}, {0x9D5D,0x9E45}, {0x9D60,0x9E44}, {0x9D61,0x9E49}, {0x9D6A,0x9E4C}, 
+  {0x9D6C,0x9E4F}, {0x9D6F,0x9E4E}, {0x9D72,0x9E4A}, {0x9D87,0x9E2B}, {0x9D89,0x9E51}, 
+  {0x9D93,0x9E4B}, {0x9D98,0x9E55}, {0x9D9A,0x9E57}, {0x9DA5,0x9E5B}, {0x9DA9,0x9E5C}, 
+  {0x9DAF,0x83BA}, {0x9DB4,0x9E64}, {0x9DBB,0x9E58}, {0x9DBC,0x9E63}, {0x9DC0,0x9E5A}, 
+  {0x9DC2,0x9E5E}, {0x9DC4,0x9E21}, {0x9DD3,0x9E67}, {0x9DD7,0x9E25}, {0x9DD9,0x9E37}, 
+  {0x9DDA,0x9E68}, {0x9DE5,0x9E36}, {0x9DE6,0x9E6A}, {0x9DEF,0x9E69}, {0x9DF2,0x9E6B}, 
+  {0x9DF3,0x9E47}, {0x9DF8,0x9E6C}, {0x9DF9,0x9E70}, {0x9DFA,0x9E6D}, {0x9E0C,0x9E71}, 
+  {0x9E15,0x9E2C}, {0x9E1A,0x9E66}, {0x9E1B,0x9E73}, {0x9E1D,0x9E42}, {0x9E1E,0x9E3E}, 
+  {0x9E7A,0x9E7E}, {0x9E7C,0x7877}, {0x9E7D,0x76D0}, {0x9E97,0x4E3D}, {0x9EA5,0x9EA6}, 
+  {0x9EA9,0x9EB8}, {0x9EBD,0x4E48}, {0x9ECC,0x9EC9}, {0x9EDE,0x70B9}, {0x9EE8,0x515A}, 
+  {0x9EF2,0x9EEA}, {0x9EF7,0x9EE9}, {0x9EFD,0x9EFE}, {0x9EFF,0x9F0B}, {0x9F09,0x9F0D}, 
+  {0x9F4A,0x9F50}, {0x9F4B,0x658B}, {0x9F4F,0x9F51}, {0x9F52,0x9F7F}, {0x9F54,0x9F80}, 
+  {0x9F59,0x9F85}, {0x9F5C,0x9F87}, {0x9F5F,0x9F83}, {0x9F60,0x9F86}, {0x9F61,0x9F84}, 
+  {0x9F66,0x9F88}, {0x9F6A,0x9F8A}, {0x9F6C,0x9F89}, {0x9F72,0x9F8B}, {0x9F77,0x9F8C}, 
+  {0x9F8D,0x9F99}, {0x9F90,0x5E9E}, {0x9F94,0x9F9A}, {0x9F95,0x9F9B}, {0x9F9C,0x9F9F}
+};
+
+
+
+/* the letters correspond to unicode characters which
+ * have Lu, Ll, Lt, Lm, Lo, Mn, Mc, or Me in their
+ * GENERAL CATEGORY */
+
+#define NUM_LETTER_INFO 276
+static const unirange letter_info[NUM_LETTER_INFO] = {
+  {0x41,0x5a}, {0x61,0x7a}, {0xaa,0xaa}, {0xb5,0xb5}, 
+  {0xba,0xba}, {0xc0,0xd6}, {0xd8,0xf6}, {0xf8,0x1f5}, 
+  {0x1fa,0x217}, {0x250,0x2a8}, {0x2b0,0x2b8}, {0x2bb,0x2c1}, 
+  {0x2d0,0x2d1}, {0x2e0,0x2e4}, {0x300,0x345}, {0x360,0x361}, 
+  {0x37a,0x37a}, {0x386,0x386}, {0x388,0x38a}, {0x38c,0x38c}, 
+  {0x38e,0x3a1}, {0x3a3,0x3ce}, {0x3d0,0x3d6}, {0x3da,0x3da}, 
+  {0x3dc,0x3dc}, {0x3de,0x3de}, {0x3e0,0x3e0}, {0x3e2,0x3f3}, 
+  {0x401,0x40c}, {0x40e,0x44f}, {0x451,0x45c}, {0x45e,0x481}, 
+  {0x483,0x486}, {0x490,0x4c4}, {0x4c7,0x4c8}, {0x4cb,0x4cc}, 
+  {0x4d0,0x4eb}, {0x4ee,0x4f5}, {0x4f8,0x4f9}, {0x531,0x556}, 
+  {0x559,0x559}, {0x561,0x587}, {0x591,0x5a1}, {0x5a3,0x5b9}, 
+  {0x5bb,0x5bd}, {0x5bf,0x5bf}, {0x5c1,0x5c2}, {0x5c4,0x5c4}, 
+  {0x5d0,0x5ea}, {0x5f0,0x5f2}, {0x621,0x63a}, {0x640,0x652}, 
+  {0x670,0x6b7}, {0x6ba,0x6be}, {0x6c0,0x6ce}, {0x6d0,0x6d3}, 
+  {0x6d5,0x6e8}, {0x6ea,0x6ed}, {0x901,0x903}, {0x905,0x939}, 
+  {0x93c,0x94d}, {0x951,0x954}, {0x958,0x963}, {0x981,0x983}, 
+  {0x985,0x98c}, {0x98f,0x990}, {0x993,0x9a8}, {0x9aa,0x9b0}, 
+  {0x9b2,0x9b2}, {0x9b6,0x9b9}, {0x9bc,0x9bc}, {0x9be,0x9c4}, 
+  {0x9c7,0x9c8}, {0x9cb,0x9cd}, {0x9d7,0x9d7}, {0x9dc,0x9dd}, 
+  {0x9df,0x9e3}, {0x9f0,0x9f1}, {0xa02,0xa02}, {0xa05,0xa0a}, 
+  {0xa0f,0xa10}, {0xa13,0xa28}, {0xa2a,0xa30}, {0xa32,0xa33}, 
+  {0xa35,0xa36}, {0xa38,0xa39}, {0xa3c,0xa3c}, {0xa3e,0xa42}, 
+  {0xa47,0xa48}, {0xa4b,0xa4d}, {0xa59,0xa5c}, {0xa5e,0xa5e}, 
+  {0xa70,0xa74}, {0xa81,0xa83}, {0xa85,0xa8b}, {0xa8d,0xa8d}, 
+  {0xa8f,0xa91}, {0xa93,0xaa8}, {0xaaa,0xab0}, {0xab2,0xab3}, 
+  {0xab5,0xab9}, {0xabc,0xac5}, {0xac7,0xac9}, {0xacb,0xacd}, 
+  {0xae0,0xae0}, {0xb01,0xb03}, {0xb05,0xb0c}, {0xb0f,0xb10}, 
+  {0xb13,0xb28}, {0xb2a,0xb30}, {0xb32,0xb33}, {0xb36,0xb39}, 
+  {0xb3c,0xb43}, {0xb47,0xb48}, {0xb4b,0xb4d}, {0xb56,0xb57}, 
+  {0xb5c,0xb5d}, {0xb5f,0xb61}, {0xb82,0xb83}, {0xb85,0xb8a}, 
+  {0xb8e,0xb90}, {0xb92,0xb95}, {0xb99,0xb9a}, {0xb9c,0xb9c}, 
+  {0xb9e,0xb9f}, {0xba3,0xba4}, {0xba8,0xbaa}, {0xbae,0xbb5}, 
+  {0xbb7,0xbb9}, {0xbbe,0xbc2}, {0xbc6,0xbc8}, {0xbca,0xbcd}, 
+  {0xbd7,0xbd7}, {0xc01,0xc03}, {0xc05,0xc0c}, {0xc0e,0xc10}, 
+  {0xc12,0xc28}, {0xc2a,0xc33}, {0xc35,0xc39}, {0xc3e,0xc44}, 
+  {0xc46,0xc48}, {0xc4a,0xc4d}, {0xc55,0xc56}, {0xc60,0xc61}, 
+  {0xc82,0xc83}, {0xc85,0xc8c}, {0xc8e,0xc90}, {0xc92,0xca8}, 
+  {0xcaa,0xcb3}, {0xcb5,0xcb9}, {0xcbe,0xcc4}, {0xcc6,0xcc8}, 
+  {0xcca,0xccd}, {0xcd5,0xcd6}, {0xcde,0xcde}, {0xce0,0xce1}, 
+  {0xd02,0xd03}, {0xd05,0xd0c}, {0xd0e,0xd10}, {0xd12,0xd28}, 
+  {0xd2a,0xd39}, {0xd3e,0xd43}, {0xd46,0xd48}, {0xd4a,0xd4d}, 
+  {0xd57,0xd57}, {0xd60,0xd61}, {0xe01,0xe2e}, {0xe30,0xe3a}, 
+  {0xe40,0xe4e}, {0xe81,0xe82}, {0xe84,0xe84}, {0xe87,0xe88}, 
+  {0xe8a,0xe8a}, {0xe8d,0xe8d}, {0xe94,0xe97}, {0xe99,0xe9f}, 
+  {0xea1,0xea3}, {0xea5,0xea5}, {0xea7,0xea7}, {0xeaa,0xeab}, 
+  {0xead,0xeae}, {0xeb0,0xeb9}, {0xebb,0xebd}, {0xec0,0xec4}, 
+  {0xec6,0xec6}, {0xec8,0xecd}, {0xedc,0xedd}, {0xf18,0xf19}, 
+  {0xf35,0xf35}, {0xf37,0xf37}, {0xf39,0xf39}, {0xf40,0xf47}, 
+  {0xf49,0xf69}, {0xf71,0xf84}, {0xf86,0xf87}, {0xf90,0xf95}, 
+  {0xf97,0xf97}, {0xf99,0xfad}, {0xfb1,0xfb7}, {0xfb9,0xfb9}, 
+  {0x10a0,0x10c5}, {0x10d0,0x10f6}, {0x1100,0x1159}, {0x115f,0x11a2}, 
+  {0x11a8,0x11f9}, {0x1820,0x1877}, {0x1880,0x18a9}, {0x1e00,0x1e9b}, 
+  {0x1ea0,0x1ef9}, {0x1f00,0x1f15}, 
+  {0x1f18,0x1f1d}, {0x1f20,0x1f45}, {0x1f48,0x1f4d}, {0x1f50,0x1f57}, 
+  {0x1f59,0x1f59}, {0x1f5b,0x1f5b}, {0x1f5d,0x1f5d}, {0x1f5f,0x1f7d}, 
+  {0x1f80,0x1fb4}, {0x1fb6,0x1fbc}, {0x1fbe,0x1fbe}, {0x1fc2,0x1fc4}, 
+  {0x1fc6,0x1fcc}, {0x1fd0,0x1fd3}, {0x1fd6,0x1fdb}, {0x1fe0,0x1fec}, 
+  {0x1ff2,0x1ff4}, {0x1ff6,0x1ffc}, {0x207f,0x207f}, {0x20d0,0x20e1}, 
+  {0x2102,0x2102}, {0x2107,0x2107}, {0x210a,0x2113}, {0x2115,0x2115}, 
+  {0x2118,0x211d}, {0x2124,0x2124}, {0x2126,0x2126}, {0x2128,0x2128}, 
+  {0x212a,0x2131}, {0x2133,0x2138}, {0x3005,0x3005}, {0x302a,0x302f}, 
+  {0x3031,0x3035}, {0x3041,0x3094}, {0x3099,0x309e}, {0x30a1,0x30fa}, 
+  {0x30fc,0x30fe}, {0x3105,0x312c}, {0x3131,0x318e}, {0x4e00,0x9fa5}, 
+  {0xac00,0xd7a3}, {0xf900,0xfa2d}, {0xfb00,0xfb06}, {0xfb13,0xfb17}, 
+  {0xfb1e,0xfb28}, {0xfb2a,0xfb36}, {0xfb38,0xfb3c}, {0xfb3e,0xfb3e}, 
+  {0xfb40,0xfb41}, {0xfb43,0xfb44}, {0xfb46,0xfbb1}, {0xfbd3,0xfd3d}, 
+  {0xfd50,0xfd8f}, {0xfd92,0xfdc7}, {0xfdf0,0xfdfb}, {0xfe20,0xfe23}, 
+  {0xfe70,0xfe72}, {0xfe74,0xfe74}, {0xfe76,0xfefc}, {0xff21,0xff3a}, 
+  {0xff41,0xff5a}, {0xff66,0xffbe}, {0xffc2,0xffc7}, {0xffca,0xffcf}, 
+  {0xffd2,0xffd7}, {0xffda,0xffdc}
+};
+
+
+/* the digits correspond to unicode characters which
+ * have Nd in their GENERAL CATEGORY */
+
+#define NUM_DIGIT_INFO 17
+static const unirange digit_info[NUM_DIGIT_INFO] = {
+  {0x30,0x39}, {0x660,0x669}, {0x6f0,0x6f9}, {0x966,0x96f}, 
+  {0x9e6,0x9ef}, {0xa66,0xa6f}, {0xae6,0xaef}, {0xb66,0xb6f}, 
+  {0xbe7,0xbef}, {0xc66,0xc6f}, {0xce6,0xcef}, {0xd66,0xd6f}, 
+  {0xe50,0xe59}, {0xed0,0xed9}, {0xf20,0xf29}, {0xff10,0xff19},
+  {0x1810,0x1819}
+};
+
+
+/* the spaces correspond to unicode characters which
+ * have Zs, Zl, or Zp in their GENERAL CATEGORY */
+
+#define NUM_SPACE_INFO 5
+static const unirange space_info[NUM_SPACE_INFO] = {
+  {0x20,0x20}, {0xa0,0xa0}, {0x2000,0x200b}, {0x2028,0x2029}, 
+  {0x3000,0x3000}
+};
+
+
+
+/* parse_utf8_char parses the next utf-8 character, placing its
+ * unicode equivalent in *value. The length of the utf-8 character
+ * is returned */
+int parse_utf8_char(const unsigned char *here,
+		    const unsigned char *end,
+		    unsigned short *value) {
+  unsigned short c1;
+  unsigned short c2;
+  unsigned short c3;
+  
+  *value = 0; /* will be the value for illegal characters */
+  
+  if (here <= end) {
+    c1 = (unsigned short)(*here);
+    
+    if (c1 <= 0x7f) {
+      /* found a one-byte character */
+      *value = c1;
+      return 1;
+      
+    } else if (c1 >= 0xc0 && c1 <= 0xdf && here+1 <= end &&
+	       (c2=(unsigned short)(*(here+1))) >= 0x80) {
+      /* found a two-byte character */
+      *value = ((c1 & 0x1f) << 6) + (c2 & 0x3f);
+      return 2;
+      
+    } else if (c1 >= 0xe0 && c1 <= 0xef && here+2 <= end &&
+	       (c2=(unsigned int)(*(here+1))) >= 0x80 &&
+	       (c3=(unsigned int)(*(here+2))) >= 0x80) {
+      /* found a three-byte character */
+      *value = ((c1 & 0xf) << 12) + ((c2 & 0x3f) << 6) +
+	(c3 & 0x3f);
+      return 3;
+      
+    } else {
+      /* error in encoding, return the length as 1 */
+      return 1;
+    }
+  }
+
+  /* end of string */
+  return 0;
+}
+
+
+/* output_utf8_char encodes a unicode character as a UTF-8 character.
+ * The length of the encoding is returned. If the string was not
+ * long enough to encode the character 0 is returned. */
+int output_utf8_char (unsigned short value,
+		      unsigned char *here,
+		      unsigned char *end) {
+  int len = (int)(end - here + 1); /* end is the last character */
+  if (value < 0x80) {
+    /* will be encoded in one byte */
+    if (len >= 1) {
+      *here = (unsigned char)value;
+      return 1;
+    }
+
+  } else if (value < 0x800) {
+    /* will be encoded in two bytes */
+    if (len >= 2) {
+      *here++ = 0xc0 | (unsigned char)((value >> 6) & 0x1f);
+      *here = 0x80 | (unsigned char)(value & 0x3f);
+
+      return 2;
+    }
+
+  } else {
+    /* will be encoded in three bytes */
+    if (len >= 3) {
+      *here++ = 0xe0 | (unsigned char)((value >> 12) & 0xf);
+      *here++ = 0x80 | (unsigned char)((value >> 6) & 0x3f);
+      *here = 0x80 | (unsigned char)(value & 0x3f);
+      return 3;
+    }
+  }
+
+  return 0;
+}
+
+
+static int lookup_decompose_table (unsigned short value) {
+  int first = 0;
+  int last = NUM_DECOMPOSE_INFO;
+  int here;
+
+  while (first < last) {
+    here = (last-first)/2 + first;
+    if (value < decompose_info[here].ch) {
+      last = here;
+    } else if (value > decompose_info[here].ch) {
+      first = here+1;
+    } else {
+      return here;
+    }
+  }
+
+  return -1;
+}
+
+/* decompose_str will decompose a unicode string into its canonical
+ * equivalents. NULL is returned if the input array was not 
+ * large enough to contain the fully decomposed string (the array
+ * will be in a correct, but partially decomposed state). The input 
+ * must be null-terminated. */
+unsigned short *decompose_str (unsigned short *input,
+			       int max_output_len) {
+  int curpos = 0;
+  int curlen = unicode_strlen (input);
+  int tablepos = 0;
+  int leninc;
+  int i;
+
+  while (input[curpos] != 0) {
+    tablepos = lookup_decompose_table (input[curpos]);
+    if (tablepos >= 0) {
+      /* found a decomposition */
+      leninc = unicode_strnlen (decompose_info[tablepos].str, 3)-1;
+      if (curlen+leninc < max_output_len) {
+	/* enough space for this decomposition */
+
+	if (leninc > 1) {
+	  /* we have to shift the array along */
+	  for (i=curlen-1; i>=curpos; i--) {
+	    input[i+leninc] = input[i];
+	  }
+	  input[curlen+leninc] = 0;
+	  curlen += leninc;
+	}
+
+	/* decompose the character */
+	for (i=0; i<=leninc; i++) {
+	  input[curpos+i] = decompose_info[tablepos].str[i];
+	}
+
+	/* note: curpos is not incremented because the decomposed */
+	/*       characters might need decomposing */
+
+      } else {
+	/* no space left in string */
+	return NULL;
+      }
+
+    } else {
+      /* the character cannot be decomposed */
+      curpos++;
+    }
+  }
+
+  return input;
+}
+
+
+
+/* unicode_cat_data is a combination of the letter, digit, and
+ * space information in a form that is quick to look up.
+ * The information about each byte is stored in two bits
+ *
+ * 00 - neither letter, digit or space
+ * 01 - letter
+ * 10 - space
+ * 11 - digit
+ *
+ * You can test for letter | space by looking at the right
+ * column
+ */
+unsigned long *unicode_cat_data;
+
+void create_unicat_data () {
+  int i=0;
+  int min_start=0;
+  int min_end=0;
+  register unsigned long min_value=0; /* filling the whole byte */
+  
+  const unirange *letter_here = letter_info;
+  const unirange *letter_end = letter_info+NUM_LETTER_INFO;
+  const unirange *digit_here = digit_info;
+  const unirange *digit_end = digit_info+NUM_DIGIT_INFO;
+  const unirange *space_here = space_info;
+  const unirange *space_end = space_info+NUM_SPACE_INFO;
+
+  if (unicode_cat_data != NULL) return;
+  unicode_cat_data = malloc (0x10000/4);
+  if (unicode_cat_data == NULL) return;
+  
+  while (i <= 0xffff) {
+    /* decide what to fill with next */
+    min_start = i;
+    min_end = 0xffff;
+    min_value = 0; /* 00 */
+    
+    while (letter_here < letter_end && letter_here->last < i) letter_here++;
+    if (letter_here < letter_end && letter_here->last <= min_end) {
+      min_start = letter_here->first;
+      min_end = letter_here->last;
+      min_value = 0x55555555; /* 01 */
+    }
+    
+    while (digit_here < digit_end && digit_here->last < i) digit_here++;
+    if (digit_here < digit_end && digit_here->last <= min_end) {
+      min_start = digit_here->first;
+      min_end = digit_here->last;
+      min_value = 0xffffffff; /* 11 */
+    }
+    
+    while (space_here < space_end && space_here->last < i) space_here++;
+    if (space_here < space_end && space_here->last <= min_end) {
+      min_start = space_here->first;
+      min_end = space_here->last;
+      min_value = 0xaaaaaaaa; /* 10 */
+    }
+
+    if (min_start < i) min_start = i;
+    else if (min_start > i) {
+      min_end = min_start-1;
+      min_start = i;
+      min_value = 0; /* 00 */
+    }
+
+    /* fill the entries from min_start to min_end with min_value */
+    while (i <= min_end) {
+      /* special version for common case */
+      if (i % 16 == 0) {
+	unicode_cat_data[i/16] = min_value; /* doesn't matter if too long */
+	i += 16;
+	if (i > min_end) {
+	  i = min_end+1;
+	  break;
+	}
+	
+      } else {
+	register unsigned long mask = 3 << ((i % 16) * 2);
+	unicode_cat_data[i/16] = (unicode_cat_data[i/16] & (~mask)) |
+				  (min_value & mask);
+	i++;
+      }
+    }
+  }
+}
+
+/* does a binary search on a range table */
+static int in_unirange (const unirange *info, int num_info,
+			unsigned short value) {
+  int first = 0;
+  int last = num_info;
+  int here;
+
+  while (first < last) {
+    here = (last-first)/2 + first;
+    if (value < info[here].first) {
+      last = here;
+    } else if (value > info[here].last) {
+      first = here+1;
+    } else {
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
+
+
+/* tests to see whether 'value' is a valid Unicode letter */
+int is_unicode_letter (unsigned short value) {
+  if (unicode_cat_data == NULL) create_unicat_data ();
+  if (unicode_cat_data == NULL) {
+    /* use old method */
+    return in_unirange(letter_info, NUM_LETTER_INFO, value);
+  }
+
+  return (((unicode_cat_data[value/16] >> ((value%16)*2)) & 0x3) == 0x1);
+}
+
+/* tests to see whether 'value' is a valid Unicode digit */
+int is_unicode_digit (unsigned short value) {
+  if (unicode_cat_data == NULL) create_unicat_data ();
+  if (unicode_cat_data == NULL) {
+    /* use old method */
+    return in_unirange(digit_info, NUM_DIGIT_INFO, value);
+  }
+
+  return (((unicode_cat_data[value/16] >> ((value%16)*2)) & 0x3) == 0x3);
+}
+
+/* tests to see whether 'value' is a valid Unicode letter or 
+ * digit */
+int is_unicode_letdig (unsigned short value) {
+  if (unicode_cat_data == NULL) create_unicat_data ();
+  if (unicode_cat_data == NULL) {
+    /* use old method */
+    return (in_unirange(letter_info, NUM_LETTER_INFO, value) ||
+	    in_unirange(digit_info, NUM_DIGIT_INFO, value));
+    
+  }
+
+  return ((unicode_cat_data[value/16] >> ((value%16)*2)) & 0x1);
+}
+
+/* tests to see whether 'value' is a valid space
+ * The test includes both "C" spaces and "Unicode" spaces, i.e. 
+ * form-feed, newline, carriage return, horizontal tab,
+ * vertical tab, and the Zs, Zl, and Zp Unicode categorizations */
+int is_unicode_space (unsigned short value) {
+  if (value < 0x80) return isspace (value);
+  if (unicode_cat_data == NULL) create_unicat_data ();
+  if (unicode_cat_data == NULL) {
+    /* use old method */
+    return in_unirange(space_info, NUM_SPACE_INFO, value);
+  }
+
+  return (((unicode_cat_data[value/16] >> ((value%16)*2)) & 0x3) == 0x2);
+}
+
+/* returns the length of the unicode string */
+int unicode_strlen (const unsigned short *str) {
+  int len = 0;
+
+  /* keep going till you find the null-terminator */
+  while (*str != 0) {
+    len++;
+    str++;
+  }
+
+  return len;
+}
+
+/* returns the length of the unicode string, up to a maximum */
+int unicode_strnlen (const unsigned short *str, int max_length) {
+  int len = 0;
+
+  /* keep going till you find the null-terminator */
+  while (*str != 0 && len < max_length ) {
+    len++;
+    str++;
+  }
+
+  return len;
+}
+
+
+/* Does a binary search on a relate table, returns -1 if it is not
+ * found. */
+static int search_unirelate (const unirelate *info, int num_info,
+			     unsigned short value) {
+  int first = 0;
+  int last = num_info;
+  int here;
+
+  while (first < last) {
+    here = (last-first)/2 + first;
+    if (value < info[here].ch1) {
+      last = here;
+    } else if (value > info[here].ch1) {
+      first = here+1;
+    } else {
+      return here;
+    }
+  }
+
+  return -1;
+}
+
+
+/* returns the upper-case equivalent of value */
+unsigned short unicode_toupper (unsigned short value) {
+  int related = search_unirelate (toupper_info, NUM_TOUPPER_INFO, value);
+  if (related >= 0) {
+    value = toupper_info[related].ch2;
+  }
+  return value;
+}
+
+/* returns the lower-case equivalent of value */
+unsigned short unicode_tolower (unsigned short value) {
+  int related = search_unirelate (tolower_info, NUM_TOLOWER_INFO, value);
+  if (related >= 0) {
+    value = tolower_info[related].ch2;
+  }
+  return value;
+}
+
+/* returns the simplified Chinese character equivalent of 
+ * another Chinese character */
+unsigned short unicode_tosimplified (unsigned short value) {
+  int related = search_unirelate (tosimplified_info, NUM_TOSIMPLIFIED_INFO, value);
+  if (related >= 0) {
+    value = tosimplified_info[related].ch2;
+  }
+  return value;
+}
+
+
+/* converts a utf-8 word (string with length stored in the first byte
+ * to a Unicode array. To handle all situations the output buffer should
+ * be 256 unsigned shorts long. The output will also have the length as
+ * the first entry. */
+unsigned short *utf8_word_to_unicode (const unsigned char *input,
+				      unsigned short *output,
+				      int max_output_length) {
+  int inlen = *input;
+  const unsigned char *inhere = input+1;
+  const unsigned char *inend = &inhere[inlen-1];
+  unsigned short c;
+  int clen;
+  
+  int outlen = 0;
+  unsigned short *outhere = output+1;
+  
+  while (inhere <= inend && inlen < max_output_length-1) {
+    /* decode the character */
+    clen = parse_utf8_char (inhere, inend, &c);
+    inhere += clen;
+
+    if (clen > 0) {
+      /* store the character */
+      *outhere = c;
+      outhere++;
+      outlen++;
+    }
+  }
+
+  output[0] = outlen;
+  return output;
+}
+
+
+/* converts a unicode word buffer (with the length stored in the
+ * entry) to a utf8 encoded word output (with the length stored in
+ * the first byte. Only 255 bytes (not characters) can be stored 
+ * in the output. */
+unsigned char *unicode_to_utf8_word (const unsigned short *input,
+				     unsigned char *output,
+				     int max_output_length) {
+  int inlen = *input;
+  const unsigned short *word = input + 1;
+  int in_i = 0;
+  int clen;
+
+  int outlen = 0;
+  unsigned char *outhere = output+1;
+  unsigned char *outend = output+max_output_length;
+
+  while (in_i < inlen) {
+    if ((clen=output_utf8_char(word[in_i], outhere, outend)) == 0) {
+      /* ran out of space to encode the character */
+      break;
+    }
+
+    outhere += clen;
+    outlen += clen;
+    in_i++;
+  }
+
+  output[0] = outlen;
+
+  return output;
+}
+
Index: /indexers/branches/3.03a/mg/lib/unitool.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/unitool.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/unitool.h	(revision 14757)
@@ -0,0 +1,88 @@
+#ifndef UNITOOL_H
+#define UNITOOL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* This module is based on Unicode 2.1 */
+
+
+/* parse_utf8_char parses the next utf-8 character, placing its
+ * unicode equivalent in *value. The length of the utf-8 character
+ * is returned. end is the address of the last character. */
+int parse_utf8_char (const unsigned char *here,
+		     const unsigned char *end,
+		     unsigned short *value);
+
+/* output_utf8_char encodes a unicode character as a UTF-8 character.
+ * The length of the encoding is returned. If the string was not
+ * long enough to encode the character 0 is returned. end is the
+ * address of the last character */
+int output_utf8_char (unsigned short value,
+		      unsigned char *here,
+		      unsigned char *end);
+
+/* decompose_str will decompose a unicode string into its canonical
+ * equivalents. NULL is returned if the input array was not 
+ * large enough to contain the fully decomposed string (the array
+ * will be in a correct, but partially decomposed state). The input 
+ * must be null-terminated. */
+unsigned short *decompose_str (unsigned short *input,
+			       int max_output_len);
+
+/* tests to see whether 'value' is a valid Unicode letter */
+int is_unicode_letter (unsigned short value);
+
+/* tests to see whether 'value' is a valid Unicode digit */
+int is_unicode_digit (unsigned short value);
+
+/* tests to see whether 'value' is a valid Unicode letter or 
+ * digit */
+int is_unicode_letdig (unsigned short value);
+
+/* tests to see whether 'value' is a valid space
+ * The test includes both "C" spaces and "Unicode" spaces, i.e. 
+ * form-feed, newline, carriage return, horizontal tab,
+ * vertical tab, and the Zs, Zl, and Zp Unicode categorizations */
+int is_unicode_space (unsigned short value);
+
+/* returns the length of the unicode string */
+int unicode_strlen (const unsigned short *str);
+
+/* returns the length of the unicode string, up to a maximum */
+int unicode_strnlen (const unsigned short *str, int max_length);
+
+/* returns the upper-case equivalent of value */
+unsigned short unicode_toupper (unsigned short value);
+
+/* returns the lower-case equivalent of value */
+unsigned short unicode_tolower (unsigned short value);
+
+/* returns the simplified Chinese character equivalent of 
+ * another Chinese character */
+unsigned short unicode_tosimplified (unsigned short value);
+
+
+/* converts a utf-8 word (string with length stored in the first byte
+ * to a Unicode array. To handle all situations the output buffer should
+ * be 256 unsigned shorts long. The output will also have the length as
+ * the first entry. */
+unsigned short *utf8_word_to_unicode (const unsigned char *input,
+				      unsigned short *output,
+				      int max_output_length);
+
+/* converts a unicode word buffer (with the length stored in the
+ * entry) to a utf8 encoded word output (with the length stored in
+ * the first byte. Only 255 bytes (not characters) can be stored 
+ * in the output. */
+unsigned char *unicode_to_utf8_word (const unsigned short *input,
+				     unsigned char *output,
+				     int max_output_length);
+
+#ifdef __cplusplus
+	   }
+#endif
+
+#endif
Index: /indexers/branches/3.03a/mg/lib/win32in.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/win32in.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/win32in.c	(revision 14757)
@@ -0,0 +1,86 @@
+#include "longlong.h"
+
+/* This module provides an equivalent of <netinet/in.h> on  */
+/* unix systems. */
+
+unsigned long htonl(unsigned long x) {
+#if defined (LITTLE_ENDIAN) || defined (_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN)
+	x = ((x >> 24) & 0x000000FF) | ((x >> 8) & 0x0000FF00) |
+		((x << 8) & 0x00FF0000) | ((x << 24) & 0xFF000000);
+#endif
+
+	return x;
+}
+
+mg_ullong ntohll(mg_ullong x)
+{
+#if defined (LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN)
+	x = 
+	  ((x >> 56) & 0x00000000000000FF) | ((x >> 40) & 0x000000000000FF00) |
+	  ((x >> 24) & 0x0000000000FF0000) | ((x >> 8)  & 0x00000000FF000000) |
+	  ((x << 8)  & 0x000000FF00000000) | ((x << 24) & 0x0000FF0000000000) |
+		((x << 40) & 0x00FF000000000000) | ((x << 56) & 0xFF00000000000000);
+#endif
+  return x;
+}
+
+unsigned long ntohl(unsigned long x) {
+#if defined (LITTLE_ENDIAN) || defined (_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN)
+	x = ((x >> 24) & 0x000000FF) | ((x >> 8) & 0x0000FF00) |
+		((x << 8) & 0x00FF0000) | ((x << 24) & 0xFF000000);
+#endif
+	return x;
+}
+
+unsigned short htons(unsigned short x) {
+#if defined (LITTLE_ENDIAN) || defined (_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN)
+	x = ((x >> 8) & 0x00FF) | ((x << 8) & 0xFF00);
+#endif
+	return x;
+}
+
+unsigned short ntohs(unsigned short x) {
+#if defined (LITTLE_ENDIAN) || defined (_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN)
+	x = ((x >> 8) & 0x00FF) | ((x << 8) & 0xFF00);
+#endif
+	return x;
+}
+
+/* just to test stuff
+#include <stdio.h>
+
+main () {
+	long x;
+	short sx;
+
+	x = 0x000000FF;
+	printf ("before %i, ",(int)x);
+	x = htonl (x);
+	printf ("after %i\n",(int)x);
+
+	x = 0x0000FF00;
+	printf ("before %i, ",(int)x);
+	x = htonl (x);
+	printf ("after %i\n",(int)x);
+
+	x = 0x00FF0000;
+	printf ("before %i, ",(int)x);
+	x = htonl (x);
+	printf ("after %i\n",(int)x);
+
+	x = 0xFF000000;
+	printf ("before %i, ",(int)x);
+	x = htonl (x);
+	printf ("after %i\n\n",(int)x);
+
+	sx = 0x00FF;
+	printf ("before %i, ",(int)sx);
+	sx = htons (sx);
+	printf ("after %i\n",(int)sx);
+
+	sx = 0xFF00;
+	printf ("before %i, ",(int)sx);
+	sx = htons (sx);
+	printf ("after %i\n",(int)sx);
+}
+*/
Index: /indexers/branches/3.03a/mg/lib/win32in.h
===================================================================
--- /indexers/branches/3.03a/mg/lib/win32in.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/win32in.h	(revision 14757)
@@ -0,0 +1,10 @@
+/* This module provides an equivalent of <netinet/in.h> on  */
+/* unix systems. */
+
+#include "longlong.h"
+
+unsigned long htonl(unsigned long x);
+unsigned long ntohl(unsigned long x);
+mg_ullong ntohll(mg_ullong x);
+unsigned short htons(unsigned short x);
+unsigned short ntohs(unsigned short x);
Index: /indexers/branches/3.03a/mg/lib/xmalloc.c
===================================================================
--- /indexers/branches/3.03a/mg/lib/xmalloc.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/lib/xmalloc.c	(revision 14757)
@@ -0,0 +1,111 @@
+/* xmalloc.c -- malloc with out of memory checking
+   Copyright (C) 1990, 91, 92, 93, 94 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 program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+#  include <win32cfg.h>
+# else
+#  include <sysfuncs.h>
+# endif
+#endif
+
+#if __STDC__
+#define VOID void
+#else
+#define VOID char
+#endif
+
+#include <sys/types.h>
+
+#if STDC_HEADERS
+#include <stdlib.h>
+#else
+VOID *malloc ();
+VOID *realloc ();
+void free ();
+#endif
+
+/* This is for other GNU distributions with internationalized messages.
+   The GNU C Library itself does not yet support such messages.  */
+#if HAVE_LIBINTL_H
+# include <libintl.h>
+#else
+# define gettext(msgid) (msgid)
+#endif
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+
+/* Exit value when the requested amount of memory is not available.
+   The caller may set it to some other value.  */
+int xmalloc_exit_failure = EXIT_FAILURE;
+
+#if defined(__WIN32__)
+void error (int, int, const char *, ...);
+#else
+#if __STDC__ && (HAVE_VPRINTF || HAVE_DOPRNT)
+void error (int, int, const char *, ...);
+#else
+void error (int, int, char *, char *, char *, char *, char *, char *, char *, char *, char *);
+#endif
+#endif;
+
+static VOID *
+fixup_null_alloc (n)
+     size_t n;
+{
+  VOID *p;
+
+  p = 0;
+  if (n == 0)
+    p = malloc ((size_t) 1);
+  if (p == 0)
+    error (xmalloc_exit_failure, 0, gettext ("Memory exhausted"));
+  return p;
+}
+
+/* Allocate N bytes of memory dynamically, with error checking.  */
+
+VOID *
+xmalloc (n)
+     size_t n;
+{
+  VOID *p;
+
+  p = malloc (n);
+  if (p == 0)
+    p = fixup_null_alloc (n);
+  return p;
+}
+
+/* Change the size of an allocated block of memory P to N bytes,
+   with error checking.
+   If P is NULL, run xmalloc.  */
+
+VOID *
+xrealloc (p, n)
+     VOID *p;
+     size_t n;
+{
+  if (p == 0)
+    return xmalloc (n);
+  p = realloc (p, n);
+  if (p == 0)
+    p = fixup_null_alloc (n);
+  return p;
+}
Index: /indexers/branches/3.03a/mg/man/man1/mg_compression_dict.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_compression_dict.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_compression_dict.1	(revision 14757)
@@ -0,0 +1,219 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_compression_dict 1 \*(Dt CITRI
+.SH NAME
+mg_compression_dict \- build a compression dictionary.
+.SH SYNOPSIS
+.B mg_compression_dict
+[
+.B \-h
+]
+[
+.BR \-C " |"
+.BR \-P " |"
+.B  \-S
+]
+.if n .ti +9n
+[
+.BR \-0 " |"
+.BR \-1 " |"
+.BR \-2 " |"
+.B  \-3
+]
+[
+.BR \-H " |"
+.BR \-B " |"
+.BR \-D " |"
+.BR \-Y " |"
+.B  \-M
+]
+.if n .ti +9n
+.if t .ti +.5i
+[
+.BI \-l " lookback"
+]
+[
+.BI \-k " mem"
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_compression_dict
+builds a compression dictionary based on the statistics gathered
+during the first pass over the text.  The options to the program are
+mainly concerned with limiting the amount of memory the dictionary
+will use and with how the text compressor will cope with any novel
+words found during the compression phase.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-C
+Build a complete dictionary from the statistics file.  If during the
+text compression phase a novel word is found, then the compressor will
+produce an error message and stop.
+.TP
+.B \-P
+Build a partial dictionary from the statistics file.  This dictionary
+assumes that the statistics file are based on the entire text.  The
+statistics of words not includes in the dictionary are used to
+calculate the escape probability.  If novel words are being coded
+character by character, then there may not be a Huffman code for every
+possible character.  This means that the compressor may fail if a novel
+word contains a novel character.
+.TP
+.B \-S
+Build a seed dictionary from the statistics file.  This dictionary
+assumes that the statistics file is based on only a portion of the
+text to be compressed.  The probability of a novel word is based on the
+number of words that have only occurred once.  If novel words are being
+coded character by character, then the Huffman codes for characters are
+based on the frequency of characters in the dictionary.
+.TP
+.B \-0
+All words from the statistics file are included in the built
+dictionary.
+.TP
+.B \-1
+Words are included in the dictionary until the dictionary reaches the
+desired size.  Words are selected for the dictionary based on the order
+they occurred in the source text.
+.TP
+.B \-2
+Words are included in the dictionary until the dictionary reaches the
+desired size.  The most frequent words are included in the dictionary
+first; where there is a tie for frequency, the shortest word is
+included first.
+.TP
+.B \-3
+Words are included in the dictionary until the dictionary reaches the
+desired size.  The most frequent words are included in the dictionary
+first; where there is a tie for frequency, the shortest word is
+included first.  Words are the shuffled back and forth between the
+`keep' and `discard' lists to find the `optimal' set of words that
+should be in the dictionary.
+.TP
+.B \-H
+This specifies that novel words will be coded character by character
+using Huffman codes.
+.TP
+.B \-B
+This specifies that an auxiliary dictionary will be built by the
+compressor.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using binary codes.  The binary code represents their occurrence
+position in the auxiliary dictionary.
+.TP
+.B \-D
+This specifies that an auxiliary dictionary will be built by the
+compressor.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using delta codes.  The delta code represents their occurrence position
+in the auxiliary dictionary.
+.TP
+.B \-Y
+This specifies that an auxiliary dictionary will be built by the
+compressor.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using a combination of gamma and binary codes.  The code represents
+their occurrence position in the auxiliary dictionary.  This generally
+produces better compression than
+.B \-B
+or
+.BR \-D .
+.TP
+.B \-M
+This specifies that an auxiliary dictionary will be built by the
+compressor.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using a combination of gamma and binary codes.  The code represents
+their occurrence position in the auxiliary dictionary.  This method is
+adaptive within documents, and generally produces better compression
+than
+.BR \-B ,
+.B \-D
+or
+.BR \-Y .
+.TP
+.BI \-l " lookback"
+The generated dictionary is designed to be front coded when it is
+loaded into memory.  Under normal circumstances, a front-coded
+dictionary would require scanning from the beginning in order to find
+any particular word.  However, every
+.I lookback
+words in the dictionary, the whole word is stored and a pointer to that
+word maintained.  E.g., if
+.I lookback
+is 4, then every fourth word is stored in its entirety.
+.TP
+.BI \-k " mem"
+This limits the amount of memory to use for the generated
+dictionary.  Words are selected for the dictionary based of the text
+statistics, and whether
+.BR \-0 , " \-1" , " \-2"
+or
+.B \-3
+is specified.  The memory is calculated assuming a lookback of 0,
+irrespective of what actual lookback is specified.  This means that if
+a non-zero lookback is given, the dictionary will actually occupy
+less space than specified by
+.BR \-k .
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.text.stats
+Statistics about the source text.
+.TP
+.B *.text.dict
+Compression dictionary for the source text.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_decompress_text.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_decompress_text.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_decompress_text.1	(revision 14757)
@@ -0,0 +1,78 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_decompress_text 1 \*(Dt CITRI
+.SH NAME
+mg_decompress_text \- decompresses the compressed text of a collection
+.SH SYNOPSIS
+.B mg_decompress_text
+[
+.B \-h
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_decompress_text
+decompresses the compressed text of a collection, inserts paragraph and
+document markers, writing the output to
+.IR stdout ".  "
+This program was created
+to be used as a type of
+.BR mg_get (1).
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 25
+.B *.text
+Compressed documents.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.text.dict.aux
+Auxiliary compression dictionary.
+.TP
+.B *.text.dict.fast
+Fast loading compression dictionary.
+.TP
+.B *.invf.paragraph
+Paragraph counts for documents.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_passes (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_fast_comp_dict.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_fast_comp_dict.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_fast_comp_dict.1	(revision 14757)
@@ -0,0 +1,86 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_fast_comp_dict 1 \*(Dt CITRI
+.SH NAME
+mg_fast_comp_dict \- build a fast loading compression dictionary
+.SH SYNOPSIS
+.B mg_fast_comp_dict
+[
+.B \-h
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_fast_comp_dict
+builds a fast-loading compression dictionary from the standard
+compression dictionary.  The new dictionary has the property that
+.BR mgquery (1)
+can load it in very quickly, making the startup time for
+.BR mgquery (1)
+much shorter.  The new dictionary is larger on disk than the original,
+but they are no different when it comes to memory usage.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.text.dict
+Compression dictionary.
+.TP
+.B *.text.dict.fast
+Fast loading compression dictionary.
+.TP
+.B *.text.dict.aux
+Auxiliary compression dictionary.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_get.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_get.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_get.1	(revision 14757)
@@ -0,0 +1,154 @@
+.TH mg_get 1 "31 January 1994"
+.SH NAME
+mg_get \- output source texts for processing
+.SH SYNOPSIS
+ 
+.B mg_get
+.I collection-name
+.RB [ \-init | \-i | \-text\fP|\fB\-t\fP|\fB\-cleanup\fP|\fB\-c\fP]
+.SH DESCRIPTION
+.LP
+This program is the default one used by mgbuild to generate the source text for the MG system. Any program may be used to generate the source text for mgbuild as long as it confirms to the interface specified here. 
+.SH OPTIONS
+.LP
+The
+.I collection\-name
+must appear before any other option. Only the first option has any significance. If no option is specified
+.B \-text
+is assumed.
+.RS
+.TP
+.BR \-init " and " \-i
+The program is called once with this flag at the start of building a collection.
+.TP
+.BR \-text " and " \-t
+The program is called with this flag multiple times during the building of a collection. The program outputs (on stdout) the text of the collection. \*(lq\fBDocuments\fP\*(rq within the collection are separated with by ctrl-B's (ASCII code 2). \*(lq\fBParagraphs\fP\*(rq within the collection are separated with ctrl-C's (ASCII code 3). A collection need not contain paragraphs unless a level 3 inverted file is being generated (see 
+.B mgbuild 
+and 
+.BR mg_passes ). 
+.TP
+.BR \-cleanup " and " \-c
+The program is called once with this flag at the completion of building a collection.
+.SH ENVIRONMENT
+.TP
+.SB MGDATA
+If this environment variable exists then its value is used a the default 
+directory where the mg collection files are. If this variable does not exist
+then the directory \*(lq\fB.\fP\*(rq is used by default. The command line 
+option 
+.BI \-d " directory"
+overrides the directory in 
+.BR MGDATA .
+.TP
+.SB MG_GETRC
+This environment variable specifies where the file containing the users 
+mg source configurations is. If not set, mg_get uses a default of 
+.B \*\~/.mg_getrc.
+
+This file contains TAB delimited lines of the form
+.RS 
+.RS 
+.I CollectionName
+.I CollectionType
+.I files or directory
+.RE
+
+.I CollectionName
+is the name of the collection supplied to mg_get.
+
+.I CollectionType
+specifies how mg_get should process the
+named files and directories and are descibed below.
+
+.I files or directory
+is either a list of files separted by blanks or a single directory.
+Some of the
+.I CollectionTypes
+deal with files and others with just a single directory.
+Any files used ending with .gz or .Z are decompressed with gzip before
+processing. References to '~' expands to the users HOME directory.
+
+.I CollectionType
+is one of
+.RS
+.TP
+.BR PARA
+For text based documents. The list of files specified are treated as
+a series of paragraphs separated by blank lines. Each paragraph becomes
+a seperate document on the indexed collection.
+.TP
+.BR MAIL
+for mail files. The list of files specified are treated as UNIX mail
+files separated by lines starting with 'From'. Each mail message becomes
+a seperate document on the indexed collection. As a extra feature any
+embedded tarmail encoded contents (enclosed by a 'xbtoa Begin' and 'xbtoa End'
+pair are removed.
+.TP
+.BR DIR
+(and DIR2)
+For a single directory of files. Each file in the directory (and in any of
+it's subdirectories) are treated as a single document. With
+.I DIR
+the pathname of the file is prefixed to the contents of each file as an
+extra line while this is not done for
+.I DIR2
+collections.
+.TP
+.BR BIB
+for biblography files. The list of files specified are treated as
+a series of biblography files (eg BIBTEX or TROFF) separated by lines
+starting with '@'. Each reference  becomes a seperate document on the indexed
+collection.
+.TP
+.BR TXTIMG
+for integrated collections of text and images. The single directory should
+contain files that have the same prefix if they are related. For example,
+monaLisa.pgm might be a gray-level image, and monaLisa.txt would be a textual
+file describing the image. The suffixes recognised are:
+.BR   .txt
+for  ascii text
+.BR  .ptm
+for  scanned text stored as a bilevel image
+.BR  .pbm
+for a black and white image (typically a line drawing)
+.BR  .pgm
+for a gray-scale image
+.BR In addition, if no corresponding ascii text file is found for
+a .pbm or .pgm file, then one is created with suffix .tmp.txt,
+and it stores the name of the image file (in principle it could
+store the OCR of a .txt.pbm file). At present the .tmp.txt files
+are deleted by the '-cleanup' option.
+
+.SH "EXAMPLE"
+
+An example ~/.mg_getrc file might look like:
+   alice   PARA    /users/alice13a.txt.Z
+   mail95  MAIL    ~/MAIL/1995/*
+   doc     DIR     ~/documents
+   bibs    BIB     ~/etc/REFS/*.bib ~/etc/REFS/CC/*.bib
+   letters DIR     ~/LETTERS
+   davinci TXTIMG  ~/images/davinci
+
+.SH "SEE ALSO"
+.LP
+.BR mg_compression_dict (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_make_fast_dict (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1)
+
Index: /indexers/branches/3.03a/mg/man/man1/mg_get_merge.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_get_merge.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_get_merge.1	(revision 14757)
@@ -0,0 +1,86 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_get_merge 1 \*(Dt CITRI
+.SH NAME
+mg_get_merge \- output source texts for processing
+.SH SYNOPSIS
+.B mg_get_merge
+.I collection-name
+.if n .ti +9n
+[
+.BR \-init " |"
+.BR \-i " |"
+.BR \-text " |"
+.BR \-t " |"
+.BR \-cleanup " |"
+.B  \-c
+]
+.SH DESCRIPTION
+This program is the default one used by
+.BR mgmerge (1)
+to generate the source text for new documents to appended to
+an
+.BR mg (1)
+system database.
+Its function is exactly the same as
+.BR mg_get (1)
+except that it generates the 
+.I new 
+documents to be added to an
+.BR mg (1)
+system database that has already been built using
+.BR mgbuild(1).
+Any program may be used to generate the source
+text for
+.BR mgmerge (1),
+as long as it confirms to the interface specified
+here.
+.SH OPTIONS
+The
+.I collection-name
+must appear before any other option.  Only the first option has any
+significance.  If no option is specified,
+.B \-text
+is assumed.
+.TP "\w'\fB\-cleanup\fP and \fB\-c\fP'u+2n"
+.BR \-init " and " \-i
+The program is called once with this flag at the start of merging a
+collection.
+.TP
+.BR \-text " and " \-t
+The program is called with this flag multiple times during the
+merging of a collection.  The program outputs (on
+.IR stdout )
+the text of the collection.
+.I Documents
+within the collection are separated by ctrl-B's (ASCII code 2).
+.TP
+.BR \-cleanup " and " \-c
+The program is called once with this flag at the completion of
+merging a collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_get (1),
+.BR mgbuild (1),
+.BR mgmerge (1),
+.BR mg_text_merge (1),
+.BR mg_invf_merge (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_hilite_words.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_hilite_words.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_hilite_words.1	(revision 14757)
@@ -0,0 +1,95 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_hilite_words 1 \*(Dt CITRI
+.SH NAME
+mg_hilite_words \- display text and highlight particular words which it contains
+.SH SYNOPSIS
+.B mg_hilite_words
+.if n .ti +9n
+[
+.B --stem_method [0-3]
+]
+.if n .ti +9n
+[
+.B --stemmer [english|lovin|french|simplefrench]
+]
+.if n .ti +9n
+[
+.B --style [bold|underline|italic|emphasis|strong]
+]
+.if n .ti +9n
+[
+.B --pager [less|more|html|???]
+]
+.if n .ti +9n
+.I list-of-words-to-highlight
+
+.SH DESCRIPTION
+.B mg_hilite_words
+reads text from stdin and outputs it into a pager such as
+less. It's command arguments include a list of stemmed words
+which if extracted from the text will be highlighted on the output
+using a highlighting style.
+
+It has been extended to output the highlighted text using html
+straight to stdout.
+
+.SH OPTIONS
+Options may appear in any order, but the
+.IR list-of-words-to-highlight ,
+must be last.
+.TP
+.B --stem_method [0-3]
+This option allows one to set the stemming method for the extraction of
+the words from the incoming text.
+This should match the way the inverted file index was created.
+The default is 3, which is fold and stem.
+.TP
+.B --stemmer [english|lovin|french|simplefrench]
+This option allows you to select the stemmer to use.  The
+default is the English stemmer.
+.TP
+.B --style [bold|underline|italic|emphasis|strong]
+This option sets the highlighting style.
+.IR Bold 
+and 
+.IR underline
+are utilised by the pager or for html output.
+.IR Italic,
+.IR emphasis,
+and
+.IR strong
+can only be used for html output.
+.TP
+.B --pager [less|more|html|???]
+One can use the standard 
+.IR less
+or
+.IR more
+pages for displaying the highlighted text.
+Or one can generate highlighted html using the paging setting of
+.IR html.
+One can also specify a custom pager of their own choosing (i.e. ???).
+.TP
+.B list-of-words-to-highlight
+Each word is taken as a command line argument.
+Each word should already be stemmed and folded according to
+the stem option.
+.SH USAGE
+This program was written primarily to be called by 
+.IR mgquery(1)
+.
+When the user selects the mode of "hilite" then this program
+is called for displaying the query-result documents instead of
+just the pager.
+.SH "SEE ALSO"
+.na
+.BR mgquery (1).
+
+
Index: /indexers/branches/3.03a/mg/man/man1/mg_invf_dict.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_invf_dict.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_invf_dict.1	(revision 14757)
@@ -0,0 +1,104 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_invf_dict 1 \*(Dt CITRI
+.SH NAME
+mg_invf_dict \- build an `on-disk' stemmed dictionary
+.SH SYNOPSIS
+.B mg_invf_dict
+[
+.B \-h
+]
+[
+.B \-F
+]
+[
+.BI \-b " num"
+]
+[
+.BI \-d " directory"
+]
+.if n .ti +9n
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_invf_dict
+builds an `on-disk' stemmed dictionary from the
+compressed stemmed dictionary that the
+.BR mgquery (1)
+program can access.  Each entry in the dictionary contains the disk
+pointer to the associated inverted file entry, and various other pieces
+of information about the stemmed word.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-b " num"
+The dictionary is stored in blocks on disk; this option is used to set
+the block size.  The default is 4-KB blocks.
+.TP
+.B \-F
+This option causes the disk blocks to be aligned on the appropriate
+boundaries.  For example, if 4-KB blocks are used, they will be aligned
+in the file on 4-KB boundaries.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.dict.build
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict
+The `on-disk' stemmed dictionary.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_invf_dump.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_invf_dump.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_invf_dump.1	(revision 14757)
@@ -0,0 +1,142 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_invf_dump 1 \*(Dt CITRI
+.SH NAME
+mg_invf_dump \- Dump out an inverted file in ASCII
+.SH SYNOPSIS
+.B mg_invf_dump
+[
+.B \-h
+]
+[
+.B \-b
+]
+[
+.B \-w
+]
+[
+.B \-t
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+This program dumps out an inverted file produced by the
+.BR mg (1)
+system as ASCII numbers.  This program could be used in conjunction
+with
+.BR mgdictlist (1)
+to write simple shell programs that work with the inverted files.  The
+output from the program looks something like this:
+.LP
+.RS
+.ft 3
+.nf
+6 337
+1
+ 1 1
+1
+ 5 1
+1
+ 2 1
+1
+ 1 1
+4
+ 1 3
+ 2 7
+ 3 2
+ 5 2
+1
+ 1 1
+ . . .
+.fi
+.ft
+.RE
+The first number (6) is the number of documents in the collection.  It
+is followed by the number of different terms in the collection.  For
+each term, the number of different documents it occurs in follows. The
+document numbers that the term occurs in are listed next.  If
+.B \-w
+is specified, then the number of times the term occurred in the
+document is printed alongside the document number.
+If
+.B \-t
+is specified, the term itself is also displayed in quotes.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-b
+This option will cause the output from the program to be in fixed-size
+binary numbers, rather than in ASCII.
+.TP
+.B \-w
+If the inverted file is a level-2 or level-3 inverted file, this causes
+the word counts per document to be output.
+.TP
+.B \-t
+This option causes each term to be displayed along with the number of
+documents it appears in. The term is printed in quotes,
+as in "the".
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf.dict
+The compressed stemmed dictionary.
+.TP
+.B *.invf.ORG
+The original inverted file saved by
+.BR mg_invf_rebuild .
+.TP
+.B *.invf
+The inverted file.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_invf_merge.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_invf_merge.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_invf_merge.1	(revision 14757)
@@ -0,0 +1,112 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_invf_merge 1 \*(Dt CITRI
+.SH NAME
+mg_invf_merge \- Merge two inverted files and stemmed dictionaries
+.SH SYNOPSIS
+.B mg_invf_merge
+[
+.B \-h
+]
+[
+.B \-s
+]
+[
+.B \-w
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+This program takes two
+.BR mg (1)
+database compressed text files and appends the second to
+the first.
+It is part of the
+.BR mgmerge (1)
+addition to the
+.BR mg (1)
+package.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-s
+This option will cause a slow merge to be performed on the inverted files,
+where each inverted file entry is decoded and recoded.
+The default is a fast merge. Accumulated fast merges slowly degrade
+compression performance on the resulting inverted file so
+a periodic slow merge is recommended.
+.TP
+.B \-w
+By default the database .weights file is updated with
+new weights for the new documents in
+.B mg_text_merge.
+The
+.B -w
+option turns this step off.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.old.invf.dict
+The old compressed stemmed dictionary.
+.TP
+.B *.new.invf.dict
+The new compressed stemmed dictionary.
+.TP
+.B *.invf.dict
+The resulting merged compressed stemmed dictionary.
+.TP
+.B *.old.invf.ORG
+The original inverted file saved by
+.BR mg_invf_rebuild .
+.TP
+.B *.old.invf
+The old inverted file.
+.TP
+.B *.new.invf
+The new inverted file.
+.TP
+.B *.invf
+The resulting merged inverted file.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mgmerge (1),
+.BR mg_get_merge (1),
+.BR mg_text_merge (1),
+.BR mg_invf_rebuild (1),
+.BR mg_invf_dict (1),
+.BR mg_weights_build (1),
+.BR mgquery (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_invf_rebuild.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_invf_rebuild.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_invf_rebuild.1	(revision 14757)
@@ -0,0 +1,156 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_invf_rebuild 1 \*(Dt CITRI
+.SH NAME
+mg_invf_rebuild \- Rebuild an mg inverted file with or without skips.
+.SH SYNOPSIS
+.B mg_invf_rebuild
+.RB [ \-h ]
+.if n .ti +9n
+[
+.BR \-0 " |"
+.B \-1
+[
+.BI \-k " num"
+] |
+.B \-2
+[
+.BI \-s " num"
+]
+[
+.BI \-m " num"
+]
+]
+.if n .ti +9n
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_invf_rebuild
+builds a new inverted file, with or without skipping, from an old
+inverted file.  This file uses
+.I *.invf.ORG
+and
+.I *.invf.idx.ORG
+as the
+source from which it builds
+.I *.invf
+and
+.IR *.invf.idx .
+If
+.I *.invf.ORG
+or
+.I *.invf.idx.ORG
+do not exist, the program renames
+.I *.invf
+or
+.I *.invf.idx
+to
+.I *.invf.ORG
+or
+.I *.invf.idx.ORG
+as appropriate.  The old inverted file may contain skipping.  This
+means that it is possible to delete the
+.I *.ORG
+files
+after the new inverted file is built.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-m\fP \fInum\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-0
+This generates a non-skipped inverted file.  This option is normally
+only needed if the
+.I *.ORG
+files have been deleted.
+.TP
+.B \-1
+This generates a skipped inverted file.  The
+.BI \-k " num"
+argument specifies the number of pointers hopped over with each skip.
+.TP
+.B \-2
+This option generates a skipped inverted file.  The skipped inverted
+file is built so that it is `optimal' for ranking using a specific
+number of accumulators.  Each term in the inverted file has a
+different skip length.  The arguments
+.BR \-s " and " \-m
+control the sizes of the skips.
+.TP
+.BI \-k " num"
+This specifies the number of pointers that should be hopped over with
+each skip.  This option is only valid if
+.B \-1
+is specified.
+.TP
+.BI \-m " num"
+This specifies the intended number of accumulators that will be used
+when ranking queries are done on the collection.
+.TP
+.BI \-s " num"
+This specifies the minimum size for skips.  If the calculation of the
+optimal skip size results in a number smaller than
+.IR num ,
+the skip size is set to
+.IR num .
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.ORG
+Original inverted file.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.TP
+.B *.invf.idx.ORG
+The original index into the inverted file.
+.TP
+.B *.invf.dict.build
+Compressed stemmed dictionary.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_passes.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_passes.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_passes.1	(revision 14757)
@@ -0,0 +1,441 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_passes 1 \*(Dt CITRI
+.SH NAME
+mg_passes \- builds mg databases
+.SH SYNOPSIS
+.B mg_passes
+[
+.B \-h
+]
+[
+.B \-G
+]
+[
+.B \-S
+]
+[
+.B \-D
+]
+[
+.B \-W
+]
+.if n .ti +9n
+[
+.BR \-1 " |"
+.BR \-2 " |"
+.B  \-3
+]
+[
+.BI \-C " compstatpoint"
+]
+.if n .ti +9n
+[
+.BI \-n " tracename"
+]
+.if t .ti +.5i
+[
+.BI \-b " bufsize"
+]
+[
+.BI \-m " memlimit"
+]
+.if n .ti +9n
+[
+.BI \-c " numchunks"
+]
+[
+.BI \-a " stemmer"
+]
+[
+.BI \-s " stemmethod"
+]
+[
+.BI \-t " tracepos"
+]
+.if n .ti +9n
+[
+.B \-T1
+]
+[
+.B \-T2
+]
+.if t .ti +.5i
+[
+.B \-I1
+]
+[
+.B \-I2
+]
+.if n .ti +9n
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+[
+.I filename(s)
+]
+.SH DESCRIPTION
+.B mg_passes
+is the program that does most of the work when building
+.BR mg (1)
+database systems.  The input documents can come from either
+.I stdin
+or from a list of files on the command line.  Individual documents
+must be separated with control-B characters.  In general,
+.B mg_passes
+must be run twice to build a database, first with the
+.B \-T1
+and
+.B \-I1
+options, and second with the
+.B \-T2
+and
+.B \-I2
+options.  Several other programs must be run in order to get an
+.BR mg (1)
+database that is ready for the
+.BR mgquery (1)
+program.  The
+.SB EXAMPLE
+section below gives an example of how to build a complete
+.BR mg (1)
+database.
+.SH OPTIONS
+Options may appear in any order, but the
+.IR filename(s) ,
+if specified, must be last.
+.TP "\w'\fB\-C\fP \fIcompstatpoint\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-G
+Treat SGML tags as non-words when building the inverted file.  An SGML
+tag is anything between angle brackets, i.e., `<' and `>'.
+.TP
+.B \-S
+This option causes a special pass to be executed.  It is up to a user
+to modify
+.I mg.special.c
+in the source code to do something with the documents it is given.
+.TP
+.B \-D
+If
+.B mg_passes
+fails, then print the document that caused the failure to the trace
+file if tracing is active, or to
+.I stderr
+if it is not.
+.TP
+.B \-W
+This option enables the generation of the weights file when
+.B \-I2
+is specified.  It causes
+.B \-I2
+to use a little more memory and CPU.
+.TP
+.B \-1
+Produce a level-1 inverted file.  This option is only useful when
+specified with
+.BR "\-I1 ".
+A level-1 inverted file makes it possible for
+.BR mgquery (1)
+to do Boolean queries.  Ranked queries can still be done,
+although the quality of the ranking is abysmal.
+.TP
+.B \-2
+Produce a level-2 inverted file.  This option is only useful when
+specified with
+.BR "\-I1 ".
+This is the default when neither
+.BR \-1 ", " "\-2 " "or " \-3
+is specified.
+A level-2 inverted file makes it possible for
+.BR mgquery (1)
+to do Boolean queries and cosine-ranked queries.
+.TP
+.B \-3
+Produce a level-3 inverted file.  This option is only useful when
+specified with
+.BR "\-I1 ".
+This has been implemented to enable paragraph-level inversion.
+Paragraphs are delimited by control-C characters in the source text.
+.TP
+.BI \-C " compstatpoint"
+This option causes statistics on the compression performance to be
+output to a file called
+.IR *.compression.stats .
+.I compstatpoint
+specifies the interval between outputting each line of statistics.  The
+units of
+.I compstatpoint
+are kilobytes of source text.  E.g., if
+.I compstatpoint
+is 10, then a line is output to the file every 10 KB of input
+source.  Each line of the file consists of 4 numbers The first number
+is the amount of input text, in bytes, processed so far.  The second
+number is the amount of input text, in bytes, processed since the
+last line was output to the file.  The third number is the number of
+output bytes generated since the last line was output to the file, and
+the fourth number is the compression achieved since the last line was
+output, i.e., the third number divided by the second number.
+.TP
+.BI \-n " tracename"
+This specifies the filename to use for the trace log, if tracing is
+enabled using the
+.B \-t
+option.  If
+.BI \-n " tracename"
+is not given and tracing is enabled, a default trace filename will be
+used.
+.TP
+.BI \-s " stemmethod"
+This specifies the method to use to \*(lqstem\*(rq the words in the
+inverted file dictionary.  This is a bit mask specifying the
+operations to do on words as they are parsed out of the text, where
+bit number 0 is the low-order (rightmost) bit.  Bit 0 does case
+folding, and bit 1 does simple stemming, so the value 3 for
+.I stemmethod
+does both case folding and stemming.
+.TP
+.BI \-a " stemmer"
+This specifies the stemmer to use when stemming words.  This
+is a description of the language the stemmer is intended for
+or a description of the stemmer.  Valid options include:
+english, lovin, french, and simplefrench.
+.TP
+.BI \-b " bufsize"
+Specify the size of the document buffer in kilobytes.  If any document
+is larger than
+.IR bufsize ,
+the program will abort with an error message.  This should probably be
+replaced with some system which automatically increases the buffer
+size as required.  The default size is 3072 KB (3 MB).
+.TP
+.BI \-m " memlimit"
+Maximum amount of memory to use for the pass-2 file inversion in
+megabytes.  This option is only useful when used in conjunction with
+the option
+.BR \-I1 .
+The larger this value, the faster the pass-2 inversion will proceed.
+The default value is 5 MB.
+.TP
+.BI \-c " numchunks"
+The maximum number of inversion chunks to write to disk.  Each chunk
+will be approximately as large as
+.IR memlimit .
+This option is only useful when used in conjunction with the option
+.BR \-I2 .
+The larger this value, the faster the pass-2 inversion will proceed.
+The default value is 5 MB.
+.TP
+.BI \-t " tracepos"
+This option activates tracing.  A line will be generated in the
+trace file for every
+.I tracepos
+input bytes processed.  The default name for the trace file can be
+overridden using the
+.BI \-n " tracename"
+option.
+.TP
+.B \-T1
+Generate the
+.I *.text.stats
+file.
+.TP
+.B \-T2
+Generate the
+.IR *.text ,
+.IR *.text.idx ,
+and possibly the
+.I *.text.dict.aux
+files.  Using this option requires that the
+.I *.text.dict
+file be present.
+.TP
+.B \-I1
+Generate the
+.IR *.invf.dict ,
+.IR *.invf.chunk ,
+and
+.I *.invf.chunk.trans
+files.
+.TP
+.B \-I2
+Generate the
+.I *.invf
+and
+.I *.invf.idx
+files.  Using this option requires
+that the
+.IR *.invf.dict.hash ,
+.IR *.invf.chunk ,
+and
+.I *.invf.chunk.trans
+files
+be present.  The
+.I *.invf.dict.hash
+file is generated by
+.BR mg_perf_hash_build (1)
+from the
+.I *.invf.dict.build
+file.  If the
+.B \-W
+option is specified, the
+.I *.weight
+file will also be generated.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection is to be
+written.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection that will be
+created.
+.TP
+.I filename(s)
+This specifies the source text. If this is not specified, then the
+program expects the source text from
+.IR stdin .
+.SH EXAMPLE
+What follows is a UNIX
+.BR csh (1)
+script as an example of how to build an
+.BR mg (1)
+document collection.
+.LP
+.nf
+.DT
+.ft B
+.I #! /bin/csh
+.I
+# The first argument on the command line specifies the
+.I
+#   source of the text
+set source = ($1)
+.PP
+.I
+# The second argument is the name of the collection
+set text = ($2)
+.PP
+.I
+# Create *.text.stats,  *.invf.dict.build,
+.I
+#   *.invf.chunk and *.invf.chunks.trans
+${source} | mg_passes -T1 -I1 -m 1 -t 1 -f ${text}
+.PP
+.I
+# Create *.text.dict
+mg_compression_dict -f ${text}
+.PP
+.I
+# Create *.invf.dict.hash
+mg_perf_hash_build -f ${text}
+.PP
+.I
+# Create *.text,  *.text.idx,
+.I
+#   *.invf and *.invf.idx
+${source} | mg_passes -T2 -I2 -c 2 -t 1 -f ${text}
+.PP
+.I
+# Create *.text.idx.wgt and *.weight.approx
+mg_weights_build -f ${text} -b 8
+.PP
+.I
+# Create *.invf.dict
+mg_invf_dict -f ${text} -b 4096
+.PP
+.I
+# Create *.text.dict
+mg_fast_comp_dict -f ${text}
+.ft R
+.fi
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.chunk
+Inverted file chunk descriptor file.  When the inverted file is
+created it is created in chunks that use no more than a set amount of
+memory.  This file describes those chunks.
+.TP
+.B *.invf.chunk.trans
+Word-occurrence-order to lexical-order translation file.  The
+.B *.invf.chunk
+file is written in word-occurrence order but is required by
+.B \-I2
+to be in lexical order.
+.TP
+.B *.invf.dict.build
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict.hash
+Data for an order-preserving perfect hash function.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.B *.text
+Compressed documents.
+.TP
+.B *.text.stats
+Statistics about the text.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.trace
+The default trace file.
+.TP
+.B *.compression.stats
+Statistics about the compression of the text.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_perf_hash_build.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_perf_hash_build.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_perf_hash_build.1	(revision 14757)
@@ -0,0 +1,89 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_perf_hash_build 1 \*(Dt CITRI
+.SH NAME
+mg_perf_hash_build \- generate an order-preserving hash function for the stemmed dictionary
+.SH SYNOPSIS
+.B mg_perf_hash_build
+[
+.B \-h
+]
+[
+.BI \-r " rndseed"
+]
+[
+.BI \-d  " directory"
+]
+.if n .ti +9n
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_perf_hash_build
+generates an order-preserving hashing function from the compressed
+stemmed dictionary and writes it out to disk.
+.BR mg_passes (1)
+will make use of the hash function when it builds the inverted file.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-r " rndseed"
+This specifies the random seed to be used in the generation of the
+hash function; it must be an integer.  If this is not specified, the
+current time will be used as the random seed.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf.dict
+Stemmed dictionary.
+.TP
+.B *.invf.dict.hash
+Data for a order-preserving perfect hash function.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_stem_idx.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_stem_idx.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_stem_idx.1	(revision 14757)
@@ -0,0 +1,95 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_stem_idx 1 \*(Dt CITRI
+.SH NAME
+mg_stem_idx \- builds a stem index file
+.SH SYNOPSIS
+.B mg_stem_idx
+[
+.B \-h
+]
+[
+.B \-F
+]
+[
+.BI \-b " num"
+]
+[
+.BI \-d " directory"
+]
+.if n .ti +9n
+.B \-s 1|2|3
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_stem_idx
+generates a stem index file for a collection that is to be built with
+stem indexes.  This program should be called three times: once for each
+.B -s
+parameter.  It uses the stemmed dictionary to create the stem index which
+contains pointers into the stemmed dictionary.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-b " num"
+The dictionary is stored in blocks on disk; this option is used to set
+the block size.  The default is 4-KB blocks.
+.TP
+.B \-F
+This option causes the disk blocks to be aligned on the appropriate
+boundaries.  For example, if 4-KB blocks are used, they will be aligned
+in the file on 4-KB boundaries.
+.TP
+.B -s 1|2|3
+The stem method to apply for the stem index.
+.br
+1 = casefolded and non-stemmed
+.br
+2 = non-casefolded and stemmed
+.br
+3 = casefolded and stemmed
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 25
+.B *.invf.dict.blocked
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict.blocked.1
+Stem index with stem index method 1.
+.TP
+.B *.invf.dict.blocked.2
+Stem index with stem index method 2.
+.TP
+.B *.invf.dict.blocked.3
+Stem index with stem index method 3.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_invf_dict (1),
+.BR mgstemidxlist (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_text_estimate.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_text_estimate.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_text_estimate.1	(revision 14757)
@@ -0,0 +1,112 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_text_estimate 1 \*(Dt CITRI
+.SH NAME
+mg_text_estimate \- Estimate the size of the compressed text based on the text statistics and a compression dictionary.
+.SH SYNOPSIS
+.B mg_text_estimate
+[
+.B \-h
+]
+[
+.BR \-H " |"
+.BR \-B " |"
+.BR \-D " |"
+.BR \-Y " |"
+.B \-M
+]
+.if n .ti +9n
+.I stats-dict
+.I compression-dict
+.SH DESCRIPTION
+This program estimates the size of the compressed text that would be
+generated if text with certain statistics were compressed with a
+particular dictionary.  This program has no real use in the
+.BR mg (1)
+system, except for experimenting with the
+.BR mg_compression_dict (1)
+program.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-m\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-H
+This specifies that novel words will be coded character by character
+using Huffman codes.
+.TP
+.B \-B
+This specifies that the size of an auxiliary dictionary will be
+estimated.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using binary codes.  The binary code represents their occurrence
+position in the auxiliary dictionary.
+.TP
+.B \-D
+This specifies that the size of an auxiliary dictionary will be
+estimated.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using delta codes.  The delta code represents their occurrence position
+in the auxiliary dictionary.
+.TP
+.B \-Y
+This specifies that the size of an auxiliary dictionary will be
+estimated.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using a combination of gamma and binary codes.  The code represents
+their occurrence position in the auxiliary dictionary.  This generally
+produces better compression than
+.B \-B
+or
+.BR \-D .
+.TP
+.B \-M
+This specifies that the size of an auxiliary dictionary will be
+estimated.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using a combination of gamma and binary codes.  The code represents
+their occurrence position in the auxiliary dictionary.  This method is
+adaptive within documents, and generally produces better compression
+than
+.BR \-B ,
+.B \-D
+or
+.BR \-Y .
+.SH FILES
+.TP 20
+.B *.text.stats
+Statistics about the text.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_text_merge.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_text_merge.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_text_merge.1	(revision 14757)
@@ -0,0 +1,76 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_text_merge 1 \*(Dt CITRI
+.SH NAME
+mg_text_merge \- Append one compressed text file to another
+.SH SYNOPSIS
+.B mg_text_merge
+[
+.B \-h
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+This program takes two
+.BR mg (1)
+database inverted files and stemmed
+dictionaries, named "old" and "new" respectively, and creates
+a merged stemmed dictionary and inverted file.
+It is part of the
+.BR mgmerge (1)
+addition to the
+.BR mg (1)
+package.
+The two compressed text files are
+.IR "name" .old.text
+and
+.IR "name" .new.text.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.old.text
+The old compressed text.
+.TP
+.B *.new.text
+The new compressed text that will be appended
+.TP
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mgmerge (1),
+.BR mg_get_merge (1),
+.BR mg_invf_merge (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mgquery (1).
Index: /indexers/branches/3.03a/mg/man/man1/mg_weights_build.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mg_weights_build.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mg_weights_build.1	(revision 14757)
@@ -0,0 +1,112 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_weights_build 1 \*(Dt CITRI
+.SH NAME
+mg_weights_build \- builds the approximate weights file
+.SH SYNOPSIS
+.B mg_weights_build
+[
+.B \-h
+]
+[
+.B \-s
+]
+[
+.BI \-b " num"
+]
+[
+.BI \-d " directory"
+]
+.if n .ti +9n
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_weights_build
+is the program that generates the approximate weights file and the
+interleaved text index and exact weights file.  To do this, it uses
+the text index and either the exact weights file, or the inverted file
+and stemmed dictionary.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-s
+Save the weights generated from the
+.I *.invf
+and
+.I *.invf.dict
+file in a
+.I *.weight
+file.
+.TP
+.BI \-b " num"
+This specifies the number of bits of precision that should be used for
+the approximate weights.  If not specified, it defaults to 8.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection is.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.dict
+Compressed stemmed dictionary.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.text.idx.wgt
+Interleaved index into the compressed documents and document weights.
+.TP
+.B *.weight.approx
+Approximate document weights.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgbilevel.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgbilevel.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgbilevel.1	(revision 14757)
@@ -0,0 +1,116 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgbilevel 1 \*(Dt CITRI
+.SH NAME
+mgbilevel \- compresses a bilevel image using a specified template
+.SH SYNOPSIS
+.B mgbilevel
+.B \-e
+[
+.B \-t
+.I \*(lqstring\*(rq
+]
+.I infile
+[
+.I \>compressed-outfile
+]
+.nf
+or
+.fi
+.B mgbilevel
+.B \-d
+.I compressed-infile
+[
+.I \>outfile
+]
+.SH DESCRIPTION
+.B mgbilevel
+performs (up to) a two-stage template-based compression.  The
+user can specify the template to be used in the compression process.  The
+default template size is a two-stage template 22/10.  The compressed file
+contains the template type in the stream.  The output files are written
+to
+.IR stdout .
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-t\fP \fI\*(lqstring\*(rq\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-e
+Compresses
+.I infile
+using a template specified, and writes to
+.IR compressed-outfile .
+.TP
+.B \-d
+Decompresses
+.I compressed-infile
+using the template contained in the compressed file.  Writes to
+.IR outfile .
+.TP
+\fB\-t \fP\fI\*(lqstring\*(rq\fP
+This option specifies which template combination is to
+be used in the compression.  Five different characters
+can occur in the string: `.' for a pixel not
+included in the template, `p' for a pixel included in the 1st
+level template, `2' for a pixel included in the 2nd level
+template (a subset of the 1st level), `*' denoting the position
+of the
+.I current
+pixel, and a `;' denoting the end of each template line.
+The default template is a two-level 22/10 template:
+.IP
+.RS
+.nf
+\&.ppppp.;
+pp222pp;
+p22222p;
+p22*.\|.\|.;
+.fi
+.RE
+.IP
+This would be specified on the command line as:
+.nf
+\&\fB\-T\fP ".ppppp.;pp222pp;p22222p;p22*.\|.\|.;"
+.fi
+.TP
+.I infile
+This is the input
+.I .pbm
+file to be compressed.
+.TP
+.I outfile
+This is the decompressed
+.I .pbm
+file.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgbuild.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgbuild.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgbuild.1	(revision 14757)
@@ -0,0 +1,169 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgbuild 1 \*(Dt CITRI
+.SH NAME
+mgbuild \- build an mg system database
+.SH SYNOPSIS
+.B mgbuild
+[
+.B \-c
+]
+[
+.BI \-g " get"
+]
+[
+.BI \-s " source"
+]
+[
+.BI \-d " mgdata dir"
+]
+.I collection-name
+.SH DESCRIPTION
+.B mgbuild
+is a
+.B csh
+script that executes all the appropriate programs in the correct order
+to completely build an
+.BR mg (1)
+system database ready for queries to be made
+by
+.BR mgquery.
+This program makes use of the
+.BR mg_get (1)
+script to obtain the text of the collection.
+.SH OPTIONS
+Options can occur in any order, but the collection name must be last.
+.TP "\w'\fIcollection-name\fP'u+2n"
+.BI \-c
+This specifies whether the
+.I get
+program is \*(lqcomplex\*(rq.  If a
+.I get
+program is \*(lqcomplex\*(rq, then it requires initialisation and
+cleanup with the
+.B \-i
+and
+.B \-c
+options.
+.TP
+.BI \-g " get"
+This specifies the program to use for getting the source text for the
+build.  If no
+.B \-g
+option is given, the default program
+.BR mg_get (1)
+is used.
+.TP
+.BI \-s " source"
+The
+.B mgbuild
+program consists of two parts.  The first part initializes variables
+to default values.  The second part uses these variables to control
+how the
+.BR mg (1)
+database is built.  This option specifies a program to execute between
+the first and second parts.  The details of what the variables are, and
+how they may be changed, are in comments in the
+.B mgbuild
+program.
+.TP
+.BI \-d " mgdata dir"
+Setting this option allows one to override the MGDATA environment variable.
+.TP
+.I collection-name
+This is the collection name, as required by the
+.BR mg_get (1)
+program.  It serves both as a
+.I case
+statement selector, and as the name of a subdirectory that holds the
+indexing files.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.chunk
+Inverted file chunk descriptor file.  When the inverted file is
+created, it is written in chunks that use no more than a set amount of
+memory.  This file describes those chunks.
+.TP
+.B *.invf.chunk.trans
+Word-occurrence-order to lexical-order translation file.  The
+.B *.invf.chunk
+file is written in word-occurrence order but is required by
+.B \-N2
+to be in lexical order.
+.TP
+.B *.invf.dict
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict.blocked
+The `on-disk' stemmed dictionary.
+.TP
+.B *.invf.dict.hash
+Data for an order-preserving perfect hash function.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.B *.text
+Compressed documents.
+.TP
+.B *.text.stats
+Text statistics.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.text.idx.wgt
+Interleaved index into the compressed documents and document weights.
+.TP
+.B *.weight.approx
+Approximate document weights.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgbuild_4.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgbuild_4.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgbuild_4.1	(revision 14757)
@@ -0,0 +1,53 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgbuild_4 1 \*(Dt CITRI
+.SH NAME
+mgbuild_4 \- build an mg system database using 4 passes instead of 2
+.SH SYNOPSIS
+.B mgbuild_4
+[
+.B \-c
+]
+[
+.BI \-g " get"
+]
+[
+.BI \-s " source"
+]
+[
+.BI \-d " mgdata dir"
+]
+.I collection-name
+.SH DESCRIPTION
+.B mgbuild_4
+is a
+.B csh
+script that executes all the appropriate programs in the correct order
+to completely build an
+.BR mg (1)
+system database ready for queries to be made
+by
+.BR mgquery.
+This program makes use of the
+.BR mg_get (1)
+script to obtain the text of the collection.
+In 
+.BR mgbuild (1)
+the build is done by two passes over the input text. The first
+pass creates the compressed text dictionary and inverted file dictionary,
+the second pass creates the compressed text and inverted file. What 
+.BR mgbuild_4
+does is use a separate pass for each function. This will be slower but will
+not require as much RAM at one time. Therefore, if your build is failing
+due to running short of memory, then 
+.BR mgbuild_4
+is worth a try.
+.SH "SEE ALSO"
+.na
+.BR mgbuild (1)
Index: /indexers/branches/3.03a/mg/man/man1/mgdictlist.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgdictlist.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgdictlist.1	(revision 14757)
@@ -0,0 +1,72 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgdictlist 1 \*(Dt CITRI
+.SH NAME
+mgdictlist \- list the contents of a dictionary
+.SH SYNOPSIS
+.B mgdictlist
+[
+.B \-q
+]
+.I filename
+.SH DESCRIPTION
+.B mgdictlist
+lists the contents of either a compressed compression dictionary, a
+text statistics file, or a compressed stemmed dictionary.  Unlike all
+the other programs in the
+.BR mg (1)
+suite, it is necessary to specify the complete pathname of the
+dictionary to list.
+.SH OPTIONS
+The
+.I filename
+must be last.
+.TP "\w'\fIfilename\fP'u+2n"
+.B \-q
+Generate an abbreviated output (machine-readable rather than
+human-readable).
+.TP
+.I filename
+This is the name of the dictionary to list.
+.B mgdictlist
+automatically detects whether the file is a compressed compression
+dictionary, text statistics file, or a compressed stemmed dictionary.
+.SH FILES
+.TP 20
+.B *.text.dict
+Text statistics file.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.invf.build
+Compressed stemmed dictionary.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgfelics.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgfelics.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgfelics.1	(revision 14757)
@@ -0,0 +1,103 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgfelics 1 \*(Dt CITRI
+.SH NAME
+mgfelics \- fast and efficient lossless image (de)compression
+.SH SYNOPSIS
+.B mgfelics
+.B \-e
+[
+.BI \-k " n"
+]
+.I infile
+[
+.I \>compressed-outfile
+]
+.br
+or
+.br
+.B mgfelics
+.B \-d
+.I compressed-infile
+[
+.I \>outfile
+]
+.SH DESCRIPTION
+.B mgfelics
+is a lossless compression process which can (de)compress portable
+bitmap files in
+.I pgm
+format.
+.B mgfelics
+writes to
+.IR stdout .
+.SH OPTIONS
+.TP "\w'\fB\-k\fP \fIn\fP'u+2n"
+.BI \-k " n"
+An integer parameter (< 32) which controls the compression speed and
+ratio.  The value of
+.I n
+is included in the output stream, and therefore is not needed in the
+decompression stage.  The default value of
+.I n
+is equal to the number of bits required to represent each grey level.
+.TP
+.B \-e
+Encodes the file
+.IR infile ,
+sending the output to
+.IR stdout .
+.TP
+.B \-d
+Decodes the file from
+.IR compressed-infile ,
+sending the output to
+.IR stdout .
+.SH NOTE
+.B mgfelics
+uses a combination of adjusted binary and Rice codes, the choice of
+which for any given pixel depends on the environment as determined by
+the intensity values of neighbouring pixels.  The result is a very
+fast and lossless algorithm for compressing grayscale images.  The
+optional parameter
+.BI \-k " n"
+corresponds to the maximum exponent of the same name in Rice encoding.
+Smaller values of
+.BI \-k " n"
+can result in significant improvement in compression times with a
+corresponding loss in compression ratio.  However the reduction in
+compression ratio with a small
+.BI \-k " n"
+parameter may be insignificant for many images.
+.SH REFERENCES
+Algorithm by Paul G. Howard and Jeffrey Scott Vitter
+of Brown University, RI, and Duke University, NC, respectively.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgmerge.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgmerge.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgmerge.1	(revision 14757)
@@ -0,0 +1,175 @@
+`.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgmerge 1 \*(Dt CITRI
+.SH NAME
+mgmerge \- update an mg system database with new documents
+.SH SYNOPSIS
+.B mgmerge
+[
+.B \-c
+]
+[
+.BI \-g " get"
+]
+[
+.BI \-s " source"
+]
+[
+.B \-S
+]
+[
+.B \-w
+]
+.I collection-name
+.SH DESCRIPTION
+.B mgmerge
+is a
+.B csh
+script that executes all the appropriate programs in the correct order
+to completely merge a current
+.BR mg (1)
+system database ready with some new documents, saving the need for a complete
+database rebuild with
+.B mgbuild.
+It does this by building a second
+.BR mg (1)
+system database from the new documents and then merging this database
+with the old one.
+This program makes use of the
+.BR mg_get_merge (1)
+script to obtain the text of the collection.
+.B mgmerge
+cannot edit or delete documents already in a database; only new documents
+can be added.
+.SH OPTIONS
+Options can occur in any order, but the collection name must be last.
+.TP "\w'\fIcollection-name\fP'u+2n"
+.BI \-c
+This specifies whether the
+.I get
+program is \*(lqcomplex\*(rq.  If a
+.I get
+program is \*(lqcomplex\*(rq, then it requires initialisation and
+cleanup with the
+.B \-i
+and
+.B \-c
+options.
+.TP
+.BI \-g " get"
+This specifies the program to use for getting the source text for the
+build.  If no
+.B \-g
+option is given, the default program
+.BR mg_get_merge (1)
+is used.
+.TP
+.BI \-s " source"
+The
+.B mgmerge
+program consists of two parts.  The first part initializes variables
+to default values.  The second part uses these variables to control
+how the
+.BR mg (1)
+database is built.  This option specifies a program to execute between
+the first and second parts.  The details of what the variables are, and
+how they may be changed, are in comments in the
+.B mgmerge
+program.
+If this option is used, the program should ideally be the same one that
+was called by
+.BR mgbuild (1)
+to build the database since some parameters need to be consistent between
+.B mgbuild
+and
+.B mgmerge.
+.TP
+.B \-S
+This option will cause a slow merge to be performed on the inverted files,
+where each inverted file entry is decoded and recoded.
+The default is a fast merge. Accumulated fast merges slowly degrade
+compression performance on the resulting inverted file so
+a periodic slow merge is recommended.
+.TP
+.B \-w
+Adding new documents can have an effect on the weight of the previous ones.
+By default the weights for documents already in the collection are not 
+recomputed since the change in their values is usually small.
+This option forces new weights to be recomputed.
+Periodic use of this option, as for the "-S" option, is recomended,
+otherwise query rankings may become inaccurate.
+.TP
+.I collection-name
+This is the collection name, as required by the
+.BR mg_get_merge (1)
+program.  It serves both as a
+.I case
+statement selector, and as the name of a subdirectory that holds the
+indexing files.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+Note that a temporary directory under the
+.B MGDATA
+directory is used to perform the merge.
+The default name for this directory is
+.BR MERGE .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.dict
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict.blocked
+The `on-disk' stemmed dictionary.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.B *.text
+Compressed documents.
+.TP
+.B *.text.stats
+Text statistics.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.text.idx.wgt
+Interleaved index into the compressed documents and document weights.
+.TP
+.B *.weight.approx
+Approximate document weights.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mgbuild (1),
+.BR mg_get_merge (1),
+.BR mg_get (1),
+.BR mg_invf_merge (1),
+.BR mg_text_merge (1),
+.BR mg_query (1),
+.BR mg_weights_build (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgquery.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgquery.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgquery.1	(revision 14757)
@@ -0,0 +1,693 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgquery 1 \*(Dt CITRI
+.SH NAME
+mgquery \- query program for the mg system
+.SH SYNOPSIS
+.B mgquery
+[
+.B \-h
+]
+[
+.B \-D
+]
+[
+.BI \-f " name"
+]
+[
+.BI \-d " directory"
+]
+.if n .ti +9n
+[
+.I collection-name
+]
+.SH DESCRIPTION
+.B mgquery
+enables users to make Boolean or ranked queries from a data base
+generated by the
+.BR mg (1)
+system.  It accepts queries from
+.I stdin
+and sends the retrieved documents to
+.IR stdout .
+Information on the resource usage of
+.B mgquery
+as it processes queries can be obtained interactively.
+.SH OPTIONS
+Options may appear in any order, but the
+.IR collection-name ,
+if specified, must be last.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-D
+This option causes the entire text to be decompressed and sent to
+.IR stdout .
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection that will be
+used.  If a collection with the specified base
+.I name
+does not exist, an error message will be displayed and
+.B mgquery
+will exit.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.SH USAGE
+Prior to processing the command line arguments, the
+.B mgquery
+program attempts to read in a startup script called
+.IR ./.mgrc .
+If that fails, it attempts to read in the file
+.IR $HOME/.mgrc .
+The startup file can only contain commands\(emno queries are
+permitted in the
+.I .mgrc
+file.  Lines starting with \*(lq\fB#\fP\*(rq in the file are comments.
+The most common use for the
+.I .mgrc
+file is to personalise the initial values of the predefined parameters
+with
+.B .set
+commands.
+.LP
+The input to
+.B mgquery
+consists of a series of input lines.  The backslash
+character
+.RB (\*(lq \e \*(rq)
+is used at the end of lines to indicate
+that input continues on the next line.
+.LP
+Input lines on which the first character is a dot
+.RB (\*(lq . \*(rq)
+are commands to the
+.B mgquery
+program.  Input lines that do not start with a dot are queries.
+.LP
+A query consists of two parts.  One part is a Boolean or ranked query
+that identifies documents.  The second part is a post-processing
+pattern matching operation.  Any text between the first speech mark
+(\*(lq) and the last speech mark (\*(rq) is considered to be a
+post-processing pattern.
+.SH COMMANDS
+The
+.B mgquery
+program can accept the following commands.
+.TP 17
+.B .help
+Display several pages of help text.
+.TP
+.B .quit
+Quit the program.
+.TP
+.B .warranty
+Display the
+.BR mg (1)
+warranty.
+.TP
+.B .conditions
+Display the conditions of use and distribution of
+.BR mg (1).
+.TP
+.BI ".set " "name value"
+Set the parameter
+.I name
+to the specified
+.IR value .
+If the parameter is a Boolean
+.I value
+and the
+.I value
+is omitted, the parameter will be inverted (i.e., if it was
+.IR true ,
+then it will change to
+.IR false ;
+if it was
+.IR false ,
+then it will change to
+.IR true ).
+.TP
+.BI ".unset " name
+Delete the parameter
+.I name
+from the currently-defined parameters.
+.TP
+.B .reset
+Reset the parameters to the state that they had after the processing
+of the
+.B mgquery
+command line.
+.TP
+.B .display
+Display the values of all the currently-defined parameters.
+.TP
+.B .push
+Push the currently-defined parameters onto a stack.
+.TP
+.B .pop
+Pops a set of parameters off the stack, replacing the currently-defined
+ones.
+.TP
+.BI ".output " arg
+This is used to specify where to send the text of the documents.  Once
+the
+.B .output
+command is specified, all subsequent output will be sent to the place
+specified by
+.IR arg .
+If
+.I arg
+is not specified subsequent output will be directed to
+.IR stdout .
+.I Arg
+may be any of the following.
+.RS
+.TP 13
+.BI "> " filename
+Send output to the specified file.
+.TP
+.BI ">> " filename
+Append output to the specified file.
+.TP
+.BI "| " command
+Pipe the output to
+.IR command ,
+which is executed by
+.IR sh .
+.RE
+.TP
+.BI ".input " arg
+This is used to specify where input (queries and commands) comes
+from.  Once the
+.B .input
+command is specified all subsequent input will be come from the place
+specified by
+.IR arg .
+If
+.I arg
+is not specified subsequent input will come from
+.IR stdin .
+.RS
+.TP 13
+.BI "< " filename
+Get input from the specified file.
+.TP
+.BI "| " command
+The input comes from the standard output of
+.IR command ,
+which is executed by
+.IR sh .
+.RE
+.SH PARAMETERS
+The following parameters are predefined and have special
+significance.  Each parameter will be followed by its default
+value.  Parameters are initialised before the
+.I .mgrc
+file is read or the command line arguments are processed.
+.TP 17
+.BI accumulator_method " `array'"
+This parameter is used during ranking, and specifies how the
+weight for each document should be accumulated.  The following
+methods are available:
+.IR array ,
+.IR splay_tree ,
+.IR hash_table ,
+and
+.IR list .
+.TP
+.BI briefstats " `off'"
+This is a Boolean parameter that determines whether the
+totals for disk, memory and time usage statistics will be
+displayed at the end of each query.
+.IR Note :
+this takes precedence over the parameters
+.BR diskstats ,
+.BR memstats " and " timestats .
+This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI buffer " `1048576'"
+When the documents are being read in, they are read into a
+buffer of this size and then displayed from this buffer.  If
+the documents are larger than this buffer, the buffer is
+expanded automatically.  Having a large buffer gives a very
+slight performance improvement, because it allows the order of
+disk operations to be optimised.  The buffer size is measured
+in bytes.
+.TP
+.BI diskstats " `off'"
+This is a Boolean parameter that determines whether the disk
+usage statistics for the preceding query will be displayed
+after each query.  This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI doc_sepstr " `---------------------------------- %n\en\'"
+This specifies the string that will be used to separate
+documents when they are displayed for `Boolean' or `docnums'
+queries.  The standard C escape character sequences
+may be used to place special characters in the
+string.  For example, a newline would be `\en'.  To include a `%',
+use the sequence `%%'.  To include the
+.BR mg (1)
+document number, use the sequence `%n'.  The following escape character
+sequences are available
+.nf
+.ta 1.7iL
+.B Sequence	Meaning
+`\e\e'	backslash
+`\eb'	backspace
+`\ef'	formfeed
+`\en'	newline
+`\er'	carriage return
+`\et'	tab
+`\e"'	speech marks
+`\e''	quote mark
+`\ex\fIhh\fP'	ASCII code in hexadecimal
+`\ennn'	ASCII code in octal
+.fi
+.TP
+.BI expert " `false'"
+If this is
+.IR true ,
+then much of the dialogue output is suppressed.  This parameter may
+take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI hash_tbl_size " `1000'"
+One of the options during ranking queries is to use a hash
+table to accumulate the weights for each document.  The hash
+table is a simple chained type.  This parameter specifies the
+size of the hash table and may take any value between 8 and
+268435456 (2^28).
+.TP
+.BI heads_length " `50'"
+When the mode is
+.BR heads ,
+this specifies the number of characters that will be output for each
+document.
+.TP
+.BI maxdocs " `all'"
+The maximum number of documents to display in response to a
+query.  This parameter may take on a numeric value between 1
+and 429467295 (2^32 - 1) or the word
+.IR all .
+.TP
+.BI maxparas " `1000'"
+The maximum number of paragraphs to identify during a ranked
+query with paragraph indexing.  After the paragraphs have been
+identified, the paragraphs are converted into documents, and
+because some of the paragraphs may refer to the same documents
+the final number of answers may be less than
+.BR maxparas .
+The
+.B maxdocs
+parameter will then be applied.  This parameter may take on a numeric
+value between 1 and 429467295 (2^32 - 1).
+.TP
+.BI max_accumulators " `50000'"
+This parameter limits the number of different paragraph and
+document numbers to be accumulated during ranked queries when
+the parameter
+.B accumulator_method
+is set to
+.IR splay_tree ,
+.IR hash_table ,
+or
+.IR list .
+This parameter may take any value between 8 and 268435456 (2^28).
+.TP
+.BI max_terms " `all'"
+This parameter limits the number of terms that will actually
+be used during a ranked query.  If more terms than the number
+specified by
+.B max_terms
+are entered, then the extra terms will be discarded.  If
+.B sorted_terms
+is on, then the limiting will be done after the terms have been
+sorted.  This parameter may take any value between 1 and 429467295
+(2^32 - 1), or the word
+.IR all.
+.TP
+.BI memstats " `off'"
+This is a Boolean parameter that determines whether the memory
+usage statistics for the preceding query will be displayed
+after each query.  This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI mgdir " `.'"
+This is set to the directory where the
+.BR mg (1)
+data files may be found.  If
+the environment variable
+.B MGDATA
+exists, then this is instead initialised to the value of
+.BR MGDATA .
+The value of this parameter may be changed, either in the
+.I .mgrc
+file with a
+.BI ".set mgdir "directory
+command, or from the command line using the
+.BI \-d " directory"
+option.  Once the \*(lq\fB>\fP\*(rq prompt appears, changing this
+parameter will have no effect.
+.TP
+.BI mgname " `bible'"
+This is set to the name of the
+.BR mg (1)
+collection that is to be used for the session.  The value of this
+parameter may be changed, either in the
+.I .mgrc
+file with a
+.BI ".set mgname "name
+command, or from the command line using the
+.BI \-f " name"
+option.  Once the \*(lq\fB>\fP\*(rq prompt appears, changing this
+parameter will have no effect.
+.TP
+.BI mode " `text'"
+This specifies how documents should be displayed when they
+are retrieved.  It may take six different values:
+.IR text ,
+.IR hilite ,
+.IR docnums ,
+.IR heads ,
+.IR silent ,
+or
+.IR count .
+.I text
+displays the contents of the document.
+.I hilite
+displays the contents of the document and highlights any of the 
+stemmed query terms.
+.I docnums
+displays only the document numbers.
+.I heads
+is used to print out the head of each document.
+.I silent
+retrieves all the documents but displays nothing except how many
+documents were retrieved.  This mode is intended to be used in timing
+experiments.
+.I count
+does the minimum
+amount of work required to determine how many documents would
+be retrieved, but does not retrieve them.
+.TP
+.BI optimise_type " `1'"
+There are three types of boolean query optimisation (parse tree
+rearrangement). Type 0 leaves parse tree unaltered. Type 1 optimises
+for AND of terms and AND of OR of terms. Type 2 converts the tree
+into DNF (an experiment :-).
+.TP
+.BI pager " `more'"
+This is the name of the program that will be used to display
+the help and the retrieved documents.  If the environment
+variable
+.B PAGER
+is defined, then
+.B pager
+takes on that value.
+.TP
+.BI hilite_style " `bold'"
+This specifies the type of highlighting method.
+It may take one of two different values:
+.IR bold,
+or
+.IR underline.
+.TP
+.BI para_sepstr " `\en######## PARAGRAPH %n ########\en'"
+This specifies the string that will be used to separate paragraphs.
+The standard C escape character sequences may be used to place special
+characters in the string.  For example, a newline would be written
+as `\en'.  To include a `%', use the sequence `%%'.  To include the
+paragraph number within the document, use the sequence `%n'.
+.TP
+.BI para_start " `***** Weight = %w *****\en'"
+This specifies the string that will be used at the head of paragraphs
+for a paragraph-level index following a ranked query.  The standard
+C-language escape character sequences may be used to place special
+characters in the string.  For example, a newline would be written as
+`\en'.  To include a `%', use the sequence `%%'.  To include the
+paragraph weight, use the sequence `%w'.
+.TP
+.BI qfreq " `true'"
+This determine whether the ranked queries will take into account the
+number of times each query term is specified.  When this is
+.IR true ,
+the number of times a term appears in the query is used in the
+ranking.  When this is
+.IR false ,
+all query terms are assumed to occur only once.  This parameter may
+take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI query  " `Boolean'"
+This specifies the type of queries that are to be specified.
+It can take four different values:
+.IR Boolean ,
+.IR ranked ,
+.IR docnums " or " approx-ranked.
+.I Boolean
+is for Boolean queries.
+The
+.BR yacc (1)
+grammar for Boolean queries is as follows.
+.IP
+.nf
+        query   : or;
+.IP
+        or      : or '|' and
+                | and ;
+.IP
+        and     : and '&' not
+                | and not
+                | not ;
+.IP
+        not     : term
+                | '!' not ;
+.IP
+        term    : TERM
+                | '(' or ')' ;
+.fi
+.IP
+.IR ranked " and " approx-ranked
+are for queries ranked by the cosine measure.
+.I approx-ranked
+uses only the low-precision document lengths, and therefore only
+produces an approximation to full cosine ranking.
+.IP
+.nf
+        query   : TERM
+                | query TERM ;
+.fi
+.IP
+.I docnums
+allows the entry of document numbers.  Multiple numbers separated by
+spaces may be specified, or ranges separated by hyphens.
+.IP
+.nf
+        query   : range
+                | query range ;
+.IP
+        range   : num
+                | num '-' num ;
+.fi
+.TP
+.BI ranked_doc_sepstr " `-------------------------------- %n %w\en'"
+This specifies the string that will be used to separate documents when
+they are displayed for `ranked' or `approx-ranked' queries.  The
+standard C escape character sequences may be used to place special
+characters in the string.  For example, a newline would be written as
+`\en'.  To include a `%', use the sequence `%%'.  To include the
+.BR mg (1)
+document number, use the sequence `%n'.  To include the document
+weight, use the sequence `%w'.
+.TP
+.BI sizestats " `false'"
+If this is
+.IR true ,
+then various numbers are output at the end of each query indicating
+what went on during the query.  This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI skip_dump " `skips.%d'"
+If this parameter is set, then a file will be produced in the current
+directory during ranked queries on skipped inverted files when
+.B accumulator_method
+is set to
+.IR splay_tree ,
+.IR hash_table ,
+or
+.IR list .
+The name of the file is the value of this parameter.  A `%d' in the
+file name will be replaced with the process id of
+.BR mgquery .
+This file will contain information about the usage of skips during the
+query processing.  This option is expensive; use
+.B .unset skip_dump
+to obtain optimal performance.
+.TP
+.BI sorted_terms " `on'"
+This specifies whether or not the terms should be sorted into
+decreasing occurrence in documents so that the least-often occurring
+terms are processed first when ranked queries are being done.  When
+this is
+.IR true ,
+the terms are sorted.  When this is
+.IR false ,
+the terms are not sorted, and are instead processed in order of
+occurrence.  This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI stop_at_max_accum " `on'"
+This specifies what should happen when the maximum number of
+accumulators set by
+.B max_accumulators
+is reached.  When this is
+.IR true ,
+the processing of terms is stopped at the completion of the current
+term.  When this is
+.IR false ,
+processing continues but no new accumulators are created.  This
+parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI terminator " `'"
+This specifies the string that will be output after the last document
+from the previous query has been output.  The standard C escape
+character sequences may be used to place special characters in the
+string.  For example, a newline would be written as `\en'.  To include
+a `%', use the sequence `%%'.
+.TP
+.BI timestats " `false'"
+If this is
+.IR true ,
+then the time to process a query is displayed in both real time and
+CPU time.  This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI verbatim " `off'"
+This is a Boolean parameter that determines whether the program
+should attempt to do a regular-expression match on the retrieved
+text.  If verbatim is
+.I on
+and a post-processing string is specified with the query, then the
+post-processing string will be searched for in the documents just
+before they are displayed.  If the string is found, the document will
+be displayed; if not, the document will not be displayed.  If verbatim
+is
+.IR off ,
+the post-processing string will be considered a regular expression
+as in
+.BR egrep (1)
+or
+.BR vi (1).
+E.g., if verbatim is
+.I on,
+\*(lq\fBand.*the\fP\*(rq will look for the 8-character sequence
+\*(lq\fBand.*the\fP\*(rq.  If verbatim is
+.IR off ,
+\*(lq\fBand.*the\fP\*(rq will look for the sequence
+\*(lq\fBand\fP\*(rq followed somewhere later in the document by the
+sequence \*(lq\fBthe\fP\*(rq.  This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.I .mgrc
+.B mgquery
+startup file
+.TP
+.B help.mg
+Help file for
+.BR mgquery .
+The contents of this file is displayed with the
+.B .help
+command.
+.TP
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.dict
+The `on-disk' stemmed dictionary.
+.TP
+.B *.text
+Compressed documents.
+.TP
+.B *.text.dict
+Compression dictionary.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.text.idx.wgt
+Interleaved index into the compressed documents and document weights.
+.TP
+.B *.weight.approx
+Approximate document weights.
+.SH "SEE ALSO"
+.na
+.BR egrep (1),
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1),
+.BR vi (1),
+.BR yacc (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgstat.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgstat.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgstat.1	(revision 14757)
@@ -0,0 +1,131 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgstat 1 \*(Dt CITRI
+.SH NAME
+mgstat \- print out statistics about a document collection
+.SH SYNOPSIS
+.B mgstat
+[
+.B \-h
+]
+[
+.B \-E
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mgstat
+prints out various statistics about an existing
+.BR mg (1)
+document collection.  Depending on the size of the collection, sizes
+will be printed in either kilobytes or megabytes.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stdout .
+.TP
+.B \-E
+This option forces sizes to be printed in bytes rather than kilobytes
+or megabytes.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.text
+Compressed documents.
+.TP
+.B *.invf
+Inverted file.
+.TP
+.B *.text.idx.wgt
+Interleaved index into the compressed documents and document weights.
+.TP
+.B *.weight.approx
+Approximate document weights.
+.TP
+.B *.invf.dict.blocked
+Compressed stemmed dictionary and index into the inverted file merged
+into an inverted file.
+.TP
+.B *.text.dict.fast
+Fast loading compression dictionary.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.invf.dict
+Compressed stemmed dictionary.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.TP
+.B *.text.stats
+Statistics about the text.
+.TP
+.B *.text.dict.aux
+Auxiliary compression dictionary.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.B *.invf.chunk
+Maps stemmed terms from occurrence order to lexical order.
+.TP
+.B *.invf.chunk.trans
+Describes where the source text is broken up into chunks for the
+inversion pass.
+.TP
+.B *.invf.dict.hash
+A perfect hash function for the terms in the stemmed dictionary.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgstemidxlist.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgstemidxlist.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgstemidxlist.1	(revision 14757)
@@ -0,0 +1,86 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgstemidxlist 1 \*(Dt CITRI
+.SH NAME
+mgstemidxlist \- dumps the stem index file to STDOUT in ASCII format
+.SH SYNOPSIS
+.B mgstemidxlist
+[
+.B \-h
+]
+[
+.BI \-d " directory"
+]
+.B \-s 1|2|3
+.BI \-f " name"
+.SH DESCRIPTION
+.B mgstemidxlist
+is a utility program which passes through the stem index and displays
+the information.  (This program was used for debugging but is included
+for completeness!)  The header information is printed out, then for each
+block in the file the block header is displayed.  For each word in the
+stem index, the output is formatted as:
+
+.RS
+.I number_of_references \*(lqword\*(rq
+.br
+.RS
+.I "->  number_of_cases block 3-in-4_block offset"
+.br
+.I "->  ..."
+.RE
+.RE
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B -s 1|2|3
+The stem index file with the associated stem method.
+.br
+1 = casefolded and non-stemmed
+.br
+2 = non-casefolded and stemmed
+.br
+3 = casefolded and stemmed
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 25
+.B *.invf.dict.blocked.1
+Stem index with stem index method 1.
+.TP
+.B *.invf.dict.blocked.2
+Stem index with stem index method 2.
+.TP
+.B *.invf.dict.blocked.3
+Stem index with stem index method 3.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_invf_dict (1),
+.BR mg_stem_idx (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgtic.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgtic.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgtic.1	(revision 14757)
@@ -0,0 +1,137 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgtic 1 \*(Dt CITRI
+.SH NAME
+mgtic \- textual image compression.
+.SH SYNOPSIS
+.B mgtic
+.B \-e
+[
+.B \-L
+]
+[
+.B \-Q
+]
+[
+.B \-X
+]
+.I libraryfile
+.I infile
+.if n .ti +9n
+[
+.I \>compressed\-outfile
+]
+.nf
+or
+.fi
+.B mgtic
+.B \-d
+[
+.B \-L
+]
+[
+.BI \-X " libraryfile"
+]
+.I compressed-infile
+.if n .ti +9n
+[
+.I \>outfile
+]
+.SH DESCRIPTION
+This is the main routine in the
+.B mgtic
+system.
+.B mgtic
+is used to
+processes a series of files, and by using the
+.I libraryfile
+produced by
+.BR mgticbuild (1),
+compresses input files with respect to the marks contained in the
+library.  On the CCITT test faxes, lossless mode achieved around 20:1
+compression, and lossy, around 40:1 compression.  On more textual
+images, the amount of compression is determined by the resolution of
+the original file, and the amount of noise in the image.  By default,
+.B mgtic
+will reconstruct a lossy version of the image.  This
+can be changed to lossless by using the
+.B \-L
+option.
+.SH OPTIONS
+Options may appear in any order, but must come before the input
+filenames.
+.TP "\w'\fB\-X\fP \fI[libraryfile]\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-e
+Encode
+.I infile
+with respect to the library.
+.TP
+.B \-d
+Decodes
+.IR compressed-infile
+with respect to the library.
+.TP
+.B \-l
+This specifies lossy mode, and is the default mode for (de)compression.
+Do not generate the residue.  If used in encoding mode, does not store
+the residue in the output.  If used in decoding mode, the residue (if
+it exists) is ignored.
+.TP
+.B \-L
+Use lossless mode for (de)compression, which generates the residue.
+If used in encoding mode, this stores the residue in the compressed
+output.  If used in decoding mode (assuming the residue is present),
+this allows the original file to be recovered exactly.
+.TP
+.BI \-R\  filename
+Stores the residue as an external file
+.I filename
+which could possibly be stored on another medium.  During
+decompression, if the residue file specified does not relate to the
+compressed file, the resulting decompressed image will be a mess.
+Note that only the width and height of the residue image is checked.
+.TP
+.BI \-Q
+Uses a quicker form of compression.  This option decreases the time
+spent looking for a good match during encoding.  On average this
+option decreases compression ratios, but increases compression speed.
+.TP
+.BI \-X " [libraryfile]"
+Use an external library file, instead of (de)compressing the library
+within the normal stream.  When decoding, the
+.B \-X
+option must be followed by the
+.IR libraryfile .
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgticbuild.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgticbuild.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgticbuild.1	(revision 14757)
@@ -0,0 +1,61 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgticbuild 1 \*(Dt CITRI
+.SH NAME
+mgticbuild \- build a library of marks from training documents
+.SH SYNOPSIS
+.B mgticbuild
+[
+.B \-h
+]
+.I "libraryfile infile1 infile2 .\|.\|."
+.SH DESCRIPTION
+.B mgticbuild
+builds an uncompressed library of marks that have been
+extracted from a series of input files.  If the
+.I libraryfile
+does
+not exist, it is created, otherwise new marks are appended to the
+file.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fIlibraryfile\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.I libraryfile
+This specifies the name of the library file.
+.TP
+.I infile(s)
+The training files; the only currently-supported format is
+.IR pbm .
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgticdump.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgticdump.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgticdump.1	(revision 14757)
@@ -0,0 +1,55 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgticdump 1 \*(Dt CITRI
+.SH NAME
+mgticdump \- displays the library in a user-friendly manner
+.SH SYNOPSIS
+.B mgticdump
+[
+.B \-h
+]
+.I libraryfile
+.SH DESCRIPTION
+.B mgticdump
+displays the marks in a library in a user-viewable form.  The output
+is to
+.I stdout
+and is in a plain ASCII form.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fIlibraryfile\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.I libraryfile
+This specifies the name of the library file.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgticprune.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgticprune.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgticprune.1	(revision 14757)
@@ -0,0 +1,91 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgticprune 1 \*(Dt CITRI
+.SH NAME
+mgticprune \- prunes the library to remove duplicates
+.SH SYNOPSIS
+.B mgticprune
+[
+.BI \-a " n"
+]
+[
+.BI \-s " n"
+]
+[
+.B \-Q
+]
+.I libraryfile
+.if n .ti +9n
+[
+.I pruned-libraryfile
+]
+.SH DESCRIPTION
+.B mgticprune
+examines
+.I libraryfile
+and removes duplicate marks.  If
+.I pruned-libraryfile
+is not specified,
+.I libraryfile
+is overwritten with the marks in the pruned library.  The Combined
+Symbol Independent Strategy (CSIS) method is used to match marks.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fIpruned-libraryfile\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-a " n"
+Prune marks when their area is under or equal to the threshold,
+.IR n .
+The default value is\ 3.
+.TP
+.BI \-s " n"
+Prune marks when their width and height is under or equal to
+the threshold,
+.IR n .
+The default value is\ 0.
+.TP
+.BI \-Q
+Use a quicker method of pruning.  The number of iterations through the
+averaging and pruning processes is decreased.  This usually reduces
+time by a half, but compression ratios decrease.
+.TP
+.I libraryfile
+This specifies the name of the library file
+.TP
+.I pruned-libraryfile
+This specifies the name of the prune library, after duplicates and
+matches have been removed.  If this file is not specified, then
+.I libraryfile
+will be overwritten.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/man/man1/mgticstat.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/mgticstat.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/mgticstat.1	(revision 14757)
@@ -0,0 +1,57 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgticstat 1 \*(Dt CITRI
+.SH NAME
+mgticstat \- displays the statistics for the library
+.SH SYNOPSIS
+.B mgticstat
+[
+.B \-h
+]
+.I libraryfile
+.SH DESCRIPTION
+.B mgticstat
+displays statistics about the
+.I libraryfile
+file.
+The output of this program contains the average mark size, average
+centroid position, and the number of marks with an area less than or
+equal to a few powers of\ 2.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fIlibraryfile\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.I libraryfile
+This specifies the name of the library file.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1).
Index: /indexers/branches/3.03a/mg/man/man1/xmg.1
===================================================================
--- /indexers/branches/3.03a/mg/man/man1/xmg.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/man/man1/xmg.1	(revision 14757)
@@ -0,0 +1,130 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH xmg 1 \*(Dt CITRI
+.SH NAME
+xmg \- An X interface to mgquery
+.SH SYNOPSIS
+.B xmg
+[
+.I collection-name
+]
+.SH DESCRIPTION
+.B xmg
+is an X interface to the
+.BR mg (1)
+information retrieval system.
+.PP
+Type a query in the ``Query'' box.  The escape key clears the query text.
+.PP
+The first line or so of each matching document is listed.
+.PP
+Click on any line to show the complete document.
+.PP
+Shift-click to show the document in a new window.
+.PP
+Press
+.I Next
+and
+.I Previous
+to cycle through the list of documents (shift works here too).
+.PP
+If you change the query, existing windows continue to refer to the
+original query.
+.PP
+You can select either Boolean or ranked queries:
+.RS
+.TP "\w'\fIBoolean queries:\fP'u+2n"
+.I "Boolean queries:"
+use ``&'' for AND, ``|'' for OR, ``!'' for NOT, and parentheses for
+grouping.
+.TP
+.I "Ranked queries:"
+Documents are listed in order of relevance.  A weight is shown
+alongside each.  Weights are normalized to 100 for the most relevant
+document.  Choose
+.I "Approximate Ranking"
+for greater retrieval speed.
+.RE
+.PP
+In document windows (other than the main window):
+.RS
+.br
+Typing `n' = next document;
+.br
+Typing `N' = next document in new window;
+.br
+Typing `p' = previous document;
+.br
+Typing `P' = previous document in new window;
+.br
+Typing `q' = close window.
+.RE
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.TP
+.SB Xdefaults
+To override the default font options, use RESOURCE_MANAGER properties
+like the following in your
+.I .Xdefaults
+file:
+.IP
+.RS
+.nf
+.I "xmg.textfont: fixed"
+.I "xmg.buttonfont: fixed"
+.fi
+.RE
+.IP
+To override the default query type of ranked, use
+.IP
+.RS
+.I "xmg.querytype: boolean"
+.RE
+.IP
+To override the default collection name (the first one listed by
+.BR ls (1)
+from your MGDATA environment variable), use
+.IP
+.RS
+.I "xmg.collection: mail93"
+.RE
+.SH "SEE ALSO"
+.na
+.BR ls (1),
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/mkinstalldirs
===================================================================
--- /indexers/branches/3.03a/mg/mkinstalldirs	(revision 14757)
+++ /indexers/branches/3.03a/mg/mkinstalldirs	(revision 14757)
@@ -0,0 +1,32 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Last modified: 1994-03-25
+# Public domain
+
+errstatus=0
+
+for file in ${1+"$@"} ; do 
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d in ${1+"$@"} ; do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp" 1>&2
+        mkdir "$pathcomp" || errstatus=$?
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
Index: /indexers/branches/3.03a/mg/src/images/Makefile.in
===================================================================
--- /indexers/branches/3.03a/mg/src/images/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/Makefile.in	(revision 14757)
@@ -0,0 +1,216 @@
+###########################################################################
+#
+# Makefile.in -- Makefile for the MG system
+# Copyright (C) 1994  Neil Sharman
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#       @(#)Makefile.in	1.10 22 Mar 1994
+#
+###########################################################################
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+ 
+SHELL = /bin/sh
+VPATH = @srcdir@
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+bindir = @bindir@
+srcdir = @srcdir@
+subdir = src/images
+top_srcdir = @top_srcdir@
+transform = @program_transform_name@
+ 
+CC = @CC@
+CFLAGS = @CFLAGS@ 
+CPPFLAGS = @CPPFLAGS@
+DEFS = @DEFS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBS = ../../lib/libmglib.a @LIBS@
+TOUCH = echo timestamp >
+ 
+datadir = $(prefix)/share
+libexecdir = $(exec_prefix)/libexec
+localedir = $(datadir)/locale
+mandir = $(prefix)/man/man1
+ 
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(LDFLAGS) -o $@
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+	$(COMPILE) $<
+ 
+
+ANSI2KNR = @ANSI2KNR@
+o = .@U@o
+ 
+.SUFFIXES: ._c ._o
+.c._c:
+	./ansi2knr $< > $*.tmp && mv $*.tmp $@
+._c._o:
+	@echo $(COMPILE) $<
+	@rm -f _$*.c
+	@ln $< _$*.c && $(COMPILE) _$*.c && mv _$*.o $@ && rm _$*.c
+.c._o:
+	./ansi2knr $< > $*.tmp && mv $*.tmp $*._c
+	@echo $(COMPILE) $*._c
+	@rm -f _$*.c
+	@ln $*._c _$*.c && $(COMPILE) _$*.c && mv _$*.o $@ && rm _$*.c
+ 
+INCLUDES = -I../../../.. -I../.. -I../../lib -I.
+
+
+SOURCES = \
+  arithcode.c     extractor.c     mgbilevel.c     mgticdump.c     utils.c \
+  bilevel.c       felics.c        mgfelics.c      mgticprune.c    mgticstat.c\
+  codeoffsets.c   marklist.c      mgtic.c         pbmtools.c      lstevent.c \
+  codesyms.c      match.c         mgticbuild.c    sortmarks.c     ppm.c  
+
+
+ 
+HEADERS = \
+  arithcode.h     codeoffsets.h   marklist.h      sortmarks.h \
+  basictypes.h    codesyms.h      match.h         utils.h     \
+  bilevel.h       extractor.h     pbmtools.h      model.h
+
+MISC          = Makefile.in 
+
+ALLFILES      =	$(SOURCES) $(HEADERS) $(MISC) $(MAN)
+
+DISTFILES     = $(ALLFILES) 
+
+EXEC          = mgfelics mgbilevel mgtic mgticbuild mgticprune mgticstat \
+                mgticdump
+
+MAN           = mgfelics.1 mgbilevel.1 mgtic.1 mgticbuild.1  mgticprune.1 \
+                mgticstat.1 mgticdump.1
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+all: $(EXEC)
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+FELICS_OBJS = felics$o mgfelics$o utils$o
+
+mgfelics: $(FELICS_OBJS)
+	$(LINK) $(FELICS_OBJS) $(LIBS)
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+BILEVEL_OBJS = \
+	arithcode$o bilevel$o extractor$o marklist$o mgbilevel$o \
+	pbmtools$o utils$o
+            
+mgbilevel: $(BILEVEL_OBJS)
+	$(LINK) $(BILEVEL_OBJS) $(LIBS)
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+TIC_OBJS = \
+	mgtic$o extractor$o marklist$o pbmtools$o utils$o match$o \
+	sortmarks$o codesyms$o ppm$o lstevent$o arithcode$o codeoffsets$o bilevel$o
+
+mgtic: $(TIC_OBJS) 
+	$(LINK) $(TIC_OBJS) $(LIBS) 
+
+TICBUILD_OBJS = mgticbuild$o extractor$o marklist$o pbmtools$o utils$o
+
+mgticbuild: $(TICBUILD_OBJS)
+	$(LINK) $(TICBUILD_OBJS) $(LIBS)
+ 
+TICPRUNE_OBJS = \
+	mgticprune$o extractor$o marklist$o pbmtools$o \
+	utils$o match$o
+
+mgticprune: $(TICPRUNE_OBJS)
+	$(LINK) $(TICPRUNE_OBJS) $(LIBS)
+ 
+TICSTAT_OBJS = mgticstat$o extractor$o marklist$o pbmtools$o utils$o
+
+mgticstat: $(TICSTAT_OBJS)
+	$(LINK) $(TICSTAT_OBJS) $(LIBS) 
+ 
+TICDUMP = mgticdump$o extractor$o marklist$o pbmtools$o utils$o
+
+mgticdump: $(TICDUMP)
+	$(LINK) $(TICDUMP) $(LIBS) 
+ 
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ansi2knr: ansi2knr.o
+	$(LINK) ansi2knr.o $(LIBS)
+
+install: execinstall #maninstall
+uninstall: execuninstall manuninstall
+
+execinstall: $(EXEC)
+	for name in $(EXEC); do \
+	  $(INSTALL_PROGRAM) $$name \
+	  $(bindir)/`echo $$name | sed '$(transform)'`; \
+	done
+
+execuninstall:
+	for name in $(EXEC); do \
+	 rm -f $(bindir)/`echo $$name | sed '$(transform)'`; \
+	done
+
+maninstall: $(MAN)
+	$(top_srcdir)/mkinstalldirs $(mandir); \
+	for f in $(MAN); do \
+	  $(INSTALL_DATA) $$f $(mandir)/$$f ;\
+	done
+
+manuninstall: $(MAN)
+	for f in $(MAN); do \
+	  rm -f $(mandir)/$$f ;\
+	done
+
+
+mostlyclean:
+	rm -f *$o _*.c _*.o *._c *._o core core.*
+ 
+clean: mostlyclean
+	rm -f $(EXEC)
+ 
+distclean: clean
+	rm -f ansi2knr
+	rm -f Makefile
+ 
+maintainer-clean: distclean
+	@echo "This command is intended only for maintainers to use;"
+	@echo "rebuilding the deleted files may require special tools."
+ 
+dist: $(DISTFILES)
+	for file in $(DISTFILES); do \
+	  ln $(srcdir)/$$file $(distdir) 2> /dev/null \
+	  || cp -p $(srcdir)/$$file $(distdir); \
+	done
+
+# screws up distclean (jrm21) 
+#Makefile: Makefile.in ../../../../config.status
+#	cd ../../../.. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
+ 
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /indexers/branches/3.03a/mg/src/images/WIN32.MAK
===================================================================
--- /indexers/branches/3.03a/mg/src/images/WIN32.MAK	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/WIN32.MAK	(revision 14757)
@@ -0,0 +1,189 @@
+# Generated automatically from Makefile.in by configure.
+###########################################################################
+#
+# Makefile.in -- Makefile for the MG system
+# Copyright (C) 1994  Neil Sharman
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#       @(#)Makefile.in	1.10 22 Mar 1994
+#
+###########################################################################
+
+MGHOME = ..\..
+# for now put executables in indexers/bin
+INSTALLDIR = ..\..\..\bin
+
+CC = cl
+CPPFLAGS = 
+DEFS = -DHAVE_CONFIG_H -D__WIN32__ -D_LITTLE_ENDIAN
+INCLUDES = -I"." -I"$(MGHOME)" -I"$(MGHOME)\lib"
+LDFLAGS =
+LIBS = $(MGHOME)\lib\libmglib.lib 
+ 
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES)
+LINK = $(CC) $(LDFLAGS)
+
+.SUFFIXES:
+.SUFFIXES: .c .obj
+.c.obj:
+	$(COMPILE) $<
+ 
+o = .obj
+e = .exe
+
+ 
+HEADERS = \
+  arithcode.h     codeoffsets.h   marklist.h      sortmarks.h \
+  basictypes.h    codesyms.h      match.h         utils.h     \
+  bilevel.h       extractor.h     pbmtools.h      model.h
+
+
+SOURCES = \
+  arithcode.c     extractor.c     mgbilevel.c     mgticdump.c     utils.c \
+  bilevel.c       felics.c        mgfelics.c      mgticprune.c    mgticstat.c\
+  codeoffsets.c   marklist.c      mgtic.c         pbmtools.c      lstevent.c \
+  codesyms.c      match.c         mgticbuild.c    sortmarks.c     ppm.c  
+
+
+
+MISC          = Makefile.in 
+
+ALLFILES      =	$(SOURCES) $(HEADERS) $(MISC) $(MAN)
+
+DISTFILES     = $(ALLFILES) 
+
+EXEC          = mgfelics$e mgbilevel$e mgtic$e mgticbuild$e mgticprune$e mgticstat$e \
+                mgticdump$e
+
+MAN           = mgfelics.1 mgbilevel.1 mgtic.1 mgticbuild.1  mgticprune.1 \
+                mgticstat.1 mgticdump.1
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+all: $(EXEC)
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+FELICS_OBJS = felics$o mgfelics$o utils$o
+
+mgfelics$e: $(FELICS_OBJS)
+	$(LINK) $(FELICS_OBJS) $(LIBS)
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+BILEVEL_OBJS = \
+	arithcode$o bilevel$o extractor$o marklist$o mgbilevel$o \
+	pbmtools$o utils$o
+            
+mgbilevel$e: $(BILEVEL_OBJS)
+	$(LINK) $(BILEVEL_OBJS) $(LIBS)
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+TIC_OBJS = \
+	mgtic$o extractor$o marklist$o pbmtools$o utils$o match$o \
+	sortmarks$o codesyms$o ppm$o lstevent$o arithcode$o codeoffsets$o bilevel$o
+
+mgtic$e: $(TIC_OBJS) 
+	$(LINK) $(TIC_OBJS) $(LIBS) 
+
+TICBUILD_OBJS = mgticbuild$o extractor$o marklist$o pbmtools$o utils$o
+
+mgticbuild$e: $(TICBUILD_OBJS)
+	$(LINK) $(TICBUILD_OBJS) $(LIBS)
+ 
+TICPRUNE_OBJS = \
+	mgticprune$o extractor$o marklist$o pbmtools$o \
+	utils$o match$o
+
+mgticprune$e: $(TICPRUNE_OBJS)
+	$(LINK) $(TICPRUNE_OBJS) $(LIBS)
+ 
+TICSTAT_OBJS = mgticstat$o extractor$o marklist$o pbmtools$o utils$o
+
+mgticstat$e: $(TICSTAT_OBJS)
+	$(LINK) $(TICSTAT_OBJS) $(LIBS) 
+ 
+TICDUMP = mgticdump$o extractor$o marklist$o pbmtools$o utils$o
+
+mgticdump$e: $(TICDUMP)
+	$(LINK) $(TICDUMP) $(LIBS) 
+ 
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+#ansi2knr: ansi2knr.o
+#	$(LINK) ansi2knr.o $(LIBS)
+#
+install: execinstall maninstall
+uninstall: execuninstall manuninstall
+
+#execinstall: $(EXEC)
+#	$(top_srcdir)/mkinstalldirs $(bindir); \
+#	for name in $(EXEC); do \
+#	  $(INSTALL_PROGRAM) $$name \
+#	  $(bindir)/`echo $$name | sed '$(transform)'`; \
+#	done
+
+#execuninstall:
+#	for name in $(EXEC); do \
+#	 rm -f $(bindir)/`echo $$name | sed '$(transform)'`; \
+#	done
+
+maninstall: $(MAN)
+	$(top_srcdir)/mkinstalldirs $(mandir); \
+	for f in $(MAN); do \
+	  $(INSTALL_DATA) $$f $(mandir)/$$f ;\
+	done
+
+manuninstall: $(MAN)
+	for f in $(MAN); do \
+	  rm -f $(mandir)/$$f ;\
+	done
+
+
+mostlyclean:
+	if exist *$o del *$o
+	if exist  _*.c del  _*.c
+	if exist _*.o  del  _*.o 
+	if exist *._c  del *._c
+	if exist *._o  del *._o
+	if exist core  del  core
+	if exist core.* del  core.*
+ 
+clean: mostlyclean
+	if exist *$e del *$e
+ 
+distclean: clean
+	del ansi2knr
+	 
+maintainer-clean: distclean
+	@echo "This command is intended only for maintainers to use;"
+	@echo "rebuilding the deleted files may require special tools."
+ 
+#dist: $(DISTFILES)
+#	for file in $(DISTFILES); do \
+#	  ln $(srcdir)/$$file $(distdir) 2> /dev/null \
+#	  || cp -p $(srcdir)/$$file $(distdir); \
+#	done
+ 
+#Makefile: Makefile.in ../../config.status
+#	cd ../.. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
+ 
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+#.NOEXPORT:
Index: /indexers/branches/3.03a/mg/src/images/arithcode.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/arithcode.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/arithcode.c	(revision 14757)
@@ -0,0 +1,471 @@
+/**************************************************************************
+ *
+ * arithcode.c -- Arithmetic coding
+ * Copyright (C) 1994  Alistair Moffat
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * $Id$
+ *
+ **************************************************************************
+ *
+ *	Arithmetic encoding. Taken largely from Witten, Neal, Cleary,
+ *		CACM, 1987, p520.
+ *	Includes bitfiddling routines.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "arithcode.h"
+
+
+FILE *arith_in, *arith_out;
+
+/*
+   $log$
+ */
+
+static char *RCSID = "$Id$";
+
+#undef BECAREFUL
+#define INTEGRATED
+
+
+codevalue S_low = 0, S_high = 0, S_value = 0;
+long S_bitstofollow = 0;
+int S_buffer = 0, S_bitstogo = 0;
+
+long cmpbytes = 0, rawbytes = 0;
+
+#ifdef INTEGRATED
+long CountOfBitsOut;
+#endif
+
+
+/*==================================*/
+
+#define BITPLUSFOLLOW(b)		\
+{	OUTPUTBIT((b));			\
+	while (bitstofollow)		\
+	{	OUTPUTBIT(!(b));	\
+		bitstofollow -= 1;	\
+	}				\
+}
+
+#ifdef INTEGRATED
+#define OUTPUTBIT(b)			\
+{	buffer >>= 1;			\
+	if (b) buffer |= 0x80;	 	\
+	bitstogo -= 1;			\
+	if (bitstogo==0)		\
+	{	putc(buffer, arith_out);	\
+		bitstogo = 8;		\
+		cmpbytes += 1;		\
+	}				\
+	CountOfBitsOut++;		\
+}
+#else
+#define OUTPUTBIT(b)			\
+{	buffer >>= 1;			\
+	if (b) buffer |= 0x80;	 	\
+	bitstogo -= 1;			\
+	if (bitstogo==0)		\
+	{	putc(buffer, arith_out);	\
+		bitstogo = 8;		\
+		cmpbytes += 1;		\
+	}				\
+}
+#endif
+
+#define ADDNEXTINPUTBIT(v)		\
+{	if (bitstogo==0)		\
+	{	buffer = getc(arith_in);	\
+		bitstogo = 8;		\
+	}				\
+	v = (v<<1)+(buffer&1);		\
+	buffer >>= 1;			\
+	bitstogo -=1;			\
+}
+
+/*==================================*/
+
+void
+arithmetic_encode (lbnd, hbnd, totl)
+     int lbnd, hbnd, totl;
+{
+  register codevalue low, high;
+
+#ifdef BECAREFUL
+  if (!(0 <= lbnd && lbnd < hbnd && hbnd <= totl && totl < maxfrequency))
+    {
+      fprintf (stderr, "(corrupt file) coding error: %d %d %d\n", lbnd, hbnd, totl);
+      abort ();
+    }
+#endif
+
+  {
+    register codevalue range;
+    range = S_high - S_low + 1;
+    high = S_low + range * hbnd / totl - 1;
+    low = S_low + range * lbnd / totl;
+  }
+
+  {
+    register codevalue H;
+    register long bitstofollow;
+    register int buffer, bitstogo;
+
+    bitstofollow = S_bitstofollow;
+    buffer = S_buffer;
+    bitstogo = S_bitstogo;
+    H = half;
+
+    for (;;)
+      {
+	if (high < H)
+	  {
+	    BITPLUSFOLLOW (0);
+	  }
+	else if (low >= H)
+	  {
+	    BITPLUSFOLLOW (1);
+	    low -= H;
+	    high -= H;
+	  }
+	else if (low >= firstqtr && high < thirdqtr)
+	  {
+	    bitstofollow++;
+	    low -= firstqtr;
+	    high -= firstqtr;
+	  }
+	else
+	  break;
+	low += low;
+	high += high;
+	high++;
+      }
+    S_bitstofollow = bitstofollow;
+    S_buffer = buffer;
+    S_bitstogo = bitstogo;
+    S_low = low;
+    S_high = high;
+  }
+}
+
+/*==================================*/
+
+/* Made into a macro 
+
+   codevalue
+   arithmetic_decode_target(totl)
+   register int totl;
+   {    return (((S_value-S_low+1)*totl-1) / (S_high -S_low+1));
+   } 
+ */
+
+/*==================================*/
+
+void
+arithmetic_decode (lbnd, hbnd, totl)
+     int lbnd, hbnd, totl;
+{
+  register codevalue low, high;
+
+#ifdef BECAREFUL
+  if (!(0 <= lbnd && lbnd < hbnd && hbnd <= totl && totl < maxfrequency))
+    {
+      fprintf (stderr, "(corrupt file) coding error: %d %d %d\n", lbnd, hbnd, totl);
+      abort ();
+    }
+#endif
+
+  {
+    register codevalue range;
+    range = S_high - S_low + 1;
+    high = S_low + range * hbnd / totl - 1;
+    low = S_low + range * lbnd / totl;
+  }
+
+  {
+    register codevalue value, H;
+    register int buffer, bitstogo;
+
+    buffer = S_buffer;
+    bitstogo = S_bitstogo;
+    H = half;
+    value = S_value;
+
+    for (;;)
+      {
+	if (high < H)
+	  {			/* nothing */
+	  }
+	else if (low >= H)
+	  {
+	    value -= H;
+	    low -= H;
+	    high -= H;
+	  }
+	else if (low >= firstqtr && high < thirdqtr)
+	  {
+	    value -= firstqtr;
+	    low -= firstqtr;
+	    high -= firstqtr;
+	  }
+	else
+	  break;
+	low += low;
+	high += high;
+	high += 1;
+	ADDNEXTINPUTBIT (value);
+      }
+    S_buffer = buffer;
+    S_bitstogo = bitstogo;
+    S_low = low;
+    S_high = high;
+    S_value = value;
+  }
+}
+
+/*==================================*/
+
+
+static void
+startoutputingbits ()
+{
+  S_buffer = 0;
+  S_bitstogo = 8;
+}
+
+static void
+startinputingbits ()
+{
+  S_buffer = 0;
+  S_bitstogo = 0;
+}
+
+static void
+doneoutputingbits ()
+{				/* write another byte if necessary */
+  if (S_bitstogo < 8)
+    {
+      putc (S_buffer >> S_bitstogo, arith_out);
+      cmpbytes += 1;
+    }
+}
+
+/*==================================*/
+
+static void
+startencoding ()
+{
+  S_low = 0;
+  S_high = topvalue;
+  S_bitstofollow = 0;
+}
+
+static void
+startdecoding ()
+{
+  register int i;
+  register int buffer, bitstogo;
+  S_low = 0;
+  S_high = topvalue;
+  S_value = 0;
+  bitstogo = S_bitstogo;
+  buffer = S_buffer;
+  for (i = 0; i < codevaluebits; i++)
+    ADDNEXTINPUTBIT (S_value);
+  S_bitstogo = bitstogo;
+  S_buffer = buffer;
+}
+
+static void
+doneencoding ()
+{
+  register long bitstofollow;
+  register int buffer, bitstogo;
+  bitstofollow = S_bitstofollow;
+  buffer = S_buffer;
+  bitstogo = S_bitstogo;
+  bitstofollow += 1;
+  if (S_low < firstqtr)
+    {
+      BITPLUSFOLLOW (0);
+    }
+  else
+    {
+      BITPLUSFOLLOW (1);
+    }
+  S_bitstofollow = bitstofollow;
+  S_buffer = buffer;
+  S_bitstogo = bitstogo;
+}
+
+
+
+void 
+EncodeGammaDist (int Off)
+/* Encode Off with probability distribution derived from the Elias gamma distribution. */
+{
+  int Len, i;
+
+  Off++;
+  for (Len = 31; Len >= 0 && !(Off & (1 << Len)); Len--);
+
+  for (i = Len; i >= 0; i--)
+    arithmetic_encode (0, 1, 2);
+  arithmetic_encode (1, 2, 2);
+
+  for (i = Len - 1; i >= 0; i--)
+    if (Off & (1 << i))
+      arithmetic_encode (1, 2, 2);
+    else
+      arithmetic_encode (0, 1, 2);
+}
+
+
+
+int 
+DecodeGammaDist ()
+/* Decode next Off using probability distribution derived from the Elias gamma distribution. Inverse of EncodeGammaDist. */
+{
+  int i = 1, Len = 0, bit;
+
+  do
+    {
+      bit = arithmetic_decode_target (2) < 1 ? 0 : 1;
+      if (bit)
+	arithmetic_decode (1, 2, 2);
+      else
+	{
+	  arithmetic_decode (0, 1, 2);
+	  Len++;
+	}
+    }
+  while (!bit);
+
+  Len--;
+  while (Len-- > 0)
+    {
+      bit = arithmetic_decode_target (2) < 1 ? 0 : 1;
+      if (bit)
+	arithmetic_decode (1, 2, 2);
+      else
+	arithmetic_decode (0, 1, 2);
+      i = (i << 1) | bit;
+    }
+  return (i - 1);
+}
+
+
+
+
+
+void 
+EncodeGammaSigned (int snum, int *pos, int *neg)
+{
+  if (snum >= 0)
+    arithmetic_encode (0, *pos, *pos + (*neg)), (*pos)++;
+  else
+    arithmetic_encode (*pos, *pos + (*neg), *pos + (*neg)), (*neg)++;
+  if (*pos + (*neg) >= maxfrequency)
+    {
+      *pos = (*pos + 1) / 2;
+      *neg = (*neg + 1) / 2;
+    }
+  EncodeGammaDist (abs (snum));
+}
+
+
+int 
+DecodeGammaSigned (int *pos, int *neg)
+{
+  int signedpos = 1;
+  if (arithmetic_decode_target (*pos + (*neg)) < *pos)
+    arithmetic_decode (0, *pos, *pos + (*neg)), (*pos)++;
+  else
+    arithmetic_decode (*pos, *pos + (*neg), *pos + (*neg)), (*neg)++, signedpos = 0;
+
+  if (*pos + (*neg) >= maxfrequency)
+    {
+      *pos = (*pos + 1) / 2;
+      *neg = (*neg + 1) / 2;
+    }
+
+  if (signedpos)
+    return DecodeGammaDist ();
+  else
+    return (-DecodeGammaDist ());
+}
+
+
+void 
+InitArithEncoding (void)
+{
+  S_low = 0, S_high = 0, S_value = 0;
+  S_bitstofollow = 0;
+  S_buffer = 0, S_bitstogo = 0;
+  cmpbytes = 0, rawbytes = 0;
+
+  startoutputingbits ();
+  startencoding ();
+}
+
+void 
+InitArithDecoding (void)
+{
+  S_low = 0, S_high = 0, S_value = 0;
+  S_bitstofollow = 0;
+  S_buffer = 0, S_bitstogo = 0;
+  cmpbytes = 0, rawbytes = 0;
+
+  startinputingbits ();
+  startdecoding ();
+}
+
+void 
+CloseDownArithEncoding (void)
+{
+  doneencoding ();
+  doneoutputingbits ();
+}
+
+void 
+CloseDownArithDecoding (void)
+{
+}
+
+
+
+
+
+/* encode that famous number, 42 uses 12 bits */
+void 
+EncodeChecksum ()
+{
+  EncodeGammaDist (42);
+}
+
+void 
+DecodeChecksum (char str[])
+{
+  if (DecodeGammaDist () != 42)
+    {
+      fprintf (stderr, "%s: checksum error, file corrupt.\n", str);
+      exit (1);
+    }
+}
Index: /indexers/branches/3.03a/mg/src/images/arithcode.h
===================================================================
--- /indexers/branches/3.03a/mg/src/images/arithcode.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/arithcode.h	(revision 14757)
@@ -0,0 +1,78 @@
+/**************************************************************************
+ *
+ * arithcode.h -- Arithmetic coding
+ * Copyright (C) 1994  Alistair Moffat
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef _arithcode_h
+#define _arithcode_h
+
+extern FILE *arith_in, *arith_out;
+
+#define codevaluebits 16
+#if (codevaluebits<16)
+typedef unsigned short codevalue;
+#else
+typedef unsigned long codevalue;
+#endif
+
+#define topvalue ((codevalue)((1<<codevaluebits)-1))
+#define maxfrequency ((topvalue+1)/4 + 1)
+
+#define firstqtr (topvalue/4+1)
+#define half     (2*firstqtr)
+#define thirdqtr (3*firstqtr)
+
+#define	escape_event	U->totalcnt-U->notfound, U->totalcnt, U->totalcnt
+
+void arithmetic_encode ();
+codevalue arithmetic_decode_target ();
+
+#define	arithmetic_decode_target(totl)	\
+	(  ((S_value-S_low+1)*(totl)-1) / (S_high-S_low+1)  )
+
+void arithmetic_decode ();
+
+
+extern codevalue S_low, S_high, S_value;
+extern long S_bitstofollow;
+extern int S_buffer, S_bitstogo;
+
+extern long cmpbytes, rawbytes;
+
+extern long CountOfBitsOut;
+
+void EncodeGammaDist (int Off);
+int DecodeGammaDist ();
+
+void EncodeGammaSigned (int snum, int *pos, int *neg);
+int DecodeGammaSigned (int *pos, int *neg);
+
+
+void InitArithEncoding (void);
+void InitArithDecoding (void);
+
+void CloseDownArithEncoding (void);
+void CloseDownArithDecoding (void);
+
+void EncodeChecksum ();
+void DecodeChecksum (char str[]);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/images/basictypes.h
===================================================================
--- /indexers/branches/3.03a/mg/src/images/basictypes.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/basictypes.h	(revision 14757)
@@ -0,0 +1,34 @@
+/**************************************************************************
+ *
+ * basictypes.h -- base data types
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************
+ *
+ * This file contains information relating to the base data types
+ *
+ **************************************************************************/
+
+#ifndef __basictypes_h
+#define __basictypes_h
+
+typedef unsigned long Pixel;
+
+
+#endif
Index: /indexers/branches/3.03a/mg/src/images/bilevel.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/bilevel.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/bilevel.c	(revision 14757)
@@ -0,0 +1,747 @@
+/**************************************************************************
+ *
+ * bilevel.c -- Compress a bilevel bitmap
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************
+ *
+ *  
+ *  
+ *  This is the code used to compress a bitmap.  The template is given in
+ *  the following format. 
+ *   '.'  = pixel not used
+ *   'p'  = pixel used in 1st order context (the superset)
+ *   '2'  = pixel used in 2nd order context (the subset)
+ *   ';'  = marker used to denote the end of a row in the template
+ *   '*'  = the current context pixel.
+ *  for instance, the common 22/10 template would be shown as:
+ *     ".ppppp.;"
+ *     "pp222pp;"
+ *     "p22222p;"
+ *     "p22*...;"
+ * 
+ **************************************************************************/
+
+
+#include "sysfuncs.h"
+
+#include "bilevel.h"
+#include "extractor.h"
+#include "pbmtools.h"
+#include "marklist.h"
+#include "arithcode.h"
+#include "utils.h"
+
+
+
+#define INITVALUE 2
+#define INCREMENT 4
+
+#define MAX_T_W 32
+
+/* note memory usage is 2*TEMPLATESIZE*sizeof(prob), which is currently 4.9 Mb */
+#define TEMPLATESIZE 612317
+
+
+#define HASH(x) ((x)%TEMPLATESIZE)
+
+
+typedef struct
+  {
+    unsigned short s, n;
+  }
+prob;				/* set and notset */
+typedef struct
+  {
+    short int x, y;
+  }
+coordinate;
+
+coordinate MM[MAX_T_W][MAX_T_W];	/* the actual (x,y) positions */
+unsigned int MMcount[MAX_T_W];	/* number of bits in this row of the template */
+unsigned int MMmask[MAX_T_W];	/* the "current" mask value */
+unsigned int MMbits[MAX_T_W];	/* the bitmask to mask out higher bits */
+unsigned int MMrows;		/* total number of rows */
+unsigned int MM2level[MAX_T_W];	/* bitmask to calculate the 2nd level mask */
+int twolevel, curr_row, surr;
+
+prob *P = NULL;			/* probability array, up to N bits */
+prob *P2 = NULL;
+
+void 
+bl_clearmodel ()
+{
+  int i;
+
+  P = (prob *) malloc (TEMPLATESIZE * sizeof (prob));
+  if (!P)
+    error_msg ("bl_clearmodel()", "not enough memory.", "");
+
+  P2 = (prob *) malloc (TEMPLATESIZE * sizeof (prob));
+  if (!P2)
+    error_msg ("bl_clearmodel()", "not enough memory.", "");
+
+  for (i = 0; i < TEMPLATESIZE; i++)
+    {
+      P[i].s = P[i].n = INITVALUE;
+      P2[i].s = P2[i].n = INITVALUE;
+    }
+}
+
+
+void 
+bl_freemodel ()
+{
+  free (P);
+  free (P2);
+}
+
+
+
+
+#define update_counts(p, pixel)                        \
+    pixel ? (p->s+=INCREMENT) : (p->n+=INCREMENT);     \
+                                                       \
+    if(p->s+p->n >= (unsigned)(maxfrequency)) {        \
+       p->s=(p->s+1)/(unsigned)2;                      \
+       p->n=(p->n+1)/(unsigned)2;                      \
+    }
+
+
+
+
+/* mask is the bigger one, mask2l is smaller one */
+static void 
+bl_encode_in_context (unsigned long mask, unsigned long mask2l, unsigned long pixel)
+{
+  register int twol, t;
+  prob *p = &P[mask];
+  prob *p2 = &P2[mask2l];
+
+  twol = twolevel && (p->s + p->n < (unsigned) (2 * INITVALUE + 5 * INCREMENT));
+
+  t = twol ? (p2->s + p2->n) : (p->s + p->n);
+
+  if (twol == 0)
+    {
+      if (pixel)
+	arithmetic_encode (0, p->s, t);
+      else
+	arithmetic_encode (p->s, t, t);
+      update_counts (p, pixel);
+    }
+  else
+    {
+      if (pixel)
+	arithmetic_encode (0, p2->s, t);
+      else
+	arithmetic_encode (p2->s, t, t);
+      update_counts (p2, pixel);
+      update_counts (p, pixel);
+    }
+}
+
+
+static void 
+bl_decode_in_context (unsigned long mask, unsigned long mask2l, unsigned long *val)
+{
+  register int twol, pixel, t;
+  prob *p = &P[mask];
+  prob *p2 = &P2[mask2l];
+
+
+  if (twolevel && (p->s + p->n < (unsigned) (2 * INITVALUE + 5 * INCREMENT)))
+    {
+      pixel = arithmetic_decode_target (p2->s + p2->n) < p2->s, twol = 1;
+    }
+  else
+    {
+      pixel = arithmetic_decode_target (p->s + p->n) < p->s, twol = 0;
+    }
+
+  t = twol ? (p2->s + p2->n) : (p->s + p->n);
+
+  if (twol == 0)
+    {
+      if (pixel)
+	arithmetic_decode (0, p->s, t);
+      else
+	arithmetic_decode (p->s, t, t);
+      update_counts (p, pixel);
+    }
+  else
+    {
+      if (pixel)
+	arithmetic_decode (0, p2->s, t);
+      else
+	arithmetic_decode (p2->s, t, t);
+      update_counts (p2, pixel);
+      update_counts (p, pixel);
+    }
+
+  *val = pixel;
+}
+
+static void 
+bl_string_to_array (char inputstr[], char parsestr[], int *w, int *h)
+{
+  int r, c;
+  int i, j, lastc, p, l;
+  int xc, yc;
+  int foundstatus;
+
+  surr = twolevel = 0;
+  for (i = 0; i < MAX_T_W; i++)
+    MMcount[i] = MM2level[i] = 0;
+  MMrows = 0;
+
+  for (i = 0; i < (int) strlen (inputstr); i++)
+    {
+      p = inputstr[i];
+      if ((p != '.') && (p != '2') && (p != '*') && (p != 'p') && (p != ';'))
+	{
+	  fprintf (stderr, "Template string can only contain [.p2*;], not \"%c\".\n", inputstr[i]);
+	  exit (1);
+	}
+    }
+
+  /* get the width and height, test rectangularity... */
+  parsestr[l = 0] = 0;
+  for (c = 0, r = 0, lastc = -1, p = 0; p < (int) strlen (inputstr); p++)
+    {
+      if ((inputstr[p] == ';'))
+	{
+	  r++;
+	  if (lastc != -1)
+	    {			/* this is the 2nd row at least */
+	      if (lastc != c)
+		{
+		  fprintf (stderr, "The rows have to be the same width. "
+			   "Row %d has width %d (previous row has width %d)\n", r, c, lastc);
+		  exit (1);
+		}
+	    }
+	  lastc = c;
+	  c = 0;
+	}
+      else
+	{
+	  c++;
+	  parsestr[l] = inputstr[p];
+	  parsestr[++l] = 0;
+	}
+    }
+
+  if (c != 0)
+    lastc = c;
+  *w = lastc;
+  *h = r;
+  if ((*w) <= 0)
+    {
+      fprintf (stderr, "Must have at least one column!\n");
+      exit (1);
+    }
+  if ((*h) <= 0)
+    {
+      fprintf (stderr, "Must have at least one row! Terminate each row with a ';'\n");
+      exit (1);
+    }
+  if ((*w > MAX_T_W) || (*h > MAX_T_W))
+    {
+      fprintf (stderr, "template size bigger than internal threshold of %d\n", MAX_T_W);
+      exit (1);
+    }
+
+  /* get the (x,y) position of the current (*) pixel */
+  for (xc = -1, yc = 0, i = 0; i < *w; i++)
+    for (j = 0; j < *h; j++)
+      if (parsestr[j * (*w) + i] == '*')
+	{
+	  if (xc >= 0)
+	    {
+	      fprintf (stderr, "There can only be ONE current ('*') pixel.\n");
+	      exit (1);
+	    }
+	  xc = i;
+	  yc = j;
+	  curr_row = j + 1;
+	}
+  if (xc < 0)
+    error_msg ("bl_string_to_array", "Error in mask, no current ('*') pixel.", "");
+  /* found the position (xc,yc) */
+
+
+  /* convert parsestr[] into a MM[][] structure */
+  for (j = 0; j < *h; j++)
+    {
+      foundstatus = 0;
+      for (i = 0; i < *w; i++)
+	{
+	  p = j * (*w) + i;
+	  if ((parsestr[p] == 'p') || (parsestr[p] == '2'))
+	    {
+	      if (!foundstatus)
+		foundstatus = 1;
+	      MM2level[j] = MM2level[j] * 2 | (parsestr[p] == '2');
+	      if (parsestr[p] == '2')
+		twolevel = 1;
+
+	      MM[j][MMcount[j]].x = i - xc;
+	      MM[j][MMcount[j]++].y = j - yc;
+	      if (((i - xc) >= 0) && ((j - yc) >= 0))
+		surr = 1;
+	    }
+	  else
+	    {
+	      if (foundstatus == 1)
+		foundstatus = 2;
+	    }
+
+	}
+      if (foundstatus)
+	MMrows++;
+      MMbits[j] = (1 << MMcount[j]) - 1;
+    }
+
+  /* reverse matrix, so [][0] is the closest to the right */
+  {
+    coordinate temp;
+    for (i = 0; i < MMrows; i++)
+      for (j = 0; j < MMcount[i] / (unsigned) 2; j++)
+	{
+	  temp = MM[i][MMcount[i] - 1 - j];
+	  MM[i][MMcount[i] - 1 - j] = MM[i][j];
+	  MM[i][j] = temp;
+	}
+  }
+}
+
+
+
+
+
+
+
+
+void 
+bl_writetemplate (char inputstr[])
+{
+  register int i, j;
+  int w, h;
+  char ind[255];
+  char *str;
+
+  str = (char *) malloc (strlen (inputstr) * sizeof (char) + 2);
+
+  bl_string_to_array (inputstr, str, &w, &h);
+
+  EncodeGammaDist (surr);
+  EncodeGammaDist (w);
+  EncodeGammaDist (h);
+  ind['.'] = 0;
+  ind['p'] = 1;
+  ind['2'] = 2;
+  ind['*'] = 3;
+  for (j = 0; j < h; j++)
+    for (i = 0; i < w; i++)
+      EncodeGammaDist (ind[(int) str[j * w + i]]);
+
+  free (str);
+}
+
+
+void 
+bl_readtemplate ()
+{
+  register int i, j;
+  int w, h, p;
+  char ind[4];
+  char *inputstr, *str;
+
+  surr = DecodeGammaDist (surr);
+  if (surr)
+    {
+      fprintf (stderr, "It's fine compressing an image using a 'surrounding' template, but I can't "
+	       "decompress it!\n");
+      exit (1);
+    }
+  w = DecodeGammaDist ();
+  h = DecodeGammaDist ();
+
+  inputstr = (char *) malloc ((w + 2) * h * sizeof (char) + 2);
+  ind[0] = '.';
+  ind[1] = 'p';
+  ind[2] = '2';
+  ind[3] = '*';
+  for (p = 0, j = 0; j < h; j++)
+    {
+      for (i = 0; i < w; i++)
+	{
+	  inputstr[p++] = ind[DecodeGammaDist ()];
+	}
+      inputstr[p++] = ';';
+      inputstr[p] = 0;
+    }
+
+  str = (char *) malloc (strlen (inputstr) * sizeof (char) + 2);
+  bl_string_to_array (inputstr, str, &w, &h);
+}
+
+
+
+
+
+/* Currently if there are more than 32 bits, the topmost 32 will be discarded, if the 
+   topbits are to be used in compression, define _MORETHAN32 */
+#undef _MORETHAN32
+
+void 
+bl_compress_mark (marktype d)
+{
+  register int r, c;
+  register int i, j;
+  register unsigned long mask, mask2level;
+  char *array[MAX_T_W];
+
+
+  for (i = 0; i < MAX_T_W; i++)
+    {
+      array[i] = (char *) calloc ((size_t) d.w + 2 * MAX_T_W + 1, (size_t) sizeof (char));
+      array[i] = array[i] + MAX_T_W;
+    }
+
+  EncodeGammaDist (d.w);
+  EncodeGammaDist (d.h);
+
+  for (r = 0; r < min (curr_row, d.h); r++)
+    for (c = 0; c < d.w; c++)
+      array[r % MAX_T_W][c] = pbm_getpixel (d.bitmap, c, r);
+
+  for (r = 0; r < d.h; r++)
+    {
+      if (V)
+	if (r && (r % 200 == 0))
+	  fprintf (stderr, ".");
+
+      if (r + curr_row < d.h)
+	for (c = 0; c < d.w; c++)
+	  array[(r + curr_row) % MAX_T_W][c] = pbm_getpixel (d.bitmap, c, r + curr_row);
+      else
+	for (c = 0; c < d.w; c++)
+	  array[(r + curr_row) % MAX_T_W][c] = 0;
+
+      for (c = 0; c < d.w; c++)
+	{
+	  for (mask = 0, mask2level = 0, i = 0; i < MMrows; i++)
+	    {
+	      if (c != 0)
+		{
+		  MMmask[i] = (MMmask[i] * 2);
+		  MMmask[i] |= array[(r + MM[i][0].y + MAX_T_W) % MAX_T_W][c + MM[i][0].x];
+		}
+	      else
+		{
+		  for (MMmask[i] = 0, j = MMcount[i] - 1; j >= 0; j--)
+		    MMmask[i] = 2 * MMmask[i] | array[(r + MM[i][j].y + MAX_T_W) % MAX_T_W][c + MM[i][j].x];
+		}
+	      MMmask[i] &= MMbits[i];
+#ifdef _MORETHAN32
+	      mask = ((mask * 8191) << MMcount[i]) | MMmask[i];
+	      mask2level = ((mask2level * 499) << MMcount[i]) | (MMmask[i] & MM2level[i]);
+#else
+	      mask = (mask << MMcount[i]) | MMmask[i];
+	      mask2level = (mask2level << MMcount[i]) | (MMmask[i] & MM2level[i]);
+#endif
+	    }
+
+	  mask = HASH (mask);
+	  mask2level = HASH (mask2level);
+
+	  bl_encode_in_context (mask, mask2level, pbm_getpixel (d.bitmap, c, r));
+	}
+    }
+  for (i = 0; i < MAX_T_W; i++)
+    free (array[i] - MAX_T_W);
+}
+
+
+
+void 
+bl_decompress_mark (marktype * d)
+{
+  register int r, c;
+  register int i, j;
+  unsigned long pix;
+  register unsigned long mask, mask2level;
+  char *array[MAX_T_W];
+
+
+  d->w = DecodeGammaDist ();
+  d->h = DecodeGammaDist ();
+
+  d->bitmap = pbm_allocarray (d->w, d->h);
+  for (i = 0; i < MAX_T_W; i++)
+    {
+      array[i] = (char *) calloc ((size_t) d->w + 2 * MAX_T_W + 1, (size_t) sizeof (char));
+      array[i] = array[i] + MAX_T_W;
+    }
+
+  for (r = 0; r < d->h; r++)
+    {
+      if (V)
+	if (r && (r % 200 == 0))
+	  fprintf (stderr, ".");
+      for (c = 0; c < d->w; c++)
+	array[r % MAX_T_W][c] = pbm_getpixel (d->bitmap, c, r);
+      for (c = 0; c < d->w; c++)
+	{
+	  for (mask = 0, mask2level = 0, i = 0; i < MMrows; i++)
+	    {
+	      if (c != 0)
+		{
+		  MMmask[i] = (MMmask[i] * 2);
+		  MMmask[i] |= array[(r + MM[i][0].y + MAX_T_W) % MAX_T_W][c + MM[i][0].x];
+		}
+	      else
+		{
+		  for (MMmask[i] = 0, j = MMcount[i] - 1; j >= 0; j--)	/* get all pixels */
+		    MMmask[i] = 2 * MMmask[i] | array[(r + MM[i][j].y + MAX_T_W) % MAX_T_W][c + MM[i][j].x];
+		}
+	      MMmask[i] &= MMbits[i];
+
+#ifdef _MORETHAN32
+	      mask = ((mask * 8191) << MMcount[i]) | MMmask[i];
+	      mask2level = ((mask2level * 499) << MMcount[i]) | (MMmask[i] & MM2level[i]);
+#else
+	      mask = (mask << MMcount[i]) | MMmask[i];
+	      mask2level = (mask2level << MMcount[i]) | (MMmask[i] & MM2level[i]);
+#endif
+	    }
+
+	  mask = HASH (mask);
+	  mask2level = HASH (mask2level);
+
+	  bl_decode_in_context (mask, mask2level, &pix);
+	  if (pix)
+	    {
+	      pbm_putpixel (d->bitmap, c, r, pix);
+	      array[r % MAX_T_W][c] = pix;
+	    }
+	}
+    }
+  for (i = 0; i < MAX_T_W; i++)
+    free (array[i] - MAX_T_W);
+}
+
+
+
+void 
+bl_compress (marktype d, char inputstr[])
+{
+  bl_clearmodel ();
+  bl_writetemplate (inputstr);
+  bl_compress_mark (d);
+  bl_freemodel ();
+}
+
+
+void 
+bl_decompress (marktype * d)
+{
+  bl_clearmodel ();
+  bl_readtemplate ();
+  bl_decompress_mark (d);
+  bl_freemodel ();
+}
+
+
+
+
+
+
+/* 
+   The bitmap in d2, can be examined clairvoyantly.  The ordering of the
+   params is therefore non-clairvoyant, and clairvoyant in that order.
+
+ */
+/*
+   coordinate M1[6]={        { 0,-2},
+   {-1,-1},{ 0,-1}, {1,-1},
+   {-2,0},  {-1, 0}};
+   };
+   coordinate M2[13]={       { 0,-2},
+   {-1,-1}, { 0,-1},   {1, -1},
+   {-2,0}, {-1, 0}, { 0, 0},   { 1, 0},  {2,0},
+   {-1, 1}, { 0, 1},   { 1, 1},
+   { 0, 2}
+ */
+
+coordinate M1[6] =
+{
+  {0, -2},
+  {-2, 0},
+  {1, -1},
+  {-1, -1},
+  {0, -1},
+  {-1, 0}};
+coordinate M2[13] =
+{
+  {0, -2},
+  {1, -1},
+  {-2, 0},
+  {2, 0},
+  {-1, 1},
+  {1, 1},
+  {0, 2},
+  {-1, -1},
+  {0, -1},
+  {1, 0},
+  {-1, 0},
+  {0, 1},
+  {0, 0}
+};
+#define M1S 6
+#define M1S_2level 3
+#define M2S 13
+#define M2S_2level 6
+
+
+void 
+bl_clair_compress (marktype d1, marktype d2)
+{
+  register int r, c;
+  register int i, j, n;
+  register unsigned long mask, mask2level = 0;
+  int cols, rows;
+  int gap;
+  Pixel **b1, **b2;
+
+
+  bl_clearmodel ();
+  twolevel = 1;
+
+  b1 = d1.bitmap;
+  b2 = d2.bitmap;
+  cols = d1.w;
+  rows = d1.h;
+
+  gap = max (50, rows / 10);
+
+  EncodeGammaDist (cols);
+  EncodeGammaDist (rows);
+
+  for (r = 0; r < rows; r++)
+    {
+      if (V)
+	if (!(r % gap))
+	  fprintf (stderr, ".");
+      for (c = 0; c < cols; c++)
+	{
+
+	  mask = 0;
+	  for (n = 0; n < M1S; n++)
+	    {
+	      i = c + M1[n].x;
+	      j = r + M1[n].y;
+	      mask = (2 * mask) | pbm_getpixel_trunc (b1, i, j, cols, rows);
+	    }
+
+	  mask2level = mask & ((1 << M1S_2level) - 1);
+
+	  for (n = 0; n < M2S; n++)
+	    {
+	      i = c + M2[n].x;
+	      j = r + M2[n].y;
+	      mask = (2 * mask) | pbm_getpixel_trunc (b2, i, j, cols, rows);
+	    }
+
+	  mask2level = (mask2level << M2S_2level) | (mask & ((1 << M2S_2level) - 1));
+
+	  bl_encode_in_context (mask, mask2level, pbm_getpixel (b1, c, r));
+
+	}
+    }
+  if (V)
+    fprintf (stderr, "\n");
+  bl_freemodel ();
+}
+
+
+void 
+bl_clair_decompress (marktype d1, marktype d2)
+{
+  register int r, c;
+  register int i, j, n;
+  register unsigned long mask, mask2level = 0;
+  unsigned long p;
+  int cols, rows;
+  int gap;
+  Pixel **b1, **b2;
+
+  bl_clearmodel ();
+  twolevel = 1;
+
+  b1 = d1.bitmap;
+  b2 = d2.bitmap;
+  cols = d1.w;
+  rows = d1.h;
+
+  gap = max (50, rows / 10);
+
+  i = DecodeGammaDist ();
+  j = DecodeGammaDist ();
+  if ((i != cols) || (j != rows))
+    error_msg ("bl_clair_decompress", "incorrect size of residue image", "");
+
+  if (V)
+    fprintf (stderr, "cols=%d rows=%d\n", cols, rows);
+
+  for (r = 0; r < rows; r++)
+    {
+      if (V)
+	if (!(r % gap))
+	  fprintf (stderr, ".");
+      for (c = 0; c < cols; c++)
+	{
+	  mask = 0;
+	  for (n = 0; n < M1S; n++)
+	    {
+	      i = c + M1[n].x;
+	      j = r + M1[n].y;
+	      mask = (2 * mask) | pbm_getpixel_trunc (b1, i, j, cols, rows);
+	    }
+	  mask2level = mask & ((1 << M1S_2level) - 1);
+	  for (n = 0; n < M2S; n++)
+	    {
+	      i = c + M2[n].x;
+	      j = r + M2[n].y;
+	      mask = (2 * mask) | pbm_getpixel_trunc (b2, i, j, cols, rows);
+	    }
+	  mask2level = (mask2level << M2S_2level) | (mask & ((1 << M2S_2level) - 1));
+
+
+	  bl_decode_in_context (mask, mask2level, &p);
+	  if (p)
+	    pbm_putpixel (b1, c, r, 1);
+	}
+    }
+  if (V)
+    fprintf (stderr, "\n");
+  bl_freemodel ();
+}
Index: /indexers/branches/3.03a/mg/src/images/bilevel.h
===================================================================
--- /indexers/branches/3.03a/mg/src/images/bilevel.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/bilevel.h	(revision 14757)
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * bilevel.h -- Compress a bilevel bitmap
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef __BILEVEL_H
+#define __BILEVEL_H
+
+#include "marklist.h"
+
+/* must be called before the start of de/compression */
+void bl_clearmodel ();
+void bl_freemodel ();
+
+/* writes the template to the stream, and sets up the de/compression params */
+void bl_writetemplate (char inputstr[]);
+void bl_readtemplate ();
+
+/* actually performs the de/compression */
+void bl_compress (marktype d, char str[]);
+void bl_compress_mark (marktype d);
+void bl_decompress (marktype * d);
+void bl_decompress_mark (marktype * d);
+
+/* clairvoyantly de/compress d1 with respect to clairvoyantly viewable d2 */
+void bl_clair_compress (marktype d1, marktype d2);
+void bl_clair_decompress (marktype d1, marktype d2);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/images/codeoffsets.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/codeoffsets.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/codeoffsets.c	(revision 14757)
@@ -0,0 +1,257 @@
+/**************************************************************************
+ *
+ * codeoffsets.c -- Functions which code the mark offsets
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "marklist.h"
+#include "arithcode.h"
+#include "utils.h"
+
+#define TOP_INC 2
+#define MID_INC 1
+#define BOT_INC 1
+
+
+void 
+EncodeOffsets (marklistptr symbol_list, int nsyms)
+{
+  int xpos = 1, xneg = 1, ypos = 1, yneg = 1;
+  marklistptr step;
+  int found;
+  int dox = 0, leveltop = 1, levelmid = 1, levelbot = 1;
+  elemlist xlist, ylist;	/* all previous offsets */
+  int p, f, t, xoff, yoff, symnum, count;
+  elemlist *xcond, *ycond;	/* previous offsets conditioned on symbol num */
+
+  xcond = (elemlist *) malloc (nsyms * sizeof (elemlist));
+  if (!xcond)
+    error_msg ("EncodeOffsets", "Out of memory...", "");
+  ycond = (elemlist *) malloc (nsyms * sizeof (elemlist));
+  if (!ycond)
+    error_msg ("EncodeOffsets", "Out of memory...", "");
+
+  for (t = 0; t < nsyms; t++)
+    {
+      xcond[t].head = ycond[t].head = NULL;
+      xcond[t].tot = ycond[t].tot = 0;
+    }
+  xlist.head = NULL;
+  xlist.tot = 0;
+  ylist.head = NULL;
+  ylist.tot = 0;
+  for (step = symbol_list, count = 0; step; step = step->next, count++)
+    {
+      xoff = step->data.xoffset;
+      yoff = step->data.yoffset;
+      symnum = step->data.symnum;
+      for (dox = 1; dox >= 0; dox--)
+	{
+	  /* encode the offsets, x first then y */
+
+	  if (dox)
+	    found = elem_find (&xcond[symnum], xoff, &p, &f, &t);
+	  else
+	    found = elem_find (&ycond[symnum], yoff, &p, &f, &t);
+
+	  if (found)
+	    {
+	      arithmetic_encode (0, leveltop, leveltop + levelmid + levelbot);
+	      leveltop += TOP_INC;
+	      arithmetic_encode (p, f, t);
+	    }
+	  else
+	    {
+	      if (dox)
+		found = elem_find (&xlist, xoff, &p, &f, &t);
+	      else
+		found = elem_find (&ylist, yoff, &p, &f, &t);
+
+	      if (found)
+		{
+		  arithmetic_encode (leveltop, leveltop + levelmid, leveltop + levelmid + levelbot);
+		  levelmid += MID_INC;
+		  arithmetic_encode (p, f, t);
+		}
+	      else
+		{
+		  arithmetic_encode (leveltop + levelmid, leveltop + levelmid + levelbot, leveltop + levelmid + levelbot);
+		  levelbot += BOT_INC;
+		  if (dox)
+		    EncodeGammaSigned (xoff, &xpos, &xneg);
+		  else
+		    EncodeGammaSigned (yoff, &ypos, &yneg);
+		}
+	    }
+	  if (dox)
+	    {
+	      elem_add (&xlist, xoff);
+	      elem_add (&xcond[symnum], xoff);
+	    }
+	  else
+	    {
+	      elem_add (&ylist, yoff);
+	      elem_add (&ycond[symnum], yoff);
+	    }
+
+	  if (leveltop + levelmid >= maxfrequency)
+	    {
+	      leveltop = (leveltop + 1) / 2;
+	      levelmid = (levelmid + 1) / 2;
+	      levelbot = (levelbot + 1) / 2;
+	    }
+	}
+    }
+  for (t = 0; t < nsyms; t++)
+    {
+      elem_free (&xcond[t]);
+      elem_free (&ycond[t]);
+    }
+  elem_free (&xlist);
+  elem_free (&ylist);
+  if (V)
+    fprintf (stderr, "offset models: top %d, mid %d, bot %d\n", (leveltop - 1) / TOP_INC, (levelmid - 1) / MID_INC, (levelbot - 1) / BOT_INC);
+}
+
+
+
+
+
+void 
+DecodeOffsets (marklistptr symbol_list, int nsyms)
+{
+  int xpos = 1, xneg = 1, ypos = 1, yneg = 1;
+  marklistptr step;
+  int i, target, dox;
+  int leveltop = 1, levelmid = 1, levelbot = 1;
+  elemlist xlist, ylist;
+  int p, f, t, xoff = 0, yoff = 0, symnum, count = 0;
+  elemlist *xcond, *ycond;
+
+  xcond = (elemlist *) malloc (nsyms * sizeof (elemlist));
+  if (!xcond)
+    error_msg ("EncodeOffsets", "Out of memory...", "");
+  ycond = (elemlist *) malloc (nsyms * sizeof (elemlist));
+  if (!ycond)
+    error_msg ("EncodeOffsets", "Out of memory...", "");
+
+  for (i = 0; i < nsyms; i++)
+    {
+      xcond[i].head = ycond[i].head = NULL;
+      xcond[i].tot = ycond[i].tot = 0;
+    }
+
+  xlist.head = NULL;
+  xlist.tot = 0;
+  ylist.head = NULL;
+  ylist.tot = 0;
+
+  for (step = symbol_list, count = 0; step; step = step->next, count++)
+    {
+      symnum = step->data.symnum;
+      for (dox = 1; dox >= 0; dox--)
+	{
+	  /* decode x offset first, then y */
+	  target = arithmetic_decode_target (leveltop + levelmid + levelbot);
+	  if (target < leveltop)
+	    {
+	      arithmetic_decode (0, leveltop, leveltop + levelmid + levelbot);
+	      leveltop += TOP_INC;
+
+	      if (dox)
+		i = arithmetic_decode_target (xcond[symnum].tot);
+	      else
+		i = arithmetic_decode_target (ycond[symnum].tot);
+
+	      if (dox)
+		{
+		  elem_getrange (&xcond[symnum], i, &xoff);
+		  elem_find (&xcond[symnum], xoff, &p, &f, &t);
+		}
+	      else
+		{
+		  elem_getrange (&ycond[symnum], i, &yoff);
+		  elem_find (&ycond[symnum], yoff, &p, &f, &t);
+		}
+	      arithmetic_decode (p, f, t);
+	    }
+	  else if (target < leveltop + levelmid)
+	    {
+	      arithmetic_decode (leveltop, leveltop + levelmid, leveltop + levelmid + levelbot);
+	      levelmid += MID_INC;
+
+	      if (dox)
+		i = arithmetic_decode_target (xlist.tot);
+	      else
+		i = arithmetic_decode_target (ylist.tot);
+
+	      if (dox)
+		{
+		  elem_getrange (&xlist, i, &xoff);
+		  elem_find (&xlist, xoff, &p, &f, &t);
+		}
+	      else
+		{
+		  elem_getrange (&ylist, i, &yoff);
+		  elem_find (&ylist, yoff, &p, &f, &t);
+		}
+	      arithmetic_decode (p, f, t);
+	    }
+	  else
+	    {
+	      arithmetic_decode (leveltop + levelmid, leveltop + levelmid + levelbot, leveltop + levelmid + levelbot);
+	      levelbot += BOT_INC;
+	      if (dox)
+		xoff = DecodeGammaSigned (&xpos, &xneg);
+	      else
+		yoff = DecodeGammaSigned (&ypos, &yneg);
+	    }
+
+	  if (dox)
+	    {
+	      step->data.xoffset = xoff;
+	      elem_add (&xlist, xoff);
+	      elem_add (&xcond[symnum], xoff);
+	    }
+	  else
+	    {
+	      step->data.yoffset = yoff;
+	      elem_add (&ylist, yoff);
+	      elem_add (&ycond[symnum], yoff);
+	    }
+
+	  if (leveltop + levelmid >= maxfrequency)
+	    {
+	      leveltop = (leveltop + 1) / 2;
+	      levelmid = (levelmid + 1) / 2;
+	      levelbot = (levelbot + 1) / 2;
+	    }
+	}
+    }
+  for (t = 0; t < nsyms; t++)
+    {
+      elem_free (&xcond[t]);
+      elem_free (&ycond[t]);
+    }
+  elem_free (&xlist);
+  elem_free (&ylist);
+}
Index: /indexers/branches/3.03a/mg/src/images/codeoffsets.h
===================================================================
--- /indexers/branches/3.03a/mg/src/images/codeoffsets.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/codeoffsets.h	(revision 14757)
@@ -0,0 +1,32 @@
+/**************************************************************************
+ *
+ * codeoffsets.h -- Functions which code the mark offsets
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef __CODEOFFSETS_H
+#define __CODEOFFSETS_H
+
+#include "marklist.h"
+
+void EncodeOffsets (marklistptr MarkList, int num_symbols);
+void DecodeOffsets (marklistptr MarkList, int num_symbols);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/images/codesyms.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/codesyms.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/codesyms.c	(revision 14757)
@@ -0,0 +1,96 @@
+/**************************************************************************
+ *
+ * codesyms.c -- Functions which code the symbol sequence
+ * Copyright (C) 1994  Hugh Emberson
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "arithcode.h"
+#include "marklist.h"
+#include "pbmtools.h"
+#include "utils.h"
+#include "codesyms.h"
+
+int charsetsize = 256;
+
+void 
+EncodeSymbols (marklistptr MarkList, int NSyms)
+{
+  marklistptr step;
+  unsigned short Events[PPM_CHUNK];
+  int j = 0;
+
+  charsetsize = max (NSyms, 256);
+
+  step = MarkList;
+  while (step)
+    {
+      Events[j] = step->data.symnum;
+
+      assert (Events[j] > 0 || Events[j] < (unsigned) NSyms);
+
+      j++;
+
+      if (j == PPM_CHUNK)
+	{
+	  encodestring (Events, PPM_CHUNK);
+	  j = 0;
+	}
+      step = step->next;
+    };
+
+  if (j != 0)
+    encodestring (Events, j);
+
+  encodestring (Events, 0);
+}
+
+
+marklistptr 
+DecodeSymbols (int NSyms)
+{
+  marklistptr MarkList = NULL;
+  unsigned short Events[PPM_CHUNK];
+  int j, n;
+  marktype d;
+
+  charsetsize = max (NSyms, 256);
+
+  do
+    {
+      decodestring (Events, &n);
+
+      for (j = 0; j < n; j++)
+	{
+	  d.symnum = Events[j];
+	  marklist_add (&MarkList, d);
+	}
+    }
+  while (n != 0);
+
+  return MarkList;
+}
+
+void 
+InitPPM (void)
+{
+  kbytes = 896;
+}
Index: /indexers/branches/3.03a/mg/src/images/codesyms.h
===================================================================
--- /indexers/branches/3.03a/mg/src/images/codesyms.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/codesyms.h	(revision 14757)
@@ -0,0 +1,44 @@
+/**************************************************************************
+ *
+ * codesyms.h -- Functions which code the symbol sequence
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+#ifndef _CodeSymbols_h_
+#define _CodeSymbols_h_
+
+#include "marklist.h"
+#include "arithcode.h"
+
+#ifndef FIXEDORDER
+#define FIXEDORDER	3
+#endif
+
+#define PPM_CHUNK	1024
+
+extern int kbytes;
+extern void decodestring ();
+extern void encodestring ();
+
+void EncodeSymbols (marklistptr MarkList, int NSyms);
+marklistptr DecodeSymbols (int NSyms);
+
+void InitPPM (void);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/images/extractor.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/extractor.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/extractor.c	(revision 14757)
@@ -0,0 +1,423 @@
+/**************************************************************************
+ *
+ * extractor.c -- Functions related to extracting marks
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "extractor.h"
+#include "pbmtools.h"
+#include "marklist.h"
+#include "utils.h"
+
+
+/* 
+   'splitjoined' defines whether the extractor modules tries to break
+   "seemingly" merged/joined marks.
+ */
+int splitjoined = 1;
+
+#define MAX_FILL_STACK_SIZE 10000
+
+/* RunRegionFill uses line conherence to implement a better fill
+   routine.  The stack has currently got 10000 elements, although the
+   biggest I have encountered used a maximum stack size of 1294.  usage:
+   RunRegionFill(bitmap,mark,i,j,xpos,ypos); xpos and ypos are the top
+   left corners of the mark.  */
+
+int maxst = 0, st = 0;
+struct
+  {
+    int x, y;
+  }
+a[MAX_FILL_STACK_SIZE];
+
+#define push(i,j) a[st].x=i;a[st].y=j;st++;if(st>MAX_FILL_STACK_SIZE){error_msg ("extractor/flood_fill","woooo! Fill stack overflow!","");}
+#define pop(i,j) st--;i=a[st].x;j=a[st].y
+
+void 
+RunRegionFill (Pixel ** bitmap, marktype * mark, int i, int j, int xl, int yt, int cols, int rows)
+{
+  int l, r, t, start_up, start_down;
+
+  push (i, j);
+  while (st > 0)
+    {
+      if (st > maxst)
+	maxst = st;
+
+      pop (l, j);
+      r = l;
+
+      while (pbm_getpixel (bitmap, l - 1, j))
+	l--;
+      while (pbm_getpixel (bitmap, r + 1, j))
+	r++;
+      start_up = start_down = 1;
+      for (t = min (r + 1, cols - 1); t >= max (l - 1, 0); t--)
+	{
+	  if ((t >= l) && (t <= r))
+	    {
+	      pbm_putpixel (bitmap, t, j, 0);
+
+	      if (mark)
+		pbm_putpixel (mark->bitmap, t - xl, j - yt, 1);
+	    }
+
+	  if ((j - 1 >= 0) && (pbm_getpixel (bitmap, t, j - 1)))
+	    {
+	      if (start_up)
+		{
+		  push (t, j - 1);
+		  start_up = 0;
+		}
+	    }
+	  else
+	    start_up = 1;
+	  if ((j + 1 < rows) && (pbm_getpixel (bitmap, t, j + 1)))
+	    {
+	      if (start_down)
+		{
+		  push (t, j + 1);
+		  start_down = 0;
+		}
+	    }
+	  else
+	    start_down = 1;
+	}
+    }
+}
+
+
+
+
+/*
+
+   ExtractNextMark starts at (tx,ty) and looks for a set (==1) pixel.
+   The mark is then boundary traced to give an outline {The process is a
+   4-pixel exterior check -- giving 8 way connectivity}, and then
+   RunRegionFill is used to remove the mark and set the pixels in the
+   mark.
+
+   usage: ExtractNextMark(bitmap,&marklist,&startx,&starty,int cols,int rows);
+   Defines:
+   gp - gets a pixel, but returns 0 for outside regions.
+   boundary_{x,y}comp - returns the {x,y} component of the direction.
+   dir 0=right, 1=down, 2=left, 3=up.
+ */
+
+#define gp(i,j) ( (((i)<0)||((j)<0)||((i)>=cols)||((j)>=rows))? 0 : pbm_getpixel(bitmap,(i),(j)))
+
+#define boundary_xcomp(x) (x==0?1:(x==2?-1 : 0))
+#define boundary_ycomp(x) (x==1?1:(x==3?-1 : 0))
+
+int 
+ExtractNextMark (Pixel ** bitmap, marklistptr * marklist, int *tx, int *ty, int cols, int rows)
+{
+  int i, j, xl, xr, yt, yb;
+  register int dir, tempdir;
+  marktype d;
+
+  xl = INT_MAX;
+  xr = (-1);
+  yt = INT_MAX;
+  yb = (-1);
+
+  i = *tx;
+  j = *ty;
+  if ((i < 0) || (j < 0))
+    error_msg ("ExtractNextMark()", "Stupid values for x,y in findnextmark()", "");
+  while (!pbm_getpixel (bitmap, i, j))
+    {
+      i++;
+      if (i >= cols)
+	{
+	  i = 0;
+	  j++;
+	  if (j >= rows)
+	    return 0;
+	}
+    }
+
+  *tx = i;
+  *ty = j;
+  dir = 0;
+  j = j - 1;			/* start above */
+  do
+    {
+      if (i > xr)
+	xr = i - 1;
+      if (i < xl)
+	xl = i + 1;
+      if (j < yt)
+	yt = j + 1;
+      if (j > yb)
+	yb = j - 1;
+      tempdir = (dir + 1) % 4;
+      if (gp (i + boundary_xcomp (tempdir), j + boundary_ycomp (tempdir)) == 0)
+	dir = tempdir;
+      else
+	{
+	  tempdir = dir;
+	  if (gp (i + boundary_xcomp (tempdir), j + boundary_ycomp (tempdir)) == 0)
+	    dir = tempdir;
+	  else
+	    {
+	      tempdir = (dir + 3) % 4;
+	      if (gp (i + boundary_xcomp (tempdir), j + boundary_ycomp (tempdir)) == 0)
+		dir = tempdir;
+	      else
+		dir = (dir + 2) % 4;
+	    }
+	}
+      i += boundary_xcomp (dir);
+      j += boundary_ycomp (dir);
+    }
+  while ((i != (*tx)) || (j != (*ty - 1)));
+
+  d.w = (xr - xl + 1);
+  d.h = (yb - yt + 1);
+  d.xpos = xl;
+  d.ypos = yt;
+  d.bitmap = pbm_allocarray (d.w, d.h);
+
+  RunRegionFill (bitmap, &d, *tx, *ty, xl, yt, cols, rows);
+
+  marktype_calc_features (&d, "?");
+  marklist_add (marklist, d);
+
+  *tx = *tx + 1;
+  return 1;
+}
+
+
+
+
+static void 
+normalise (float *p, int w)
+{
+  int x;
+  float mx;
+
+  mx = p[0];
+  for (x = 0; x < w; x++)
+    if (p[x] > mx)
+      mx = p[x];
+  if (mx != 0)
+    {
+      for (x = 0; x < w; x++)
+	p[x] = p[x] / mx;
+    }
+}
+
+
+
+#define MAXPROFILE 1000
+float profile[MAXPROFILE], p2[MAXPROFILE];
+
+
+static int 
+possibly_joined (marktype * d)
+{
+  float aspect;
+  int i, n, x, y;
+  int leftable, l2;
+
+
+  aspect = d->w / (float) d->h;
+
+  if ((aspect >= 1.1) || (d->w < MAXPROFILE))
+    {
+      /* examine it more closely */
+
+
+      /* set up profile[] with a vertical profile */
+      for (x = 0; x < d->w; x++)
+	{
+	  profile[x] = 0;
+	  for (y = 0; y < d->h; y++)
+	    if (pbm_getpixel (d->bitmap, x, y))
+	      profile[x]++;
+	}
+
+      /* average the profile from (up to) 3 either way */
+      for (x = 0; x < d->w; x++)
+	{
+	  n = 0;
+	  p2[x] = 0;
+	  for (i = x - 3; i <= x + 3; i++)
+	    if ((i >= 0) && (i < d->w))
+	      {
+		n++;
+		p2[x] += profile[x];
+	      }
+	  p2[x] = p2[x] / (float) n;
+	}
+      for (x = 0; x < d->w; x++)
+	profile[x] = p2[x];
+
+      /* normalise profile[] */
+      normalise (profile, d->w);
+
+      /* find a little local minimum, with profile <0.25, make p2[] either 0 or 1 */
+      for (x = 0; x < d->w; x++)
+	p2[x] = 0;
+      for (x = 3; x < d->w - 3; x++)
+	{
+	  if (((profile[x - 2] - profile[x]) > 0.00) &&
+	      ((profile[x + 2] - profile[x]) > 0.00) &&
+	      (profile[x] < .25))
+	    p2[x] = 1;
+	}
+
+      /* travel rightwards, checking aspect ratio, looking at p2 now */
+      leftable = l2 = 0;
+      for (x = 0; x < d->w; x++)
+	if (p2[x] == 1)
+	  {
+	    if ((fabs ((abs (x - leftable) / (float) d->h) - 0.7) > 0.3) &&
+		(fabs ((abs (x - l2) / (float) d->h) - 0.7) > 0.3))
+	      p2[x] = 0;
+	    if (p2[x] == 1)
+	      {
+		leftable = l2;
+		l2 = x;
+	      }
+	  }
+
+      /* travel inwards, checking widths of chars, looking at p2 */
+      /* if a char has an aspect ratio of <= ? kill it */
+      l2 = 0;
+      leftable = d->w - 1;
+      x = 0;
+      y = d->w - 1;
+      while (x <= y)
+	{
+	  if (p2[x])
+	    {
+	      if (abs (x - l2) < max (d->h * 0.6, 5))
+		p2[x] = 0;
+	      if (p2[x])
+		l2 = x;
+	    }
+	  if (p2[y])
+	    {
+	      if (abs (y - leftable) < max (d->h * 0.6, 5))
+		p2[y] = 0;
+	      if (p2[y])
+		leftable = y;
+	    }
+	  x++;
+	  y--;
+	}
+
+
+      for (x = 0; x < d->w; x++)
+	if (p2[x])
+	  return 1;
+    }
+  return 0;
+}
+
+
+static void 
+split_mark (marklistptr * list, marktype * joinedmark)
+{
+  marktype new, old;
+  int x, found = 0, left = 0;
+  int i, j;
+  int oldw, oldh;
+  int overwrite = 1;
+
+  old = marktype_copy (*joinedmark);
+  oldw = joinedmark->w;
+  oldh = joinedmark->h;
+  for (x = 0; x < old.w; x++)
+    if (p2[x])
+      {
+	found = x;
+	break;
+      }
+  do
+    {
+      /* split at (found) position */
+      new.w = found + 1 - left;
+      new.h = old.h;
+      new.xpos = old.xpos + left;
+      new.ypos = old.ypos;
+      new.bitmap = pbm_allocarray (new.w, new.h);
+
+      for (i = 0; i < new.w; i++)
+	for (j = 0; j < new.h; j++)
+	  pbm_putpixel (new.bitmap, i, j, pbm_getpixel (old.bitmap, left + i, j));
+
+      marktype_adj_bound (&new);
+
+      if (overwrite)
+	{
+	  overwrite = 0;
+	  pbm_freearray (&(joinedmark->bitmap), oldh);
+	  *joinedmark = new;
+	}
+      else
+	marklist_add (list, new);
+
+
+      p2[found] = 0;
+      left = found;
+      found = 0;
+      for (x = left; x < old.w; x++)
+	if (p2[x])
+	  {
+	    found = x;
+	    break;
+	  }
+      if (left == old.w - 1)
+	break;			/* if we've got to the right */
+      if (found == 0)
+	found = old.w - 1;
+    }
+  while (found);
+  pbm_freearray (&(old.bitmap), oldh);
+}
+
+
+
+
+
+void 
+ExtractAllMarks (Pixel ** bitmap, marklistptr * list, int cols, int rows)
+{
+  int startx, starty, count;
+  marklistptr step;
+
+  startx = starty = 0;
+  while (ExtractNextMark (bitmap, list, &startx, &starty, cols, rows))
+    ;
+
+  if (splitjoined)
+    for (step = (*list), count = 0; step; step = step->next, count++)
+      if (possibly_joined (&(step->data)))
+	split_mark (list, &(step->data));
+
+  for (step = (*list), count = 0; step; step = step->next, count++)
+    step->data.symnum = count;
+}
Index: /indexers/branches/3.03a/mg/src/images/extractor.h
===================================================================
--- /indexers/branches/3.03a/mg/src/images/extractor.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/extractor.h	(revision 14757)
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * extractor.h -- Functions related to extracting marks
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#ifndef _EXTRACTOR_H_
+#define _EXTRACTOR_H_
+
+#include "marklist.h"
+#include "pbmtools.h"
+
+extern int splitjoined;
+
+void RunRegionFill (Pixel ** bitmap, marktype * mark, int i, int j, int xl, int yt, int cols, int rows);
+
+int ExtractNextMark (Pixel ** bitmap, marklistptr * marklist, int *tx, int *ty, int cols, int rows);
+void ExtractAllMarks (Pixel ** bitmap, marklistptr * marklist, int cols, int rows);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/images/felics.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/felics.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/felics.c	(revision 14757)
@@ -0,0 +1,340 @@
+/**************************************************************************
+ *
+ * felics.c -- The main guts of the felics algorithm
+ * Copyright (C) 1994  Neil Sharman and Kerry Guise
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "bitio_m.h"
+#include "bitio_m_stdio.h"
+
+
+#undef putw
+#define putw(x)	{					\
+	short z;					\
+	byteptr = (unsigned char *)(x);			\
+	for (z = 0; z < sizeof(int); z++)		\
+		(void) putc((int) byteptr[z], fp_out);	\
+}
+#define INTSIZE sizeof(int) * 8
+#define BOOLEAN short
+#define TRUE 1
+#define FALSE 0
+
+#define IN_RANGE 0
+#define OUT_OF_RANGE 1
+#define BELOW_RANGE 0
+#define ABOVE_RANGE 1
+
+
+void 
+encode (unsigned int *line, int width, int height, int maxval, int maxk,
+	FILE * fp_in, FILE * fp_out, int (*get) (FILE *))
+{
+  int x, y;
+  unsigned long P, L, H, N1, N2, delta;
+  unsigned long cumul_param[256][INTSIZE];
+  unsigned max_cumul;
+
+  memset (cumul_param, '0', sizeof (cumul_param));
+
+  if (maxk)
+    max_cumul = maxk;
+  else
+    CEILLOG_2 (maxval, max_cumul);
+
+  ENCODE_START (fp_out)
+
+    for (y = 0; y < height; y++)
+    for (x = 0; x < width; x++)
+      {
+	if (y > 0)
+	  {
+	    if (x > 0)
+	      {			/* ******** */
+		N1 = line[x];	/* ****1*** */
+		N2 = line[x - 1];	/* ***2P*** */
+	      }			/* ******** */
+	    else
+	      {			/* |******* */
+		N1 = line[x];	/* |12***** */
+		N2 = line[x + 1];	/* |P***** */
+	      }			/* |******* */
+	  }
+	else
+	  {
+	    if (x > 1)
+	      {
+		N1 = line[x - 1];	/* -------- */
+		N2 = line[x - 2];	/* **12P*** */
+	      }			/* ******** */
+	    else if (x > 0)
+	      {
+		N1 = line[x - 1];	/* +------- */
+		N2 = N1;	/* |3P***** */
+	      }			/* |******* */
+	    else
+	      {
+		line[x] = get (fp_in);	/* +------- */
+		BINARY_ENCODE (line[x] + 1, maxval + 1);	/* |P****** */
+		continue;	/* |******* */
+	      }
+	  }
+
+
+	H = N1 > N2 ? N1 : N2;
+	L = N1 < N2 ? N1 : N2;
+	delta = H - L;
+
+	line[x] = P = get (fp_in);
+
+	if ((L <= P) && (P <= H))
+	  {
+	    /* IN-RANGE */
+	    unsigned long range, logofrange, thresh, numlong;
+	    int nbits;
+
+	    ENCODE_BIT (IN_RANGE);
+
+	    P -= L;
+
+	    range = delta + 1;
+
+	    if (range > 1)
+	      {
+		/* 2**i <= delta + 1 < 2**(i+1) ; find i ... */
+		CEILLOG_2 (range, logofrange);
+
+		/* number of n-bit values in the range */
+		thresh = (1 << logofrange) - range;
+
+		/* number of n+1-bit values in the range */
+		numlong = range - thresh;
+
+		/* rotate the n-bit codes into the centre */
+		P -= (numlong >> 1);
+		if ((long) P < 0)
+		  P += range;
+
+		if (P < thresh)
+		  nbits = logofrange - 1;
+		else
+		  {
+		    nbits = logofrange;
+		    P += thresh;
+		  }
+		while (--nbits >= 0)
+		  ENCODE_BIT ((P >> nbits) & 1);
+	      }
+	  }
+	else
+	  {
+	    /* OUT_OF_RANGE */
+	    unsigned long diff, parm, i, min;
+
+	    ENCODE_BIT (OUT_OF_RANGE);
+
+	    if (P < L)
+	      {
+		ENCODE_BIT (BELOW_RANGE);
+		diff = L - P - 1;
+	      }
+	    else
+	      {
+		ENCODE_BIT (ABOVE_RANGE);
+		diff = P - H - 1;
+	      }
+
+	    /* Now code 'diff' as a Golomb-Rice code */
+
+	    parm = 0;
+	    min = cumul_param[delta][0];
+	    for (i = 1; i < max_cumul; i++)
+	      if (cumul_param[delta][i] < min)
+		{
+		  min = cumul_param[delta][i];
+		  parm = i;
+		}
+
+	    UNARY_ENCODE ((diff >> parm) + 1);
+	    BINARY_ENCODE ((diff & ((1 << parm) - 1)) + 1, 1 << parm);
+
+	    for (i = 0; i < max_cumul; i++)
+	      cumul_param[delta][i] += (diff >> i) + 1 + i;
+	  }
+
+      }
+
+  ENCODE_DONE
+
+}
+
+
+
+
+
+
+void 
+decode (unsigned int *line, int width, int height, int maxval, int maxk,
+	FILE * fp_in, FILE * fp_out)
+{
+  int x, y;
+  unsigned int P, L, H, N1, N2, delta;
+  unsigned long cumul_param[256][INTSIZE];
+  unsigned max_cumul;
+
+  memset (cumul_param, '0', sizeof (cumul_param));
+
+  if (maxk)
+    max_cumul = maxk;
+  else
+    CEILLOG_2 (maxval, max_cumul);
+
+  DECODE_START (fp_in);
+
+  for (y = 0; y < height; y++)
+    for (x = 0; x < width; x++)
+      {
+	if (y > 0)
+	  {
+	    if (x > 0)
+	      {			/* ******** */
+		N1 = line[x];	/* ****1*** */
+		N2 = line[x - 1];	/* ***2P*** */
+	      }			/* ******** */
+	    else
+	      {			/* |******* */
+		N1 = line[x];	/* |12***** */
+		N2 = line[x + 1];	/* |P***** */
+	      }			/* |******* */
+	  }
+	else
+	  {
+	    if (x > 1)
+	      {
+		N1 = line[x - 1];	/* -------- */
+		N2 = line[x - 2];	/* **12P*** */
+	      }			/* ******** */
+	    else if (x > 0)
+	      {
+		N1 = line[x - 1];	/* +------- */
+		N2 = N1;	/* |3P***** */
+	      }			/* |******* */
+	    else
+	      {
+		BINARY_DECODE (line[x], maxval + 1);
+		line[x]--;
+		if (maxval < 256)
+		  putc (line[x], fp_out);	/* +------- */
+		else		/* |P****** */
+		  fprintf (fp_out, "%u ", line[x]);	/* |******* */
+		continue;
+	      }
+	  }
+
+
+	H = N1 > N2 ? N1 : N2;
+	L = N1 < N2 ? N1 : N2;
+	delta = H - L;
+
+	if (DECODE_BIT == IN_RANGE)
+	  {
+	    unsigned long i, range, logofrange, thresh, numlong;
+	    unsigned xx, l;
+
+	    range = delta + 1;
+
+	    if (range > 1)
+	      {
+		/* 2**i <= delta + 1 < 2**(i+1) ; find i ... */
+		CEILLOG_2 (range, logofrange);
+
+		/* number of n-bit values in the range */
+		thresh = (1 << logofrange) - range;
+		for (P = i = 0; i < logofrange - 1; i++)
+		  DECODE_ADD (P);
+		xx = P;
+		l = logofrange - 1;
+		if (P >= thresh)
+		  {
+		    DECODE_ADD (P);
+		    xx = P;
+		    l++;
+		    P -= thresh;
+		  }
+
+		/* number of n+1-bit values in the range */
+		numlong = range - thresh;
+
+		/* rotate the n-bit codes into the centre */
+		P += (numlong >> 1);
+		if ((long) P >= range)
+		  P -= range;
+
+		P += L;
+	      }
+	    else
+	      P = L;
+	  }
+	else
+	  {
+	    int out_of_range = DECODE_BIT;
+	    unsigned long diff, unary, binary, i, min, parm;
+
+	    /* Now code 'diff' as a Golomb-Rice code */
+
+	    parm = 0;
+	    min = cumul_param[delta][0];
+	    for (i = 1; i < max_cumul; i++)
+	      if (cumul_param[delta][i] < min)
+		{
+		  min = cumul_param[delta][i];
+		  parm = i;
+		}
+
+	    UNARY_DECODE (unary);
+	    diff = (unary - 1) << parm;
+	    BINARY_DECODE (binary, 1 << parm);
+	    diff |= binary - 1;
+
+	    for (i = 0; i < max_cumul; i++)
+	      cumul_param[delta][i] += (diff >> i) + 1 + i;
+
+	    if (out_of_range == BELOW_RANGE)
+	      {
+		P = L - diff - 1;
+	      }
+	    else
+	      {
+		P = diff + H + 1;
+	      }
+	  }
+
+	line[x] = P;
+
+	if (maxval < 256)
+	  (void) putc (P, fp_out);
+	else
+	  fprintf (fp_out, "%u ", P);
+      }
+
+  DECODE_DONE
+}
Index: /indexers/branches/3.03a/mg/src/images/lstevent.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/lstevent.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/lstevent.c	(revision 14757)
@@ -0,0 +1,424 @@
+/**************************************************************************
+ *
+ * lstevent.c -- Routines to implement "events" using MTF lists.
+ * Copyright (C) 1987  Alistair Moffat
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "arithcode.h"
+#include "model.h"
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:16:56  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:17:26  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:33:37  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.2  1994/09/20  04:41:40  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+void
+write_method ()
+{
+  fprintf (stderr, "C");
+}
+
+
+/*===========================================*/
+
+/*
+ * [Rodney Brown - Sep/95]
+ * On IBM RS/6000 AIX version 3.2 the compiler defines NULL as (void *)0
+ * when in ANSI mode. Hence the (event) and (point) casts
+ */
+
+
+#define GETNEWNODE(e,node)		\
+do 					\
+{	node = p32(numnodes) ;		\
+	node->eventnum = (event)e ;	\
+	node->count = increment ;	\
+	node->foll.totalcnt = 0 ;	\
+	node->foll.notfound = 0 ;	\
+	node->foll.list = (point)NULL ;	\
+	numnodes += 1 ;			\
+	nfreenodes -= 1 ;		\
+}					\
+while (false)
+
+/*===========================================*/
+
+#define INSERTNODE(U,node)		\
+do					\
+{	node->next = U->list ;		\
+	U->list = p16(node) ;		\
+	U->totalcnt += increment;	\
+}					\
+while (false)
+
+/*===========================================*/
+
+int
+halvelist (p)
+     register eventnode *p;
+{
+  register int sum = 0;
+  while (p != ENULL)
+    {
+      sum += p->count = (p->count + 1) / 2;
+      p = p32 (p->next);
+    }
+  return (sum);
+}
+
+/*===========================================*/
+
+void
+halveallcounts (U)
+     register eventset *U;
+{
+  U->notfound = (U->notfound + 1) / 2;
+  U->totalcnt = U->notfound;
+  U->totalcnt += halvelist (p32 (U->list));
+}
+
+/*===========================================*/
+
+eventnode *
+encode_event_noex (U, e, success)
+     register eventset *U;
+     event e;
+     boolean *success;
+{
+  register eventnode *pnode, *node;
+  register int lbnd, totl;
+
+  if (U->list == (point)NULL)
+    {
+      *success = false;
+      U->notfound += increment;
+      U->totalcnt += increment;
+      GETNEWNODE (e, node);
+      INSERTNODE (U, node);
+      return (node);
+    }
+
+  lbnd = 0;
+  pnode = ENULL;
+  node = p32 (U->list);
+  while (node != ENULL)
+    {
+      if (e == node->eventnum)
+	break;
+      lbnd += node->count;
+      pnode = node;
+      node = p32 (node->next);
+    }
+
+  totl = U->totalcnt;
+
+  if (node == ENULL)
+    {				/* event not found in list */
+      if ((totl > U->notfound))
+	arithmetic_encode (totl - U->notfound, totl, totl);
+      U->notfound += increment;
+      U->totalcnt += increment;
+      *success = false;
+      GETNEWNODE (e, node);
+      INSERTNODE (U, node);
+    }
+  else
+    {				/* found in the list, so go ahead and code */
+      arithmetic_encode (lbnd, lbnd + node->count, totl);
+      node->count += increment;
+      U->totalcnt += increment;
+      *success = true;
+      /* and move to front */
+      if (pnode != ENULL)
+	{
+	  pnode->next = node->next;
+	  node->next = U->list;
+	  U->list = p16 (node);
+	}
+    }
+  if (U->totalcnt > maxtotalcnt)
+    halveallcounts (U);
+  return (node);
+}
+
+/*===========================================*/
+
+eventnode *
+decode_event_noex (U, success, e)
+     register eventset *U;
+     boolean *success;
+     event *e;
+{
+  register eventnode *node, *pnode;
+  register int tget, lbnd, totl;
+
+  if (U->list == (point)NULL)
+    {
+      *success = false;
+      U->totalcnt += increment;
+      U->notfound += increment;
+      GETNEWNODE (NULL, node);
+      INSERTNODE (U, node);
+      return (node);
+    }
+  totl = U->totalcnt;
+  tget = arithmetic_decode_target (totl);
+
+  if (tget >= totl - U->notfound)
+    {
+      if (totl > U->notfound)
+	arithmetic_decode (totl - U->notfound, totl, totl);
+      U->totalcnt += increment;
+      U->notfound += increment;
+      *success = false;
+      GETNEWNODE (NULL, node);
+      INSERTNODE (U, node);
+    }
+  else
+    {
+      pnode = ENULL;
+      node = p32 (U->list);
+      lbnd = 0;
+      for (;;)
+	{
+	  if (tget < (lbnd += node->count))
+	    break;
+	  pnode = node;
+	  node = p32 (node->next);
+	}
+
+      arithmetic_decode (lbnd - node->count, lbnd, totl);
+      node->count += increment;
+      U->totalcnt += increment;
+      *e = node->eventnum;
+      *success = true;
+      /* and move to front */
+      if (pnode != ENULL)
+	{
+	  pnode->next = node->next;
+	  node->next = U->list;
+	  U->list = p16 (node);
+	}
+    }
+  if (U->totalcnt > maxtotalcnt)
+    halveallcounts (U);
+  return (node);
+}
+
+/*===========================================*/
+
+eventnode *
+encode_event (U, e, success)
+     register eventset *U;
+     event e;
+     boolean *success;
+{
+  register eventnode *pnode, *node, *p;
+  register int lbnd, totl;
+
+  if (U->list == (point)NULL)
+    {
+      *success = false;
+      U->notfound += increment;
+      U->totalcnt += increment;
+      GETNEWNODE (e, node);
+      INSERTNODE (U, node);
+      return (node);
+    }
+
+  lbnd = 0;
+  pnode = ENULL;
+  node = p32 (U->list);
+  while (node != ENULL)
+    {
+      if (!excluded[node->eventnum])
+	{
+	  if (e == node->eventnum)
+	    break;
+	  lbnd += node->count;
+	}
+      pnode = node;
+      node = p32 (node->next);
+    }
+
+  if (node == ENULL)
+    {				/* event not found in list, and whole list has been scanned */
+      totl = lbnd + U->notfound;
+      if ((totl > U->notfound))
+	arithmetic_encode (totl - U->notfound, totl, totl);
+      U->notfound += increment;
+      U->totalcnt += increment;
+      *success = false;
+      GETNEWNODE (e, node);
+      INSERTNODE (U, node);
+    }
+  else
+    {				/* found in the list, so go ahead and code */
+      /* first, total up rest of list */
+      totl = lbnd + node->count;
+      p = p32 (node->next);
+      while (p != ENULL)
+	{
+	  if (!excluded[p->eventnum])
+	    totl += p->count;
+	  p = p32 (p->next);
+	}
+      totl += U->notfound;
+
+      arithmetic_encode (lbnd, lbnd + node->count, totl);
+      node->count += increment;
+      U->totalcnt += increment;
+      *success = true;
+      /* and move to front */
+      if (pnode != ENULL)
+	{
+	  pnode->next = node->next;
+	  node->next = U->list;
+	  U->list = p16 (node);
+	}
+    }
+  if (U->totalcnt > maxtotalcnt)
+    halveallcounts (U);
+  return (node);
+}
+
+/*===========================================*/
+
+eventnode *
+decode_event (U, success, e)
+     register eventset *U;
+     boolean *success;
+     event *e;
+{
+  register eventnode *node, *pnode;
+  register int tget, lbnd, totl;
+
+  if (U->list == (point)NULL)
+    {
+      *success = false;
+      U->totalcnt += increment;
+      U->notfound += increment;
+      GETNEWNODE (NULL, node);
+      INSERTNODE (U, node);
+      return (node);
+    }
+  totl = 0;
+  node = p32 (U->list);
+  while (node != ENULL)
+    {
+      if (!excluded[node->eventnum])
+	totl += node->count;
+      node = p32 (node->next);
+    }
+  totl += U->notfound;
+  tget = arithmetic_decode_target (totl);
+
+  if (tget >= totl - U->notfound)
+    {
+      if (totl > U->notfound)
+	arithmetic_decode (totl - U->notfound, totl, totl);
+      U->totalcnt += increment;
+      U->notfound += increment;
+      *success = false;
+      GETNEWNODE (NULL, node);
+      INSERTNODE (U, node);
+    }
+  else
+    {
+      pnode = ENULL;
+      node = p32 (U->list);
+      lbnd = 0;
+      for (;;)
+	{
+	  if (!excluded[node->eventnum])
+	    {
+	      lbnd += node->count;
+	      if (tget < lbnd)
+		break;
+	    }
+	  pnode = node;
+	  node = p32 (node->next);
+	}
+
+      arithmetic_decode (lbnd - node->count, lbnd, totl);
+      node->count += increment;
+      U->totalcnt += increment;
+      *e = node->eventnum;
+      *success = true;
+      /* and move to front */
+      if (pnode != ENULL)
+	{
+	  pnode->next = node->next;
+	  node->next = U->list;
+	  U->list = p16 (node);
+	}
+    }
+  if (U->totalcnt > maxtotalcnt)
+    halveallcounts (U);
+  return (node);
+}
+
+/*===========================================*/
+
+eventnode *
+newnode (e)
+     event e;
+{
+  register eventnode *node;
+  GETNEWNODE (e, node);
+  node->next = (point)NULL;
+  node->prev = (point)NULL;
+  return (node);
+}
+
+/*===========================================*/
+
+/* not required in this version */
+
+#if 0
+eventnode *
+addevent (U, e)
+     register eventset *U;
+     event e;
+{
+  register eventnode *node;
+  /* get an event node */
+  GETNEWNODE (e, node);
+  INSERTNODE (U, node);
+  if (U->totalcnt > maxtotalcnt)
+    halveallcounts (U);
+  return (node);
+}
+#endif
Index: /indexers/branches/3.03a/mg/src/images/marklist.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/marklist.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/marklist.c	(revision 14757)
@@ -0,0 +1,827 @@
+/**************************************************************************
+ *
+ * marklist.c -- Functions managing the list of marks
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "marklist.h"
+#include "pbmtools.h"
+#include "utils.h"
+
+void 
+marktype_dump (marktype d)
+{
+  fprintf (stderr, "symnum: %d\n", d.symnum);
+  fprintf (stderr, "xpos: %d, ypos: %d\n", d.xpos, d.ypos);
+  fprintf (stderr, "w: %d, h: %d\n", d.w, d.h);
+  fprintf (stderr, "xcen: %d, ycen: %d\n", d.xcen, d.ycen);
+  write_library_mark (stderr, d);
+}
+
+
+/* copy, including make a copy of the bitmap */
+marktype 
+marktype_copy (marktype d)
+{
+  marktype d2;
+  int i, j;
+
+  d2 = d;
+  d2.bitmap = pbm_allocarray (d2.w, d2.h);
+  for (i = 0; i < d2.w; i++)
+    for (j = 0; j < d2.h; j++)
+      pbm_putpixel (d2.bitmap, i, j, pbm_getpixel (d.bitmap, i, j));
+  return d2;
+}
+
+
+float 
+marktype_density (marktype d)
+{
+  return d.set / (float) (d.w * d.h);
+}
+
+
+
+void 
+marktype_calc_centroid (marktype * b)
+{
+  int r, c;
+  int count = 0;
+  int xtot = 0, ytot = 0;
+
+  for (r = 0; r < b->h; r++)
+    for (c = 0; c < b->w; c++)
+      if (pbm_getpixel (b->bitmap, c, r))
+	{
+	  count++;
+	  xtot += c;
+	  ytot += r;
+	}
+  if (count)
+    {
+      xtot /= count;
+      ytot /= count;
+    }
+  b->xcen = xtot;
+  b->ycen = ytot;
+}
+
+
+
+static void 
+marktype_area (marktype * d)
+{
+  int x, y;
+  int set = 0;
+
+  for (y = 0; y < d->h; y++)
+    for (x = 0; x < d->w; x++)
+      if (pbm_getpixel (d->bitmap, x, y))
+	set++;
+  d->set = set;
+}
+
+
+static void 
+marktype_h_runs (marktype * d)
+{
+  int x, y;
+  int inrun = 0, num = 0;
+  int foundblack = 0;
+
+  for (y = 0; y < d->h; y++)
+    {
+      inrun = 0;
+      foundblack = 0;
+      for (x = 0; x < d->w; x++)
+	{
+	  if ((!foundblack) && (pbm_getpixel (d->bitmap, x, y)))
+	    foundblack = 1;
+	  if ((foundblack) && (pbm_getpixel (d->bitmap, x, y) == 0))
+	    inrun = 1;
+	  if ((inrun) && (pbm_getpixel (d->bitmap, x, y)))
+	    {
+	      num++;
+	      inrun = 0;
+	      foundblack = 0;
+	    }
+	}
+    }
+  d->h_runs = num;
+}
+
+static void 
+marktype_v_runs (marktype * d)
+{
+  int x, y;
+  int inrun = 0, num = 0;
+  int foundblack = 0;
+
+
+  for (x = 0; x < d->w; x++)
+    {
+      inrun = 0;
+      foundblack = 0;
+      for (y = 0; y < d->h; y++)
+	{
+	  if ((!foundblack) && (pbm_getpixel (d->bitmap, x, y)))
+	    foundblack = 1;
+	  if ((foundblack) && (pbm_getpixel (d->bitmap, x, y) == 0))
+	    inrun = 1;
+	  if ((inrun) && (pbm_getpixel (d->bitmap, x, y)))
+	    {
+	      num++;
+	      inrun = 0;
+	      foundblack = 0;
+	    }
+	}
+    }
+  d->v_runs = num;
+}
+
+
+/* assume we already have the centroid! */
+static void 
+marktype_prog_cent (marktype * d)
+{
+  int x, y;
+  int xtot = 0, ytot = 0;
+  int num = 0;
+
+  xtot = ytot = num = 0;
+  for (x = 0; x < d->xcen; x++)
+    for (y = 0; y < d->ycen; y++)
+      if (pbm_getpixel (d->bitmap, x, y))
+	{
+	  xtot += x;
+	  ytot += y;
+	  num++;
+	}
+  if (num == 0)
+    {
+      d->xcen1 = -1;
+      d->ycen1 = -1;
+    }
+  else
+    {
+      d->xcen1 = xtot / num;
+      d->ycen1 = ytot / num;
+    }
+
+
+  xtot = ytot = num = 0;
+  for (x = d->xcen; x < d->w; x++)
+    for (y = 0; y < d->ycen; y++)
+      if (pbm_getpixel (d->bitmap, x, y))
+	{
+	  xtot += x;
+	  ytot += y;
+	  num++;
+	}
+  if (num == 0)
+    {
+      d->xcen2 = -1;
+      d->ycen2 = -1;
+    }
+  else
+    {
+      d->xcen2 = xtot / num;
+      d->ycen2 = ytot / num;
+    }
+
+
+
+  xtot = ytot = num = 0;
+  for (x = 0; x < d->xcen; x++)
+    for (y = d->ycen; y < d->h; y++)
+      if (pbm_getpixel (d->bitmap, x, y))
+	{
+	  xtot += x;
+	  ytot += y;
+	  num++;
+	}
+
+
+  if (num == 0)
+    {
+      d->xcen3 = -1;
+      d->ycen3 = -1;
+    }
+  else
+    {
+      d->xcen3 = xtot / num;
+      d->ycen3 = ytot / num;
+    }
+
+  xtot = ytot = num = 0;
+  for (x = d->xcen; x < d->w; x++)
+    for (y = d->ycen; y < d->h; y++)
+      if (pbm_getpixel (d->bitmap, x, y))
+	{
+	  xtot += x;
+	  ytot += y;
+	  num++;
+	}
+  if (num == 0)
+    {
+      d->xcen4 = -1;
+      d->ycen4 = -1;
+    }
+  else
+    {
+      d->xcen4 = xtot / num;
+      d->ycen4 = ytot / num;
+    }
+}
+
+
+
+/* call this to get all features */
+void 
+marktype_calc_features (marktype * d, char str[])
+{
+  if (strlen (str))
+    strcpy (d->name, str);
+  marktype_calc_centroid (d);
+  marktype_area (d);
+  marktype_prog_cent (d);
+  marktype_h_runs (d);
+  marktype_v_runs (d);
+}
+
+
+
+
+
+void 
+marktype_adj_bound (marktype * m)
+{
+  int x, y, w, h;
+  int xpos, ypos;
+  int top = 0, left = 0, right = 0, bot = 0;
+  marktype temp;
+
+  w = m->w;
+  h = m->h;
+  xpos = m->xpos;
+  ypos = m->ypos;
+
+  for (y = 0; y < h; y++)
+    for (x = 0; x < w; x++)
+      if (pbm_getpixel (m->bitmap, x, y))
+	{
+	  top = y;
+	  x = w;
+	  y = h;
+	}
+
+  for (y = h - 1; y >= 0; y--)
+    for (x = 0; x < w; x++)
+      if (pbm_getpixel (m->bitmap, x, y))
+	{
+	  bot = y;
+	  x = w;
+	  y = -1;
+	}
+
+  for (x = 0; x < w; x++)
+    for (y = 0; y < h; y++)
+      if (pbm_getpixel (m->bitmap, x, y))
+	{
+	  left = x;
+	  x = w;
+	  y = h;
+	}
+
+  for (x = w - 1; x >= 0; x--)
+    for (y = 0; y < h; y++)
+      if (pbm_getpixel (m->bitmap, x, y))
+	{
+	  right = x;
+	  x = -1;
+	  y = h;
+	}
+
+  temp.w = right - left + 1;
+  temp.h = bot - top + 1;
+  temp.xpos = xpos + left;
+  temp.ypos = ypos + top;
+  temp.bitmap = pbm_allocarray (temp.w, temp.h);
+
+  for (x = 0; x < temp.w; x++)
+    for (y = 0; y < temp.h; y++)
+      pbm_putpixel (temp.bitmap, x, y, pbm_getpixel (m->bitmap, x + left, y + top));
+
+  pbm_freearray (&(m->bitmap), h);
+
+  marktype_calc_features (&temp, "?");
+  *m = temp;
+}
+
+
+
+
+
+
+/* returns a newly created mark reprenting the average of the marklist */
+void 
+marklist_average (marklistptr list, marktype * avgmark)
+{
+  int w = 0, h = 0;
+  int t = INT_MAX, b = 0, l = INT_MAX, r = 0, matched = 0;
+  marktype d, temp;
+  marklistptr step;
+  static int a[100][100];
+  int x, y;
+
+  if (list == NULL)
+    error_msg ("marklist_average", "Can't average 'nothing'!", "");
+
+  for (step = list; step; step = step->next)
+    {
+      matched++;
+      temp = step->data;
+      w = max (w, temp.w);
+      h = max (h, temp.h);
+      r = max (r, temp.xcen);
+      l = min (l, temp.xcen);
+      b = max (b, temp.ycen);
+      t = min (t, temp.ycen);
+    }
+  w = w + (r - l);
+  h = h + (b - t);
+  if ((w >= 100) || (h >= 100))
+    matched = 0;
+
+  if (matched > 1)
+    {
+      int x_off, y_off;
+      for (x = 0; x < w; x++)
+	for (y = 0; y < h; y++)
+	  a[x][y] = 0;
+
+      for (step = list; step; step = step->next)
+	{
+	  x_off = r - step->data.xcen;
+	  y_off = b - step->data.ycen;
+	  for (x = 0; x < step->data.w; x++)
+	    for (y = 0; y < step->data.h; y++)
+	      if (pbm_getpixel (step->data.bitmap, x, y))
+		a[x + x_off][y + y_off]++;
+	}
+
+      d.w = w;
+      d.h = h;
+      d.bitmap = pbm_allocarray (w, h);
+      for (x = 0; x < w; x++)
+	for (y = 0; y < h; y++)
+	  if (a[x][y] > max (1, (matched / 2)))		/* > gives better CR than >= */
+	    pbm_putpixel (d.bitmap, x, y, 1);
+      marktype_adj_bound (&d);
+      strcpy (d.name, "?");
+      marktype_calc_centroid (&d);
+    }
+  else
+    d = marktype_copy (list->data);
+
+  *avgmark = d;
+}
+
+
+
+
+
+
+void 
+marklist_setnull (marklistptr * list)
+{
+  *list = NULL;
+}
+
+
+marklistptr 
+marklist_add (marklistptr * list, marktype m)
+{
+  marklistptr p;
+
+  if (*list == NULL)
+    {
+      *list = (marklistptr) malloc (sizeof (marklisttype));
+      if ((*list) == NULL)
+	error_msg ("marklist_add", "OUT of Memory in marklist_add", "");
+      p = *list;
+    }
+  else
+    {
+      p = *list;
+      while (p->next != NULL)
+	p = p->next;
+      p->next = (marklistptr) malloc (sizeof (marklisttype));
+      if (p->next == NULL)
+	error_msg ("marklist_add", "OUT of Memory in marklist_add", "");
+      p = p->next;
+    }
+  p->data = m;
+  p->next = NULL;
+  return p;
+
+}
+
+
+
+marklistptr 
+marklist_addcopy (marklistptr * list, marktype m)
+{
+  marktype d;
+
+  d = marktype_copy (m);
+  return marklist_add (list, d);
+}
+
+
+
+int 
+marklist_length (marklistptr list)
+{
+  int count = 0;
+
+  while (list)
+    {
+      count++;
+      list = list->next;
+    }
+  return count;
+}
+
+
+
+
+
+void 
+marklist_dump (marklistptr list)
+{
+  int count = 0;
+  marktype d;
+
+  while (list)
+    {
+      d = list->data;
+      marktype_dump (d);
+
+      count++;
+      list = list->next;
+    }
+}
+
+
+
+
+/* pos starts from 0, to up marklist_length-1 */
+marklistptr 
+marklist_getat (marklistptr list, int pos, marktype * d)
+{
+  int count = 0;
+
+  while (list)
+    {
+      if (count == pos)
+	{
+	  *d = list->data;
+	  return list;
+	}
+      count++;
+      list = list->next;
+    }
+  fprintf (stderr, "marklist_getat(): access off ends of list: pos %d\n", pos);
+  return NULL;
+}
+
+
+
+void 
+marklist_free (marklistptr * list)
+{
+  marklistptr n;
+
+  while ((*list) != NULL)
+    {
+      n = (*list)->next;
+      pbm_freearray (&((*list)->data.bitmap), (*list)->data.h);
+      free ((*list));
+      (*list) = n;
+    }
+}
+
+
+
+int 
+marklist_removeat (marklistptr * list, int pos)
+{
+  marklistptr c, n, p = NULL;
+  int count = 0;
+
+  if ((pos == 0) && (*list))
+    {				/* if removing the 1st element */
+      *list = (*list)->next;
+      return 1;
+    }
+  else
+    {
+      c = *list;
+      while (c)
+	{
+	  if (count == pos)
+	    {			/* two cases, no previous, >=1 previous */
+	      if (p == NULL)	/* no previous */
+		{
+		  n = c->next;
+		  pbm_freearray (&c->data.bitmap, c->data.h);
+		  free (c);
+		  c = n;
+		  return 1;
+		}
+	      else
+		/* >=1 previous */
+		{
+		  n = c->next;
+		  pbm_freearray (&c->data.bitmap, c->data.h);
+		  free (c);
+		  p->next = n;
+		  return 1;
+		}
+	    }
+	  count++;
+	  p = c;
+	  c = c->next;
+	}
+    }
+  fprintf (stderr, "marklist_removeat(): access off ends of list: pos %d\n", pos);
+  return 0;			/* nothing was removed */
+}
+
+
+
+marklistptr 
+marklist_next (marklistptr list)
+{
+  return list->next;
+}
+
+
+/* only writes out ascii form */
+void 
+write_library_mark (FILE * fp, marktype d)
+{
+  int r, c, rows, cols;
+  int xtot = d.xcen, ytot = d.ycen;
+
+  rows = d.h;
+  cols = d.w;
+
+  fprintf (fp, "Mark: %d\n", d.symnum);
+  fprintf (fp, "Char: %s\n", d.name);
+  fprintf (fp, "Cols: %d Rows: %d\n", d.w, d.h);
+  for (r = 0; r < d.h; r++)
+    {
+      for (c = 0; c < d.w; c++)
+	if ((r == ytot) && (c == xtot))
+	  putc (pbm_getpixel (d.bitmap, c, r) ? 'C' : '!', fp);
+	else
+	  putc (pbm_getpixel (d.bitmap, c, r) ? 'X' : '.', fp);
+      putc ('\n', fp);
+    }
+}
+
+
+
+/* only reads in ascii library */
+int 
+read_library_mark (FILE * fp, marktype * d)
+{
+  int r, c, rows, cols, numread, ch1 = 'C';
+  char str1[100], str2[100];
+
+  numread = fscanf (fp, "%s %d\n", str1, &(d->symnum));
+  if ((numread != 2) || (strcmp (str1, "Mark:") != 0))
+    return 0;
+  fscanf (fp, "%s %s\n", str1, (d->name));
+  fscanf (fp, "%s %d %s %d\n", str1, &(d->w), str2, &(d->h));
+  cols = d->w;
+  rows = d->h;
+  d->bitmap = pbm_allocarray (cols, rows);
+  for (r = 0; r < rows; r++)
+    {
+      for (c = 0; c < cols; c++)
+	{
+	  ch1 = getc (fp);
+	  if ((ch1 == 'X') || (ch1 == 'C'))
+	    pbm_putpixel (d->bitmap, c, r, 1);
+	  else
+	    pbm_putpixel (d->bitmap, c, r, 0);
+	}
+      ch1 = getc (fp);
+    }
+  marktype_calc_features (d, "?");
+
+  return 1;
+}
+
+
+
+
+
+
+
+int 
+read_library (char libraryname[], marklistptr * library)
+{
+  int err, count;
+  FILE *lib;
+  marktype d;
+  marklistptr step;
+
+  lib = fopen (libraryname, "rb");
+  if (lib == NULL)
+    error_msg ("read_library()", "Trouble opening library file", "");
+  *library = NULL;
+  count = 0;
+  while (!isEOF (lib))
+    {
+      err = read_library_mark (lib, &d);
+      if (!err)
+	error_msg ("read_library()", "unknown format of the library file.", "");
+      d.symnum = count;
+      count++;
+      if ((*library) == NULL)
+	step = marklist_add (library, d);
+      else
+	step = marklist_add (&step, d);
+    }
+  count = marklist_length (*library);
+  fclose (lib);
+
+  return count;
+}
+
+
+
+
+
+
+/**********************************************************************
+
+'elem' routines for coding offsets
+
+the elem datatype contains the 3 params for arithmetic coding,
+stored as a no-duplicates order linked list.
+
+************************************************************************/
+
+
+
+
+void 
+elem_add (elemlist * list, int num)
+{
+  elemptr temp, nn;
+  int p, f;
+
+  list->tot++;
+  if (list->head == NULL)
+    {
+      list->head = (elemptr) malloc (sizeof (elem));
+      if ((list->head) == NULL)
+	error_msg ("", "ekk", "");
+      temp = list->head;
+      temp->next = NULL;
+      temp->num = num;
+      temp->pos = 0;
+      temp->freq = 1;
+    }
+  else
+    {				/* add to list */
+      temp = list->head;
+      p = 0;
+      f = 0;
+      while ((num > temp->num) && (temp->next != NULL))
+	{
+	  p = temp->pos;
+	  f = temp->freq;
+	  temp = temp->next;
+	}
+
+      if (temp->num == num)
+	temp->freq++;
+      else
+	{			/* insert it */
+	  nn = (elemptr) malloc (sizeof (elem));
+	  if (nn == NULL)
+	    error_msg ("", "ekk", "");
+
+	  if (num < temp->num)
+	    {
+	      nn->num = temp->num;
+	      nn->pos = temp->pos;
+	      nn->freq = temp->freq;
+	      nn->next = temp->next;
+	      temp->num = num;
+	      temp->pos = p + f;
+	      temp->freq = 1;
+	      temp->next = nn;
+	    }
+	  else
+	    {
+	      nn->next = temp->next;
+	      temp->next = nn;
+	      nn->pos = temp->pos + temp->freq;
+	      nn->num = num;
+	      nn->freq = 1;
+	      temp = nn;
+	    }
+	}
+    }
+  /* update frequencies */
+  temp = temp->next;
+  if (temp)
+    do
+      {
+	temp->pos++;
+	temp = temp->next;
+      }
+    while (temp);
+}
+
+
+void 
+elem_free (elemlist * list)
+{
+  elemptr n, p;
+
+  p = list->head;
+  while (p != NULL)
+    {
+      n = p->next;
+      free (p);
+      p = n;
+    }
+  list->head = NULL;
+}
+
+int 
+elem_find (elemlist * list, int n, int *p, int *f, int *t)
+{
+  elemptr temp;
+
+  temp = list->head;
+  while (temp)
+    {
+      if (temp->num == n)
+	{
+	  *p = temp->pos;
+	  *f = temp->freq + temp->pos;
+	  *t = list->tot;
+	  return 1;
+	}
+      temp = temp->next;
+    }
+  return 0;
+}
+
+
+int 
+elem_getrange (elemlist * list, int range, int *num)
+{
+  elemptr temp;
+
+  temp = list->head;
+  while (temp)
+    {
+      if ((range >= temp->pos) && (range < (temp->pos + temp->freq)))
+	{
+	  *num = temp->num;
+	  return 1;
+	}
+      temp = temp->next;
+    }
+  return 0;
+}
Index: /indexers/branches/3.03a/mg/src/images/marklist.h
===================================================================
--- /indexers/branches/3.03a/mg/src/images/marklist.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/marklist.h	(revision 14757)
@@ -0,0 +1,114 @@
+/**************************************************************************
+ *
+ * marklist.h -- Functions managing the list of marks
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef __MARKLIST_H
+#define __MARKLIST_H
+
+#include "sysfuncs.h"
+#include "basictypes.h"
+
+typedef struct
+  {
+    int symnum;
+    int xpos, ypos;
+    int w, h;
+    int xcen, ycen;
+    int xoffset, yoffset;
+    char name[10];
+    Pixel **bitmap;
+
+    int xcen1, ycen1;
+    int xcen2, ycen2;
+    int xcen3, ycen3;
+    int xcen4, ycen4;
+    int set;
+    int h_runs;
+    int v_runs;
+  }
+marktype;
+
+
+typedef struct marklisttype *marklistptr;
+typedef struct marklisttype
+  {
+    marktype data;
+    marklistptr next;
+  }
+marklisttype;
+
+
+void marktype_dump (marktype d);
+marktype marktype_copy (marktype d);
+
+float marktype_density (marktype d);
+void marktype_calc_centroid (marktype * b);
+void marktype_calc_features (marktype * d, char str[]);
+void marktype_adj_bound (marktype * m);
+
+void marklist_average (marklistptr list, marktype * avgmark);
+void marklist_setnull (marklistptr * list);
+marklistptr marklist_add (marklistptr * list, marktype m);
+marklistptr marklist_addcopy (marklistptr * list, marktype m);
+int marklist_length (marklistptr list);
+void marklist_dump (marklistptr list);
+marklistptr marklist_getat (marklistptr list, int pos, marktype * d);
+void marklist_free (marklistptr * list);
+int marklist_removeat (marklistptr * list, int pos);
+marklistptr marklist_next (marklistptr list);
+
+void write_library_mark (FILE * fp, marktype d);
+int read_library_mark (FILE * fp, marktype * d);
+int read_library (char libraryname[], marklistptr * library);
+
+
+
+
+
+
+/* 
+   The 'elem' structure is an ordered linked list, with fields corresponding
+   directly to the arithmetic coding routines.  
+ */
+typedef struct elem *elemptr;
+typedef struct elem
+  {
+    int num;
+    int pos;
+    int freq;
+    elemptr next;
+  }
+elem;
+
+typedef struct elemlist
+  {
+    elemptr head;
+    int tot;
+  }
+elemlist;
+
+void elem_add (elemlist * list, int num);
+void elem_free (elemlist * list);
+int elem_find (elemlist * list, int n, int *p, int *f, int *t);
+int elem_getrange (elemlist * list, int range, int *num);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/images/match.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/match.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/match.c	(revision 14757)
@@ -0,0 +1,417 @@
+/**************************************************************************
+ *
+ * match.c -- Functions related to matching marks
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "marklist.h"
+#include "pbmtools.h"
+#include "utils.h"
+
+
+/* error mask goes from 0..8, single pixel errors are worth nothing */
+int 
+WXOR_match (marktype b1, marktype b2)
+{
+  int r, c, i, j;
+  int minr, minc;
+  int maxr, maxc;
+  int offx, offy;
+  int p1, p2;
+  int count = 0;
+  marktype d;
+
+  offx = b1.xcen - b2.xcen;
+  offy = b1.ycen - b2.ycen;
+
+  minc = min (0, offx);
+  minr = min (0, offy);
+
+  maxc = max (b1.w, b2.w + offx);
+  maxr = max (b1.h, b2.h + offy);
+
+  d.w = maxc - minc + 1;
+  d.h = maxr - minr + 1;
+  d.bitmap = pbm_allocarray (d.w, d.h);
+
+
+  for (r = minr; r < maxr; r++)
+    for (c = minc; c < maxc; c++)
+      {
+	if ((r >= 0) && (c >= 0) && (r < b1.h) && (c < b1.w))
+	  p1 = pbm_getpixel (b1.bitmap, c, r);
+	else
+	  p1 = 0;		/* 0 = back ground colour */
+	if ((r - offy >= 0) && (c - offx >= 0) && (r - offy < b2.h) && (c - offx < b2.w))
+	  p2 = pbm_getpixel (b2.bitmap, c - offx, r - offy);
+	else
+	  p2 = 0;		/* background colour */
+	pbm_putpixel (d.bitmap, c - minc, r - minr, p1 != p2);
+      }
+  for (r = minr; r < maxr; r++)
+    for (c = minc; c < maxc; c++)
+      if (pbm_getpixel (d.bitmap, c - minc, r - minr))
+	for (i = -1; i <= 1; i++)
+	  for (j = -1; j <= 1; j++)
+	    if ((r + j >= 0) && (c + i >= 0) && (r + j < d.h) && (c + i < d.w) && ((i != 0) || (j != 0)) && (pbm_getpixel (d.bitmap, c + i - minc, r + j - minr)))
+	      count++;
+  pbm_freearray (&d.bitmap, d.h);
+  return count;
+}
+
+
+
+/* define an array for most matches, if it is a massive mark, then WXOR is called */
+#define S_SIZE 500
+
+static unsigned char scratch[S_SIZE][S_SIZE], sc2[S_SIZE][S_SIZE];
+
+
+
+
+/* Weighted AND-NOT */
+
+int 
+WAN_match (marktype b1, marktype b2)
+{
+  int r, c, i, j;
+  int minr, minc;
+  int maxr, maxc;
+  int offx, offy;
+  int p1, p2;
+  int count = 0;
+
+  offx = b1.xcen - b2.xcen;
+  offy = b1.ycen - b2.ycen;
+
+  minc = min (0, offx);
+  minr = min (0, offy);
+
+  maxc = max (b1.w, b2.w + offx);
+  maxr = max (b1.h, b2.h + offy);
+
+  if (((maxc - minc) >= S_SIZE) || ((maxr - minr) >= S_SIZE))
+    return WXOR_match (b1, b2);
+
+  for (r = minr; r < maxr; r++)
+    for (c = minc; c < maxc; c++)
+      {
+	scratch[r - minr][c - minc] = sc2[r - minr][c - minc] = 0;
+	if ((r >= 0) && (c >= 0) && (r < b1.h) && (c < b1.w))
+	  p1 = pbm_getpixel (b1.bitmap, c, r);
+	else
+	  p1 = 0;		/* 0 == background colour */
+	if ((r - offy >= 0) && (c - offx >= 0) && (r - offy < b2.h) && (c - offx < b2.w))
+	  p2 = pbm_getpixel (b2.bitmap, c - offx, r - offy);
+	else
+	  p2 = 0;
+
+	if ((p1 == 0) && (p2 == 1))	/* p1 not set, p2 = set */
+	  scratch[r - minr][c - minc] = 1;
+	if ((p1 == 1) && (p2 == 0))	/* p1 set, p2 not set */
+	  sc2[r - minr][c - minc] = 1;
+      }
+
+  count = 0;
+  for (r = minr; r < maxr; r++)
+    for (c = minc; c < maxc; c++)
+      if (scratch[r - minr][c - minc])
+	for (i = -1; i <= 1; i++)
+	  for (j = -1; j <= 1; j++)
+	    if ((r + j >= minr) && (c + i >= minc) && (r + j < maxr) && (c + i < maxc) && ((i != 0) || (j != 0)) && scratch[r - minr + j][c - minc + i])
+	      count++;
+
+  for (r = minr; r < maxr; r++)
+    for (c = minc; c < maxc; c++)
+      if (sc2[r - minr][c - minc])
+	for (i = -1; i <= 1; i++)
+	  for (j = -1; j <= 1; j++)
+	    if ((r + j >= minr) && (c + i >= minc) && (r + j < maxr) && (c + i < maxc) && ((i != 0) || (j != 0)) && sc2[r - minr + j][c - minc + i])
+	      count++;
+
+  return count;
+}
+
+/* oc 8 must be in a clock wise order, with oc[0] a corner */
+struct
+{
+  int x, y;
+}
+oc[8] =
+{
+  {
+    -1, -1
+  }
+  ,
+  {
+    0, -1
+  }
+  ,
+  {
+    1, -1
+  }
+  ,
+  {
+    1, 0
+  }
+  ,
+  {
+    1, 1
+  }
+  ,
+  {
+    0, 1
+  }
+  ,
+  {
+    -1, 1
+  }
+  ,
+  {
+    -1, 0
+  }
+};
+
+
+
+static void 
+xormatchscratch (marktype * b1, marktype * b2, int minr, int maxr, int minc, int maxc, int offx, int offy)
+{
+  int r, c, rmm, roo, coo;
+  int p1, p2;
+  Pixel **bm1 = b1->bitmap, **bm2 = b2->bitmap;
+  int w1 = b1->w, h1 = b1->h, w2 = b2->w, h2 = b2->h;
+
+  for (r = minr; r < maxr; r++)
+    {
+      rmm = r - minr;
+      roo = r - offy;
+      p1 = 0;
+      for (c = minc; c < 0; c++)
+	{
+	  coo = c - offx;
+	  scratch[rmm][c - minc] = sc2[rmm][c - minc] = 0;
+	  if ((coo >= 0) && (roo >= 0) && (coo < w2) && (roo < h2))
+	    p2 = pbm_getpixel (bm2, coo, roo);
+	  else
+	    p2 = 0;		/* background */
+	  scratch[rmm][c - minc] = p1 != p2;
+	}
+      for (c = 0; c < maxc; c++)
+	{
+	  coo = c - offx;
+	  scratch[rmm][c - minc] = sc2[rmm][c - minc] = 0;
+	  if ((r >= 0) && (c < w1) && (r < h1))
+	    p1 = pbm_getpixel (bm1, c, r);
+	  else
+	    p1 = 0;		/* background */
+	  if ((coo >= 0) && (roo >= 0) && (coo < w2) && (roo < h2))
+	    p2 = pbm_getpixel (bm2, coo, roo);
+	  else
+	    p2 = 0;		/* background */
+	  scratch[rmm][c - minc] = p1 != p2;
+	}
+    }
+}
+
+
+
+int 
+CSIS_match (marktype * b1, marktype * b2)
+{
+  int r, c, i;
+  int minr, minc;
+  int maxr, maxc;
+  int offx, offy, fepcount;
+  int totscratch = 0;
+
+
+  offx = b1->xcen - b2->xcen;
+  offy = b1->ycen - b2->ycen;
+
+  minc = min (0, offx);
+  minr = min (0, offy);
+
+  maxc = max (b1->w, b2->w + offx);
+  maxr = max (b1->h, b2->h + offy);
+
+  if (((maxc - minc) >= S_SIZE) || ((maxr - minr) >= S_SIZE))
+    return WXOR_match (*b1, *b2);
+
+  /* set the scratch array to 1 if there is an XOR match */
+
+  xormatchscratch (b1, b2, minr, maxr, minc, maxc, offx, offy);
+  /* We how have the XOR map. Scratch contains the number of neighbours, 1=1 neighbour set...etc */
+
+  /* CSIS rule 1, if FEP (four error pels) then exit */
+  fepcount = 0;
+  for (r = minr; r < maxr - 1; r++)
+    for (c = minc; c < maxc - 1; c++)
+      if ((scratch[r - minr][c - minc]) && (scratch[r - minr + 1][c - minc]) &&
+	  (scratch[r - minr][c - minc + 1]) && (scratch[r - minr + 1][c - minc + 1]))
+	{
+	  fepcount++;
+	  if (fepcount == 1)
+	    return 10001;
+	}
+
+  /* foreach set pixel, update scratch with the number of pels around in five dir's. 
+     FPN (five-pel neighbour hood) */
+  for (r = minr; r < maxr; r++)
+    for (c = minc; c < maxc; c++)
+      if (scratch[r - minr][c - minc])
+	{
+	  sc2[r - minr][c - minc] = 1;	/* itself */
+	  for (i = 1; i < 8; i += 3)
+	    if (((r + oc[i].y) >= minr) && ((c + oc[i].x) >= minc) && ((r + oc[i].y) < maxr) && ((c + oc[i].x) < maxc))
+	      if (scratch[r + oc[i].y - minr][c + oc[i].x - minc])
+		sc2[r - minr][c - minc]++;
+	}
+  /* now scratch has the value of the FPN - 1=single error, 5=4 neighbouring errors etc... */
+
+  /* set scratch and sc2 to be the same */
+  for (r = minr; r < maxr; r++)
+    for (c = minc; c < maxc; c++)
+      totscratch += scratch[r - minr][c - minc] = sc2[r - minr][c - minc];
+
+  for (r = minr; r < maxr; r++)
+    for (c = minc; c < maxc; c++)
+      {
+	/* CSIS rule 2i: an error pel has 2 or more neighbours---this num is the same as PMS */
+	if (scratch[r - minr][c - minc] >= 3)
+	  if ((r - minr >= 1) && (c - minc >= 1) && (r - minr < (maxr - 1)) && (c - minc < (maxc - 1)))
+	    {
+	      int i, numsep = 0;
+	      /* find how many neighbours a set pixel has, only check the 4 edges-FPN */
+	      for (i = 1; i < 8; i += 2)
+		if (scratch[r + oc[i].y - minr][c + oc[i].x - minc])	/* if a scratch pixel is set */
+		  {
+		    if ((scratch[r + oc[(i + 2) % 8].y - minr][c + oc[(i + 2) % 8].x - minc] == 0) &&
+			(scratch[r + oc[(i + 6) % 8].y - minr][c + oc[(i + 6) % 8].x - minc] == 0)
+		      )
+		      numsep++;
+		  }
+
+	      if ((b1->w >= 12) || (b2->w >= 12) || (b1->h >= 12) || (b2->h >= 12))
+		{
+
+		  /* PMS rule 2ii: at least two of its neigh. error p's aren't connected */
+		  if (numsep >= 2)
+		    {
+		      int i, j, p, p2, same;
+
+		      /* PMS rule 2(iii), look for regions in the original images of 3x3 the same */
+		      if ((c >= 0) && (r >= 0) && (c < b1->w) && (r < b1->h))
+			{
+			  p = pbm_getpixel (b1->bitmap, c, r);
+			  same = 0;
+			  for (i = -1; i <= 1; i++)
+			    for (j = -1; j <= 1; j++)
+			      {
+				if ((c + i >= 0) && (r + j >= 0) && (c + i < b1->w) && (r + j < b1->h))
+				  p2 = pbm_getpixel (b1->bitmap, c + i, r + j);
+				else
+				  p2 = 0;
+				if (p2 == p)
+				  same++;
+			      }	/* i,j loop */
+			  /* PMS rule 2(iii) */
+			  if (same == 9)
+			    {
+			      return 10002;
+			    }
+			}	/* (*b1) in range */
+
+		      if ((c - offx >= 0) && (r - offy >= 0) && (c - offx < b2->w) && (r - offy < b2->h))
+			{
+			  p = pbm_getpixel (b2->bitmap, c - offx, r - offy);
+			  same = 0;
+			  for (i = -1; i <= 1; i++)
+			    for (j = -1; j <= 1; j++)
+			      {
+				if ((c + i - offx >= 0) && (r + j - offy >= 0) && (c + i - offx < b2->w) && (r + j - offy < b2->h))
+				  p2 = pbm_getpixel (b2->bitmap, c + i - offx, r + j - offy);
+				else
+				  p2 = 0;
+				if (p2 == p)
+				  same++;
+			      }	/* i,j loop */
+			  /* PMS rule 2(iii) */
+			  if (same == 9)
+			    {
+			      return 10003;
+			    }
+			}
+		    }
+		}
+	      else
+		{		/* do the CSIS rule */
+		  /* CSIS rule 2ii: at least two of its neigh. error p's aren't connected */
+		  if (numsep >= 2)
+		    {
+		      int i, p, p2, same;
+
+		      /* PMS rule 2(iii), look for regions in the original images of 3x3 the same */
+		      if ((c >= 0) && (r >= 0) && (c < b1->w) && (r < b1->h))
+			{
+			  p = pbm_getpixel (b1->bitmap, c, r);
+			  same = 1;
+			  for (i = 1; i < 8; i += 2)
+			    if ((c + oc[i].x >= 0) && (r + oc[i].y >= 0) && (c + oc[i].x < b1->w) && (r + oc[i].y < b1->h))
+			      p2 = pbm_getpixel (b1->bitmap, c + oc[i].x, r + oc[i].y);
+			    else
+			      p2 = 0;
+			  if (p2 == p)
+			    same++;
+
+			  /* CSIS rule 2(iii) */
+			  if (same == 5)
+			    {
+			      return 10002;
+			    }
+			}
+
+		      if ((c - offx >= 0) && (r - offy >= 0) && (c - offx < b2->w) && (r - offy < b2->h))
+			{
+			  p = pbm_getpixel (b2->bitmap, c - offx, r - offy);
+			  same = 1;
+			  for (i = 1; i < 8; i += 2)
+			    if ((c + oc[i].x - offx >= 0) && (r + oc[i].y - offy >= 0) && (c + oc[i].x - offx < b2->w) && (r + oc[i].y - offy < b2->h))
+			      p2 = pbm_getpixel (b2->bitmap, c + oc[i].x - offx, r + oc[i].y - offy);
+			    else
+			      p2 = 0;
+			  if (p2 == p)
+			    same++;
+
+			  /* CSIS rule 2(iii) */
+			  if (same == 5)
+			    {
+			      return 10003;
+			    }
+			}
+		    }
+		}
+	    }
+      }
+
+  return totscratch;
+}
Index: /indexers/branches/3.03a/mg/src/images/match.h
===================================================================
--- /indexers/branches/3.03a/mg/src/images/match.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/match.h	(revision 14757)
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * match.h -- Functions related to matching marks
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef __MATCH_H
+#define __MATCH_H
+
+#include "marklist.h"
+#include "pbmtools.h"
+#include "utils.h"
+
+
+/*
+   #define NOT_SCREENED(b1,b2) ((abs(b1.w-b2.w)<=4) && (abs(b1.h-b2.h)<=4))
+ */
+
+#define NOT_SCREENED(b1,b2) ((abs(b1.xcen-b2.xcen)+abs(b1.ycen-b2.ycen))<=3)
+
+#define MATCH_VAL 1000
+#define MATCH(b1,b2) (CSIS_match(b1,b2))
+
+int XOR_match (marktype b1, marktype b2);
+int WXOR_match (marktype b1, marktype b2);
+int WAN_match (marktype b1, marktype b2);
+int PMS_match (marktype b1, marktype b2);
+int CSIS_match (marktype * b1, marktype * b2);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/images/mgbilevel.1
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgbilevel.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgbilevel.1	(revision 14757)
@@ -0,0 +1,116 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgbilevel 1 \*(Dt CITRI
+.SH NAME
+mgbilevel \- compresses a bilevel image using a specified template
+.SH SYNOPSIS
+.B mgbilevel
+.B \-e
+[
+.B \-t
+.I \*(lqstring\*(rq
+]
+.I infile
+[
+.I \>compressed-outfile
+]
+.nf
+or
+.fi
+.B mgbilevel
+.B \-d
+.I compressed-infile
+[
+.I \>outfile
+]
+.SH DESCRIPTION
+.B mgbilevel
+performs (up to) a two-stage template-based compression.  The
+user can specify the template to be used in the compression process.  The
+default template size is a two-stage template 22/10.  The compressed file
+contains the template type in the stream.  The output files are written
+to
+.IR stdout .
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-t\fP \fI\*(lqstring\*(rq\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-e
+Compresses
+.I infile
+using a template specified, and writes to
+.IR compressed-outfile .
+.TP
+.B \-d
+Decompresses
+.I compressed-infile
+using the template contained in the compressed file.  Writes to
+.IR outfile .
+.TP
+\fB\-t \fP\fI\*(lqstring\*(rq\fP
+This option specifies which template combination is to
+be used in the compression.  Five different characters
+can occur in the string: `.' for a pixel not
+included in the template, `p' for a pixel included in the 1st
+level template, `2' for a pixel included in the 2nd level
+template (a subset of the 1st level), `*' denoting the position
+of the
+.I current
+pixel, and a `;' denoting the end of each template line.
+The default template is a two-level 22/10 template:
+.IP
+.RS
+.nf
+\&.ppppp.;
+pp222pp;
+p22222p;
+p22*.\|.\|.;
+.fi
+.RE
+.IP
+This would be specified on the command line as:
+.nf
+\&\fB\-T\fP ".ppppp.;pp222pp;p22222p;p22*.\|.\|.;"
+.fi
+.TP
+.I infile
+This is the input
+.I .pbm
+file to be compressed.
+.TP
+.I outfile
+This is the decompressed
+.I .pbm
+file.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/images/mgbilevel.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgbilevel.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgbilevel.c	(revision 14757)
@@ -0,0 +1,149 @@
+/**************************************************************************
+ *
+ * mgbilevel.c -- Program to compress/decompress bilevel images
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "utils.h"
+#include "pbmtools.h"
+#include "arithcode.h"
+#include "bilevel.h"
+
+
+
+static char default_template[] =
+{
+  ".ppppp.;"
+  "pp222pp;"
+  "p22222p;"
+  "p22*...;"
+};
+
+void 
+Encode_bitmap (marktype b, char template[])
+{
+  InitArithEncoding ();
+
+  bl_compress (b, template);
+
+  CloseDownArithEncoding ();
+}
+
+void 
+Decode_bitmap (marktype * b)
+{
+  InitArithDecoding ();
+
+  bl_decompress (b);
+
+  CloseDownArithDecoding ();
+}
+
+
+void 
+usage ()
+{
+  fprintf (stderr,
+	   "usage:\n"
+	   "       mgbilevel -e  [-t \"string\"]  infile      >compressed\n"
+	   "or\n"
+	   "       mgbilevel -d                 compressed  >outfile\n");
+  exit (1);
+}
+
+#define BUF_SIZE 65536
+
+void 
+main (int argc, char *args[])
+{
+  marktype d;
+  char *filename = NULL, *template = NULL;
+  Pixel **bitmap;
+  int encode = 0, decode = 0, i;
+  char buffer[BUF_SIZE];
+
+  if (argc < 2)
+    usage ();
+  template = default_template;
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (args[i], "-e") == 0)
+	encode = 1;
+      else if (strcmp (args[i], "-d") == 0)
+	decode = 1;
+      else if (strcmp (args[i], "-h") == 0)
+	usage ();
+      else if (strcmp (args[i], "-t") == 0)
+	{
+	  template = args[i + 1];
+	  i++;
+	}
+      else if (args[i][0] == '-')
+	error_msg (args[0], "unknown switch:", args[i]);
+      else if (!filename)
+	filename = args[i];
+      else
+	error_msg (args[0], "only specify 1 filename", "");
+    }
+  if (encode == decode)
+    {
+      fprintf (stderr, "You must specify either encode XOR decode.\n");
+      exit (1);
+    }
+
+  if (!filename)
+    {
+      fprintf (stderr, "You must specify a filename.\n");
+      exit (1);
+    }
+
+  if (encode)
+    {
+      bitmap = pbm_readnamedfile (filename, &d.w, &d.h);
+      if (bitmap == NULL)
+	error_msg (args[0], "problem reading bitmap", "");
+
+      arith_out = stdout;
+      setbuffer (stdout, buffer, BUF_SIZE);
+      magic_write (stdout, MAGIC_BILEVEL);
+      if (bitmap)
+	{
+	  d.bitmap = bitmap;
+	  Encode_bitmap (d, template);
+	}
+    }
+  else if (decode)
+    {
+      FILE *tpin;
+      tpin = fopen (filename, "rb");
+      if (!tpin)
+	error_msg ("mgbilevel", "Can't open file:", filename);
+      arith_in = tpin;
+      setbuffer (tpin, buffer, BUF_SIZE);
+      magic_check (tpin, MAGIC_BILEVEL);
+      Decode_bitmap (&d);
+      fclose (tpin);
+
+      setbuffer (stdout, buffer, BUF_SIZE);
+      pbm_writefile (stdout, d.bitmap, d.w, d.h);
+    }
+}
Index: /indexers/branches/3.03a/mg/src/images/mgfelics.1
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgfelics.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgfelics.1	(revision 14757)
@@ -0,0 +1,103 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgfelics 1 \*(Dt CITRI
+.SH NAME
+mgfelics \- fast and efficient lossless image (de)compression
+.SH SYNOPSIS
+.B mgfelics
+.B \-e
+[
+.BI \-k " n"
+]
+.I infile
+[
+.I \>compressed-outfile
+]
+.br
+or
+.br
+.B mgfelics
+.B \-d
+.I compressed-infile
+[
+.I \>outfile
+]
+.SH DESCRIPTION
+.B mgfelics
+is a lossless compression process which can (de)compress portable
+bitmap files in
+.I pgm
+format.
+.B mgfelics
+writes to
+.IR stdout .
+.SH OPTIONS
+.TP "\w'\fB\-k\fP \fIn\fP'u+2n"
+.BI \-k " n"
+An integer parameter (< 32) which controls the compression speed and
+ratio.  The value of
+.I n
+is included in the output stream, and therefore is not needed in the
+decompression stage.  The default value of
+.I n
+is equal to the number of bits required to represent each grey level.
+.TP
+.B \-e
+Encodes the file
+.IR infile ,
+sending the output to
+.IR stdout .
+.TP
+.B \-d
+Decodes the file from
+.IR compressed-infile ,
+sending the output to
+.IR stdout .
+.SH NOTE
+.B mgfelics
+uses a combination of adjusted binary and Rice codes, the choice of
+which for any given pixel depends on the environment as determined by
+the intensity values of neighbouring pixels.  The result is a very
+fast and lossless algorithm for compressing grayscale images.  The
+optional parameter
+.BI \-k " n"
+corresponds to the maximum exponent of the same name in Rice encoding.
+Smaller values of
+.BI \-k " n"
+can result in significant improvement in compression times with a
+corresponding loss in compression ratio.  However the reduction in
+compression ratio with a small
+.BI \-k " n"
+parameter may be insignificant for many images.
+.SH REFERENCES
+Algorithm by Paul G. Howard and Jeffrey Scott Vitter
+of Brown University, RI, and Duke University, NC, respectively.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/images/mgfelics.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgfelics.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgfelics.c	(revision 14757)
@@ -0,0 +1,155 @@
+/**************************************************************************
+ *
+ * mgfelics.c -- Program to compress/decompress grey scale images
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "utils.h"
+
+
+#define MAXKVALUE 32
+
+
+
+void encode (unsigned int *line, int width, int height, int maxval, int maxk,
+	     FILE * fp_in, FILE * fp_out, int (*get) (FILE *));
+
+void decode (unsigned int *line, int width, int height, int maxval, int maxk,
+	     FILE * fp_in, FILE * fp_out);
+
+
+void 
+usage (char *prog)
+{
+  fprintf (stderr, "usage:\n");
+  fprintf (stderr, "\t%s -e [-k n]   infile    [>compressed]\n"
+	   "or\n"
+	   "\t%s -d  compressed-infile   [>outfile]\n", prog, prog);
+  exit (1);
+}
+
+
+
+
+int 
+main (int argc, char **argv)
+{
+  FILE *fp_in = (stdin), *fp_out = (stdout);
+  int width, height, maxval;
+  u_long magic;
+  char *filename = NULL;
+  unsigned int *line;
+  int maxk = 0;
+  int i;
+  int encode_flag = 0, decode_flag = 0;
+
+  if (argc < 2)
+    usage (argv[0]);
+
+  for (i = 1; i < argc; i++)
+    {
+      if (!strcmp (argv[i], "-h"))
+	usage (argv[0]);
+      else if (!strcmp (argv[i], "-e"))
+	encode_flag = 1;
+      else if (!strcmp (argv[i], "-d"))
+	decode_flag = 1;
+      else if (!strcmp (argv[i], "-k"))
+	{
+	  maxk = atoi (argv[++i]);
+	}
+      else if (argv[i][0] == '-')
+	error_msg (argv[0], "unknown switch:", argv[i]);
+      else if (!filename)
+	filename = argv[i];
+      else
+	error_msg (argv[0], "too many filenames specified.", "");
+    }
+
+  if (encode_flag == decode_flag)
+    error_msg (argv[0], "please specify either encode XOR decode.", "");
+
+  if (!filename)
+    error_msg (argv[0], "please specify a filename.", "");
+
+  if ((encode_flag) && (maxk >= MAXKVALUE))
+    {				/* to fit into 32 bit integers */
+      fprintf (stderr, "%s: k value of %d is too large; it must be less than %d\n",
+	       argv[0], maxk, MAXKVALUE);
+      exit (1);
+    }
+
+
+  if ((fp_in = fopen (filename, "rb")) == NULL)
+    error_msg (argv[0], "unable to open file:", filename);
+
+  /* read file header to determine the type and dimensions */
+
+
+  magic = magic_read (fp_in);
+  if (magic != MAGIC_FELICS)
+    {
+      rewind (fp_in);
+      magic = getmagicno_short_pop (fp_in);
+    }
+
+  if ((decode_flag && (magic != MAGIC_FELICS)) ||
+      (encode_flag && ((magic != MAGIC_P2) && (magic != MAGIC_P5))))
+    {
+      fclose (fp_in);
+      error_msg (argv[0], encode_flag ? "only PGM files can be used." : "only felics compressed files can be used.", "");
+    }
+
+  width = gethint (fp_in);
+  height = gethint (fp_in);
+  maxval = gethint (fp_in);
+
+  if ((line = (unsigned int *) malloc (width * sizeof (int *))) == NULL)
+    {
+      fclose (fp_in);
+      error_msg (argv[0], "unable to allocate memory,", "");
+    }
+
+
+  if (encode_flag)
+    {
+      magic_write (fp_out, MAGIC_FELICS);
+      fprintf (fp_out, "%d\n%d\n%d\n%d\n", width, height, maxval, maxk);
+      encode (line, width, height, maxval, maxk, fp_in, fp_out,
+	      magic == MAGIC_P2 ? getint : fgetc);
+    }
+  else if (decode_flag)
+    {
+      if (maxk)
+	warn (argv[0], "k value not required for decompression, ignored.", "");
+
+      maxk = gethint (fp_in);
+      fprintf (fp_out, "P%d\n%d %d\n%d\n", maxval < 256 ? 5 : 2,
+	       width, height, maxval);
+      decode (line, width, height, maxval, maxk, fp_in, fp_out);
+    }
+
+
+  fclose (fp_in);
+  fclose (fp_out);
+
+  return 0;
+}
Index: /indexers/branches/3.03a/mg/src/images/mgtic.1
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgtic.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgtic.1	(revision 14757)
@@ -0,0 +1,137 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgtic 1 \*(Dt CITRI
+.SH NAME
+mgtic \- textual image compression.
+.SH SYNOPSIS
+.B mgtic
+.B \-e
+[
+.B \-L
+]
+[
+.B \-Q
+]
+[
+.B \-X
+]
+.I libraryfile
+.I infile
+.if n .ti +9n
+[
+.I \>compressed\-outfile
+]
+.nf
+or
+.fi
+.B mgtic
+.B \-d
+[
+.B \-L
+]
+[
+.BI \-X " libraryfile"
+]
+.I compressed-infile
+.if n .ti +9n
+[
+.I \>outfile
+]
+.SH DESCRIPTION
+This is the main routine in the
+.B mgtic
+system.
+.B mgtic
+is used to
+processes a series of files, and by using the
+.I libraryfile
+produced by
+.BR mgticbuild (1),
+compresses input files with respect to the marks contained in the
+library.  On the CCITT test faxes, lossless mode achieved around 20:1
+compression, and lossy, around 40:1 compression.  On more textual
+images, the amount of compression is determined by the resolution of
+the original file, and the amount of noise in the image.  By default,
+.B mgtic
+will reconstruct a lossy version of the image.  This
+can be changed to lossless by using the
+.B \-L
+option.
+.SH OPTIONS
+Options may appear in any order, but must come before the input
+filenames.
+.TP "\w'\fB\-X\fP \fI[libraryfile]\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-e
+Encode
+.I infile
+with respect to the library.
+.TP
+.B \-d
+Decodes
+.IR compressed-infile
+with respect to the library.
+.TP
+.B \-l
+This specifies lossy mode, and is the default mode for (de)compression.
+Do not generate the residue.  If used in encoding mode, does not store
+the residue in the output.  If used in decoding mode, the residue (if
+it exists) is ignored.
+.TP
+.B \-L
+Use lossless mode for (de)compression, which generates the residue.
+If used in encoding mode, this stores the residue in the compressed
+output.  If used in decoding mode (assuming the residue is present),
+this allows the original file to be recovered exactly.
+.TP
+.BI \-R\  filename
+Stores the residue as an external file
+.I filename
+which could possibly be stored on another medium.  During
+decompression, if the residue file specified does not relate to the
+compressed file, the resulting decompressed image will be a mess.
+Note that only the width and height of the residue image is checked.
+.TP
+.BI \-Q
+Uses a quicker form of compression.  This option decreases the time
+spent looking for a good match during encoding.  On average this
+option decreases compression ratios, but increases compression speed.
+.TP
+.BI \-X " [libraryfile]"
+Use an external library file, instead of (de)compressing the library
+within the normal stream.  When decoding, the
+.B \-X
+option must be followed by the
+.IR libraryfile .
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/images/mgtic.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgtic.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgtic.c	(revision 14757)
@@ -0,0 +1,596 @@
+/**************************************************************************
+ *
+ * mgtic.c -- Program to compress/decompress textual images
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************
+ *
+ * This file is the basis of mgtic, which compresses the components of an
+ * image. 
+ * The compressed file contains the following sections:
+ *         mgtic magic_no
+ *         mgtic version
+ *         lossy/lossless flag 
+ *         internal/external library flag 
+ *         cols, rows, number of marks, library size
+ *         [library sequence]
+ *         symbol sequence
+ *         offset sequence
+ *         [residue bitmap]
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "marklist.h"
+#include "pbmtools.h"
+#include "extractor.h"
+#include "utils.h"
+#include "match.h"
+#include "sortmarks.h"
+#include "codesyms.h"
+#include "arithcode.h"
+#include "codeoffsets.h"
+#include "bilevel.h"
+
+static char library_template[] =
+{
+  ".ppppp.;"
+  "pp222pp;"
+  "p22222p;"
+  "p22*...;"
+};
+
+void 
+usage ()
+{
+  fprintf (stderr, "usage: \n"
+	"\tmgtic -e [-L] [-Q] [-X]  libraryfile   infile    [>compressed]\n"
+	   "or\n"
+	   "\tmgtic -d [-L] [-X libraryfile]  compressed  [>outfile]\n");
+  exit (1);
+}
+
+
+/* encode the list of marks 'list', w.r.t. the library 'library' */
+void 
+match_sequence (marklistptr list, marklistptr library, marklistptr * symbol_list, Pixel ** recon, int quick)
+{
+  int carryx, carryy, gap;
+  int lastx = 0, lasty = 0;
+  int i, j;
+  marktype d, d2;
+  marklistptr liststep, librarystep;
+  int score, found;
+  int r, c;
+  int p;
+
+  carryx = carryy = 0;
+  gap = max (1, marklist_length (list) / 10);
+
+  for (liststep = list, i = 0; liststep; liststep = liststep->next, i++)
+    {
+      if (V)
+	if (!(i % gap))
+	  fprintf (stderr, ".");
+      d = liststep->data;
+
+      found = -1;
+      score = INT_MAX;
+      for (librarystep = library, j = 0; librarystep; librarystep = librarystep->next, j++)
+	{
+	  d2 = librarystep->data;
+
+	  if (NOT_SCREENED (d2, d))
+	    if ((p = MATCH (&d, &d2)) < MATCH_VAL)
+	      {
+		if (p < score)
+		  {
+		    score = p;
+		    found = j;
+		    if (quick)
+		      break;
+		  }
+	      }
+	}
+      /*
+         if(found<0){
+         for(librarystep=library,j=0; librarystep; librarystep=librarystep->next,j++){
+         d2=librarystep->data;
+
+         if((p=MATCH(&d,&d2))<MATCH_VAL){
+         if(p<score){
+         score=p;found=j; if(quick) break;
+         }
+         }
+         }
+         }
+       */
+      if (found >= 0)
+	{
+	  liststep->data.symnum = found;
+	  marklist_getat (library, found, &d2);
+	  d2.symnum = found;
+
+	  d2.xoffset = d.xpos - lastx + carryx;		/* propagate changes to next mark */
+	  d2.yoffset = d.ypos - lasty + carryy;
+	  carryx = (d2.xcen - d.xcen);	/* offet centroids because thats where we match them! */
+	  carryy = (d2.ycen - d.ycen);
+	  d2.xoffset -= carryx;	/* make the changes to this mark */
+	  d2.yoffset -= carryy;
+	  lastx = d.xpos + d2.w;
+	  lasty = d.ypos;
+
+	  marklist_add (symbol_list, d2);
+
+	  /* add to the reconstructed image--this is the lossy version */
+	  for (r = 0; r < d2.h; r++)
+	    for (c = 0; c < d2.w; c++)
+	      if (pbm_getpixel (d2.bitmap, c, r))
+		pbm_putpixel_trunc (recon, d.xpos + c - carryx, d.ypos + r - carryy, 1, d2.w, d2.h);
+	}
+      else
+	{
+	  /* didn't match at all..hopefully noise */
+	  if ((liststep->data.w >= 10) || (liststep->data.w >= 10))
+	    {
+	      fprintf (stderr, "mgtic: warning, unable to match a char.\n");
+	      write_library_mark (stderr, liststep->data);
+	    }
+	  if (V)
+	    fprintf (stderr, "x");
+	  liststep->data.symnum = -1;
+	}
+    }
+  if (V)
+    fprintf (stderr, "\n");
+}
+
+
+
+
+void 
+main (int argc, char *args[])
+{
+  int i, n, r, c, ch;
+  FILE *inf;
+  marklistptr library = NULL, list = NULL, step = NULL;
+  marklistptr symbol_list = NULL;
+  marktype d, d2;
+  Pixel **bitmap, **recon, **bitmapcopy;
+  char *splitfilename = NULL;
+  int cols, rows, count, librarysize, lossy = 1;
+  int quick = 0;
+  int ticencode = 0, ticdecode = 0, external = 0;
+  char *libraryname = NULL, *infile = NULL;
+  char *s1 = NULL, *s2 = NULL;
+  char bufferin[BUFSIZ], bufferout[BUFSIZ];
+
+  if (argc < 2)
+    usage ();
+
+  while ((ch = getopt (argc, args, "edlLQhvXR:")) != -1)
+    switch (ch)
+      {
+      case 'e':
+	ticencode = 1;
+	break;
+      case 'd':
+	ticdecode = 1;
+	break;
+      case 'l':
+	lossy = 1;
+	break;
+      case 'L':
+	lossy = 0;
+	break;
+      case 'Q':
+	quick = 1;
+	break;
+      case 'v':
+	V = 1;
+	break;
+      case 'X':
+	external = 1;
+	break;
+      case 'R':
+	splitfilename = optarg;
+	break;
+      case 'h':
+      case '?':
+	usage ();
+      }
+
+  for (i = 1; i < argc; i++)
+    if (args[i][0] != '-')
+      if (strcmp (args[i - 1], "-R"))
+	{			/* ignore arg following -R, ie. -R <filename> */
+	  if (!s1)
+	    s1 = args[i];
+	  else if (!s2)
+	    s2 = args[i];
+	  else
+	    error_msg (args[0], "too many filenames", "");
+	}
+
+  if (ticencode == ticdecode)
+    error_msg (args[0], "please specify either encode XOR decode", "");
+
+  if (ticencode)
+    {
+	  /*****************
+	    ENCODING STAGE
+	  *****************/
+      long PrevBits = 0;
+      long BITS_header = 0, BITS_symbols = 0, BITS_offsets = 0, BITS_residue = 0,
+        BITS_footer = 0, BITS_library = 0;
+
+      libraryname = s1;
+      if (!libraryname)
+	error_msg (args[0], "please specify a library file", "");
+      infile = s2;
+      if (!infile)
+	error_msg (args[0], "please specify a file name", "");
+
+      inf = fopen (infile, "rb");
+      if (inf == NULL)
+	error_msg (args[0], "Trouble opening file:", infile);
+      setbuf (inf, bufferin);
+
+      count = librarysize = read_library (libraryname, &library);
+
+      if (V)
+	fprintf (stderr, "%s: processing...\n", args[0]);
+
+      if (pbm_isapbmfile (inf))
+	{
+	  if (V)
+	    fprintf (stderr, "reading file %s...\n", infile);
+	  bitmap = pbm_readfile (inf, &cols, &rows);
+	  fclose (inf);
+
+	  bitmapcopy = pbm_copy (bitmap, cols, rows);
+
+	  if (V)
+	    fprintf (stderr, "extracting...");
+	  ExtractAllMarks (bitmap, &list, cols, rows);
+	  if (V)
+	    fprintf (stderr, "(%d marks)\n", marklist_length (list));
+
+	  /* sort into reading order */
+	  if (V)
+	    fprintf (stderr, "sorting...\n");
+	  list = sortmarks (list);
+
+	  pbm_freearray (&bitmap, rows);	/* clear old version */
+	  bitmap = bitmapcopy;	/* point to the copy */
+	  recon = pbm_allocarray (cols, rows);
+
+	  if (V)
+	    fprintf (stderr, "matching...");
+
+	  match_sequence (list, library, &symbol_list, recon, quick);
+
+
+	  PrevBits = 0;
+	  setbuf (stdout, bufferout);
+	  /* start output */
+	  magic_write (stdout, MAGIC_TIC);
+	  InitArithEncoding ();
+
+	  EncodeGammaDist (1);	/* version 1 of the program */
+	  EncodeGammaDist (lossy);	/* lossy=1 = no residue */
+	  EncodeGammaDist (external);	/* 1== external file */
+
+	  count = marklist_length (symbol_list);
+	  if (V)
+	    fprintf (stderr, "encoding cols, rows, and number of symbols=%d\n", count);
+
+	  EncodeGammaDist (cols);
+	  EncodeGammaDist (rows);
+	  EncodeGammaDist (count);
+	  EncodeGammaDist (librarysize);
+
+	  BITS_header = CountOfBitsOut - PrevBits;
+	  PrevBits = CountOfBitsOut;
+
+
+	  /* output the library sequence */
+	  if (external == 0)
+	    {
+	      if (V)
+		fprintf (stderr, "encoding library\n");
+
+	      bl_clearmodel ();
+	      bl_writetemplate (library_template);
+	      for (step = library; step; step = step->next)
+		bl_compress_mark (step->data);
+	      bl_freemodel ();
+	      BITS_library = CountOfBitsOut - PrevBits;
+	      PrevBits = CountOfBitsOut;
+	    }
+
+	  /* output the symbol sequence */
+	  if (V)
+	    fprintf (stderr, "encoding symbol sequence\n");
+	  InitPPM ();
+	  EncodeSymbols (symbol_list, count);
+	  BITS_symbols = CountOfBitsOut - PrevBits;
+	  PrevBits = CountOfBitsOut;
+
+
+	  /* output the offset sequence */
+	  if (V)
+	    fprintf (stderr, "encoding offset sequence\n");
+	  EncodeOffsets (symbol_list, count);
+	  BITS_offsets = CountOfBitsOut - PrevBits;
+	  PrevBits = CountOfBitsOut;
+
+	  EncodeChecksum ();	/* code lossy checksum */
+
+	  /* calculate the residue...and compress it---if need be! */
+	  if (!lossy)
+	    {
+	      if (V)
+		fprintf (stderr, "encoding residue...\n");
+
+	      d.bitmap = bitmap;
+	      d.h = rows;
+	      d.w = cols;
+	      d2.bitmap = recon;
+	      d2.h = rows;
+	      d2.w = cols;
+
+	      if (splitfilename)
+		{
+		  FILE *temp;
+
+		  CloseDownArithEncoding ();
+		  fclose (stdout);
+		  /* no residue result */
+		  BITS_footer = CountOfBitsOut - PrevBits;
+
+		  temp = fopen (splitfilename, "wb");
+		  if (temp == NULL)
+		    error_msg (args[0], "Trouble creating file:", splitfilename);
+
+		  arith_out = temp;
+		  InitArithEncoding ();
+		  bl_clair_compress (d, d2);
+		  CloseDownArithEncoding ();
+		  BITS_residue = CountOfBitsOut;
+		  fclose (temp);
+		}
+	      else
+		{
+		  bl_clair_compress (d, d2);
+		  BITS_residue = CountOfBitsOut - PrevBits;
+		  PrevBits = CountOfBitsOut;
+		  EncodeChecksum ();	/* code lossless checksum */
+		  CloseDownArithEncoding ();
+		  BITS_footer = CountOfBitsOut - PrevBits;
+		}
+	    }
+	  else
+	    {
+	      if (V)
+		fprintf (stderr, "not encoding residue..lossy mode\n");
+	      CloseDownArithEncoding ();
+	      BITS_footer = CountOfBitsOut - PrevBits;
+	    }
+
+	  /* because we edit the values above */
+	  CountOfBitsOut = BITS_header + BITS_library + BITS_symbols + BITS_offsets + BITS_residue + BITS_footer;
+
+	  fprintf (stderr, "bits: header=%ld, library=%ld, "
+		   "symbols=%ld, offsets=%ld, residue=%ld, footer=%ld\n",
+		   BITS_header, BITS_library, BITS_symbols,
+		   BITS_offsets, BITS_residue, BITS_footer);
+	  fprintf (stderr, "total bits: %ld, ", CountOfBitsOut);
+	  fprintf (stderr, "Lossy CR: %4.2f", (cols * rows) / (float) (CountOfBitsOut - BITS_residue));
+	  if (external)
+	    fprintf (stderr, " (excluding external lib)");
+	  fprintf (stderr, ", Lossless CR: %4.2f\n", (!lossy) * (cols * rows) / (float) (CountOfBitsOut));
+	}
+      else
+	error_msg (args[0], "unknown format of bitmap--expecting PBM.", "");
+    }
+  else
+    {
+	  /*****************
+	    DECODING STAGE
+	  *****************/
+      int lastx, lasty;
+      librarysize = 0;
+
+      if (external)
+	{
+	  libraryname = s1;
+	  infile = s2;
+	  count = librarysize = read_library (libraryname, &library);
+	}
+      else
+	{
+	  infile = s1;
+	  if (infile && s2)
+	    error_msg (args[0], "too many filenames", "");
+	}
+
+      if (!freopen (infile, "rb", stdin))
+	error_msg (args[0], "Trouble opening file:", infile);
+
+
+      if (V)
+	fprintf (stderr, "decompressing...\n");
+
+      setbuf (stdin, bufferin);
+      magic_check (stdin, MAGIC_TIC);
+
+      InitArithDecoding ();
+
+      {
+	int version = DecodeGammaDist ();
+	if (version != 1)
+	  error_msg (args[0], "Need later version of decompressor.", "");
+      }
+
+      {
+	int templossy = DecodeGammaDist ();
+	if (!lossy)
+	  lossy = templossy;	/* can only choose if encoded file is lossless */
+	if (V)
+	  {
+	    if (lossy)
+	      fprintf (stderr, "lossy mode\n");
+	    else
+	      fprintf (stderr, "lossless mode\n");
+	  }
+      }
+
+      if (DecodeGammaDist ())
+	{			/* if compressed file doesn't contain library */
+	  if (!external)
+	    error_msg (args[0], "compressed file doesn't contain library, specify externally", "");
+	  external = 1;
+	}
+      else
+	{			/* if compressed file contains library */
+	  if (external)
+	    fprintf (stderr, "ignoring external library file\n");
+	  external = 0;
+	}
+
+      cols = DecodeGammaDist ();
+      rows = DecodeGammaDist ();
+      count = DecodeGammaDist ();
+
+      i = DecodeGammaDist ();	/* librarysize */
+      if (external)
+	{
+	  if (i > librarysize)
+	    error_msg (args[0], "external library file is too small!", "");
+	  else if (i < librarysize)
+	    fprintf (stderr, "%s: warning, expecting a different (smaller) library.\n", args[0]);
+	}
+      librarysize = i;
+
+      if (V)
+	fprintf (stderr, "cols %d, rows %d, num syms %d, library size %d\n", cols, rows, count, librarysize);
+
+      /* decode library */
+      if (external == 0)
+	{
+	  if (V)
+	    fprintf (stderr, "reading library\n");
+	  bl_clearmodel ();
+	  bl_readtemplate ();
+	  for (n = 0; n < librarysize; n++)
+	    {
+	      bl_decompress_mark (&d);
+	      d.symnum = n;
+	      if (library == NULL)
+		step = marklist_add (&library, d);
+	      else
+		step = marklist_add (&step, d);
+	    }
+	  bl_freemodel ();
+	  if (V)
+	    fprintf (stderr, "read %d marks from library\n", marklist_length (library));
+	}
+
+      recon = pbm_allocarray (cols, rows);
+
+      /* decode symbols */
+      InitPPM ();
+      if (V)
+	fprintf (stderr, "decompressing %d symbols\n", count);
+      symbol_list = DecodeSymbols (count);
+
+      /* decode offsets */
+      if (V)
+	fprintf (stderr, "reading offsets...\n");
+      DecodeOffsets (symbol_list, count);
+      lastx = lasty = 0;
+      for (step = symbol_list; step; step = step->next)
+	{
+	  lastx = lastx + step->data.xoffset;
+	  lasty = lasty + step->data.yoffset;
+
+	  marklist_getat (library, step->data.symnum, &d2);
+	  for (r = 0; r < d2.h; r++)
+	    for (c = 0; c < d2.w; c++)
+	      if (pbm_getpixel (d2.bitmap, c, r))
+		pbm_putpixel_trunc (recon, lastx + c, lasty + r, 1, cols, rows);	/* we don't care, already warned them! */
+	  lastx += d2.w;
+	}
+
+      DecodeChecksum (args[0]);
+
+      /* decode the residue */
+      if (!lossy)
+	{
+	  if (V)
+	    fprintf (stderr, "decoding residue...\n");
+
+	  bitmap = pbm_allocarray (cols, rows);
+	  d.bitmap = bitmap;
+	  d.w = d2.w = cols;
+	  d.h = d2.h = rows;
+
+	  d2.bitmap = recon;
+
+	  /* NOTE: the 2nd argument is clairvoyantly compressed */
+	  if (splitfilename)
+	    {
+	      FILE *temp;
+
+	      CloseDownArithDecoding ();
+	      fclose (stdin);
+
+	      temp = fopen (splitfilename, "rb");
+	      if (temp == NULL)
+		error_msg (args[0], "Trouble opening file:", splitfilename);
+
+	      arith_in = temp;
+	      InitArithDecoding ();
+	      bl_clair_decompress (d, d2);
+	      CloseDownArithDecoding ();
+	      fclose (temp);
+	    }
+	  else
+	    {
+	      bl_clair_decompress (d, d2);
+	      DecodeChecksum (args[0]);
+	      CloseDownArithDecoding ();
+	    }
+	  pbm_freearray (&recon, rows);
+	  recon = bitmap;	/* point to the bitmap */
+	}
+      else
+	{
+	  CloseDownArithDecoding ();
+	}
+
+      if (V)
+	fprintf (stderr, "writing pbm file...\n");
+      setbuf (stdout, bufferout);
+      pbm_writefile (stdout, recon, cols, rows);
+      pbm_freearray (&recon, rows);
+    }				/* end decoding */
+}
Index: /indexers/branches/3.03a/mg/src/images/mgticbuild.1
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgticbuild.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgticbuild.1	(revision 14757)
@@ -0,0 +1,61 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgticbuild 1 \*(Dt CITRI
+.SH NAME
+mgticbuild \- build a library of marks from training documents
+.SH SYNOPSIS
+.B mgticbuild
+[
+.B \-h
+]
+.I "libraryfile infile1 infile2 .\|.\|."
+.SH DESCRIPTION
+.B mgticbuild
+builds an uncompressed library of marks that have been
+extracted from a series of input files.  If the
+.I libraryfile
+does
+not exist, it is created, otherwise new marks are appended to the
+file.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fIlibraryfile\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.I libraryfile
+This specifies the name of the library file.
+.TP
+.I infile(s)
+The training files; the only currently-supported format is
+.IR pbm .
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/images/mgticbuild.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgticbuild.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgticbuild.c	(revision 14757)
@@ -0,0 +1,145 @@
+/**************************************************************************
+ *
+ * mgticbuild.c -- Program to build the textual image library
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "marklist.h"
+#include "pbmtools.h"
+#include "extractor.h"
+#include "utils.h"
+
+
+void 
+usage ()
+{
+  fprintf (stderr, "usage: \n"
+	"\tmgticbuild   libraryfile   infile.pbm  [infile2 infile3 ...]\n");
+  exit (1);
+}
+
+void 
+main (int argc, char *args[])
+{
+  int i;
+  FILE *lib = NULL, *inf = NULL;
+  marklistptr list = NULL, step;
+  Pixel **bitmap;
+  int cols, rows;
+  int count, pos = 0;
+  char *libraryname = NULL;
+
+  if (argc < 2)
+    usage ();
+
+  for (i = 1; i < argc; i++)
+    {
+      if (!strcmp (args[i], "-v"))
+	V = 1;
+      else if (!strcmp (args[i], "-h"))
+	usage ();
+      else if (args[i][0] == '-')
+	error_msg (args[0], "unknown switch:", args[i]);
+      else if (!libraryname)
+	libraryname = args[i];
+      else
+	pos = i;
+    }
+
+  if (!libraryname)
+    error_msg (args[0], "please specify a library file", "");
+  if (pos < 2)
+    usage ();
+
+  count = 0;
+  for (i = pos; i < argc; i++)
+    if (args[i][0] != '-')
+      {
+	inf = fopen (args[i], "rb");
+	count = 0;
+	if (inf == NULL)
+	  fprintf (stderr, "Trouble opening file: %s\n", args[i]);
+	else
+	  {
+	    if (pbm_isapbmfile (inf))
+	      {
+		if (V)
+		  fprintf (stderr, "%s: processing...\n", args[0]);
+		if (V)
+		  fprintf (stderr, "reading file %s...", args[i]);
+		bitmap = pbm_readfile (inf, &cols, &rows);
+		if (V && (count == 0))
+		  fprintf (stderr, "building...");
+
+		list = NULL;
+
+		ExtractAllMarks (bitmap, &list, cols, rows);
+
+		if (V)
+		  fprintf (stderr, "writing...");
+
+		if ((!lib) && (marklist_length (list)))
+		  {
+		    lib = fopen (libraryname, "r");
+		    if (lib)
+		      {
+			fclose (lib);
+			lib = fopen (libraryname, "ab");
+			if (lib == NULL)
+			  error_msg (args[0], "trouble appending library file", "");
+			fprintf (stderr, "\nwarning: appending library file: %s\n", libraryname);
+		      }
+		    else
+		      {
+			lib = fopen (libraryname, "wb");
+			if (lib == NULL)
+			  error_msg (args[0], "trouble creating library file", "");
+		      }
+		  }		/* if !lib */
+
+		step = list;
+		while (step)
+		  {
+		    step->data.symnum = count;
+		    write_library_mark (lib, step->data);
+		    count++;
+		    step = step->next;
+		  }
+		pbm_freearray (&bitmap, rows);
+	      }
+	    else
+	      fprintf (stderr, "warning: %s is not a PBM file.\n", args[i]);
+	    fclose (inf);
+	  }
+	if (count)
+	  {
+	    if (V)
+	      fprintf (stderr, "%d marks written.\n", count);
+	  }
+	else
+	  fprintf (stderr, "No marks written!\n");
+      }
+
+  if (lib)
+    fclose (lib);
+  marklist_free (&list);
+}
Index: /indexers/branches/3.03a/mg/src/images/mgticdump.1
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgticdump.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgticdump.1	(revision 14757)
@@ -0,0 +1,55 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgticdump 1 \*(Dt CITRI
+.SH NAME
+mgticdump \- displays the library in a user-friendly manner
+.SH SYNOPSIS
+.B mgticdump
+[
+.B \-h
+]
+.I libraryfile
+.SH DESCRIPTION
+.B mgticdump
+displays the marks in a library in a user-viewable form.  The output
+is to
+.I stdout
+and is in a plain ASCII form.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fIlibraryfile\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.I libraryfile
+This specifies the name of the library file.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/images/mgticdump.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgticdump.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgticdump.c	(revision 14757)
@@ -0,0 +1,86 @@
+/**************************************************************************
+ *
+ * mgticdump.c -- Program to dump out a library in a human readable form
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "marklist.h"
+#include "pbmtools.h"
+#include "extractor.h"
+#include "utils.h"
+
+
+void 
+usage ()
+{
+  fprintf (stderr, "usage:\n"
+	   "\tmgticdump   libraryfile\n");
+  exit (1);
+}
+
+
+
+void 
+main (int argc, char *args[])
+{
+  FILE *lib;
+  int count, i;
+  marktype d;
+  char *libraryname = NULL;
+  FILE *outf = (stdout);
+
+  if (argc < 2)
+    usage ();
+
+  for (i = 1; i < argc; i++)
+    {
+      if (!strcmp (args[i], "-h"))
+	usage ();
+      else if (args[i][0] == '-')
+	error_msg (args[0], "unknown switch:", args[i]);
+      else if (!libraryname)
+	libraryname = args[i];
+      else
+	error_msg (args[0], "too many filenames", "");
+    }
+
+  if (!libraryname)
+    error_msg (args[0], "please specify a library file", "");
+
+
+  lib = fopen (libraryname, "rb");
+  if (lib == NULL)
+    error_msg (args[0], "trouble opening library file:", libraryname);
+
+  count = 0;
+  while (!isEOF (lib))
+    {
+      read_library_mark (lib, &d);
+
+      write_library_mark (outf, d);
+      count++;
+
+      pbm_freearray (&d.bitmap, d.h);
+    }
+  fprintf (stderr, "count=%d", count);
+  fclose (lib);
+}
Index: /indexers/branches/3.03a/mg/src/images/mgticprune.1
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgticprune.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgticprune.1	(revision 14757)
@@ -0,0 +1,91 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgticprune 1 \*(Dt CITRI
+.SH NAME
+mgticprune \- prunes the library to remove duplicates
+.SH SYNOPSIS
+.B mgticprune
+[
+.BI \-a " n"
+]
+[
+.BI \-s " n"
+]
+[
+.B \-Q
+]
+.I libraryfile
+.if n .ti +9n
+[
+.I pruned-libraryfile
+]
+.SH DESCRIPTION
+.B mgticprune
+examines
+.I libraryfile
+and removes duplicate marks.  If
+.I pruned-libraryfile
+is not specified,
+.I libraryfile
+is overwritten with the marks in the pruned library.  The Combined
+Symbol Independent Strategy (CSIS) method is used to match marks.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fIpruned-libraryfile\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-a " n"
+Prune marks when their area is under or equal to the threshold,
+.IR n .
+The default value is\ 3.
+.TP
+.BI \-s " n"
+Prune marks when their width and height is under or equal to
+the threshold,
+.IR n .
+The default value is\ 0.
+.TP
+.BI \-Q
+Use a quicker method of pruning.  The number of iterations through the
+averaging and pruning processes is decreased.  This usually reduces
+time by a half, but compression ratios decrease.
+.TP
+.I libraryfile
+This specifies the name of the library file
+.TP
+.I pruned-libraryfile
+This specifies the name of the prune library, after duplicates and
+matches have been removed.  If this file is not specified, then
+.I libraryfile
+will be overwritten.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/images/mgticprune.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgticprune.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgticprune.c	(revision 14757)
@@ -0,0 +1,393 @@
+/**************************************************************************
+ *
+ * mgticprune.c -- Program to prune a textual image library
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "marklist.h"
+#include "pbmtools.h"
+#include "extractor.h"
+#include "utils.h"
+#include "match.h"
+
+marklistptr *avglib = NULL;
+int avglibsize;
+int libsize = 0;
+
+
+void 
+usage ()
+{
+  fprintf (stderr, "usage:\n"
+    "\tmgticbuild [-a n]  [-s n]  [-Q]   libraryfile   [pruned-library]\n");
+  exit (1);
+}
+
+
+
+
+/* foreach list in the avglib[] array, an average mark is returned */
+marklistptr 
+average_library ()
+{
+  marklistptr librarylist;
+  int i;
+  marktype avgmark;
+
+  librarylist = NULL;
+  for (i = 0; i < libsize; i++)
+    {
+      if (avglib[i])
+	{
+	  marklist_average (avglib[i], &avgmark);
+	  avgmark.symnum = i;
+	  marklist_addcopy (&librarylist, avgmark);
+	}
+    }
+  return librarylist;
+}
+
+
+void 
+average_space_enlarge ()
+{
+  int j;
+
+  if (libsize >= avglibsize)
+    {
+      avglib = (marklistptr *) realloc (avglib, (avglibsize + 100) * sizeof (marklistptr));
+      if (!avglib)
+	error_msg ("mgticprune", "out of memory in reallocating..", "");
+      for (j = avglibsize; j < avglibsize + 100; j++)
+	avglib[j] = NULL;
+      avglibsize += 100;
+    }
+}
+
+
+/* for each mark in 'origlist', if it can't be matched with one in 
+   'librarylist', then add to the librarylist, and update the relevant
+   avglib[] position */
+void 
+greedy_add (marklistptr origlist, marklistptr * librarylist)
+{
+  marklistptr step, step_i;
+  int i, j, notfound;
+  marktype d_i;
+
+  for (i = 0, step_i = origlist; step_i; i++, step_i = step_i->next)
+    {
+      d_i = step_i->data;
+
+      notfound = 1;
+      for (j = 0, step = *librarylist; step; j++, step = step->next)
+	{
+	  if (NOT_SCREENED (d_i, step->data))
+	    if (MATCH (&d_i, &step->data) < MATCH_VAL)
+	      {
+		d_i.symnum = j;
+		marklist_addcopy (&avglib[j], d_i);
+		notfound = 0;
+		break;
+	      }
+	}
+
+      if (notfound)
+	{
+	  d_i.symnum = libsize;
+	  marklist_addcopy (librarylist, d_i);
+	  marklist_addcopy (&avglib[libsize], d_i);
+	  libsize++;
+	  if (libsize >= avglibsize)
+	    average_space_enlarge ();
+	}
+    }
+}
+
+
+
+/* for each mark in 'library', if another matches with it, remove
+   one copy from the library, and erase the relevant avglib[] */
+void 
+greedy_prune (marklistptr * library)
+{
+  int count;
+  int i, j;
+  marklistptr step;
+  marktype d;
+
+  count = marklist_length (*library);
+  /* an invariant, all marks <i have been kept in the pruned library */
+  for (i = 0; i < count; i++)
+    {
+      marklist_getat (*library, i, &d);
+
+      for (j = 0, step = *library; j < i; j++, step = step->next)
+	{
+	  if (NOT_SCREENED (d, step->data))
+	    if (MATCH (&d, &step->data) < MATCH_VAL)
+	      {
+		/* [i,d] has matched with library element [j,d2]. */
+		marklist_removeat (library, i);		/* because we kill it here */
+		marklist_free (&avglib[d.symnum]);
+		avglib[d.symnum] = NULL;
+		i--, count--;
+		break;
+	      }
+	}
+    }
+}
+
+
+void 
+prune_on_size (marklistptr * list, int sizethres)
+{
+  int count, i;
+  marktype d;
+
+  if (sizethres)
+    {
+      count = marklist_length (*list);
+      i = 0;
+      do
+	{
+	  marklist_getat (*list, i, &d);
+	  if ((d.w <= sizethres) && (d.h <= sizethres))
+	    {
+	      marklist_removeat (list, i);
+	      i--;
+	      count--;
+	    }
+	  i++;
+	}
+      while (i < count);
+    }
+}
+
+
+
+void 
+prune_on_area (marklistptr * list, int areathres)
+{
+  int count, i;
+  marktype d;
+
+  if (areathres)
+    {
+      count = marklist_length (*list);
+      i = 0;
+      do
+	{
+	  marklist_getat (*list, i, &d);
+	  if (d.set <= areathres)
+	    {
+	      marklist_removeat (list, i);
+	      i--;
+	      count--;
+	    }
+	  i++;
+	}
+      while (i < count);
+    }
+}
+
+
+void 
+averagedout_addagain (marklistptr origlist, marklistptr * librarylist)
+{
+  marklistptr step, stepi;
+  int notfound;
+  int i, j;
+
+  for (i = 0, step = origlist; step; i++, step = step->next)
+    {
+      notfound = 1;
+
+      for (j = 0, stepi = *librarylist; stepi; j++, stepi = stepi->next)
+	if (NOT_SCREENED (step->data, stepi->data))
+	  if (MATCH (&step->data, &stepi->data) < MATCH_VAL)
+	    {
+	      notfound = 0;
+	      break;
+	    }
+
+      if (notfound)
+	{
+	  marklist_addcopy (librarylist, step->data);
+	  marklist_addcopy (&avglib[libsize], step->data);
+	  libsize++;
+	  if (libsize >= avglibsize)
+	    average_space_enlarge ();
+	}
+    }
+}
+
+
+
+
+
+void 
+main (int argc, char *args[])
+{
+  int i;
+  FILE *lib;
+
+  marklistptr origlist = NULL, librarylist = NULL;
+  marklistptr step;
+  char tempn[1000], sysstr[1000];
+  int count;
+  char *libraryname = NULL, *prunename = NULL;
+  int sizethres = 3, areathres = 0;
+  int pass;
+  int num_passes = 3;
+  int overwrite = 0;
+
+  V = 0;
+
+  if (argc < 2)
+    usage ();
+
+  for (i = 1; i < argc; i++)
+    {
+      if (!strcmp (args[i], "-v"))
+	V = 1;
+      else if (!strcmp (args[i], "-h"))
+	usage ();
+      else if (!strcmp (args[i], "-Q"))
+	{
+	  num_passes = 0;
+	}
+      else if (!strcmp (args[i], "-s"))
+	{
+	  i++;
+	  if ((i < argc) && (isinteger (args[i])))
+	    sizethres = atoi (args[i]);
+	  else
+	    error_msg (args[0], "follow the -s option with a numeric arg >=0", "");
+	}
+      else if (!strcmp (args[i], "-a"))
+	{
+	  i++;
+	  if ((i < argc) && (isinteger (args[i])))
+	    areathres = atoi (args[i]);
+	  else
+	    error_msg (args[0], "follow the -a option with a numeric arg >=0", "");
+	}
+      else if (args[i][0] == '-')
+	error_msg (args[0], "unknown switch:", args[i]);
+      else if (!libraryname)
+	libraryname = args[i];
+      else if (!prunename)
+	prunename = args[i];
+      else
+	error_msg (args[0], "too many filenames", "");
+    }
+
+  if (!libraryname)
+    error_msg (args[0], "please specify a library file", "");
+
+  if (V)
+    fprintf (stderr, "%s: processing...\n", args[0]);
+
+  overwrite = 0;
+  if (!prunename)
+    {
+      prunename = libraryname;
+      if (V)
+	fprintf (stderr, "overwriting previous library file.\n");
+      overwrite = 1;
+    }
+
+  if (overwrite)
+    {
+      tmpnam (tempn);
+    }
+  else
+    strcpy (tempn, prunename);
+
+
+  avglibsize = count = read_library (libraryname, &origlist);
+  if (V)
+    fprintf (stderr, "%d marks...", count);
+
+  avglib = (marklistptr *) malloc (count * sizeof (marklistptr));
+  if (!avglib)
+    error_msg (args[0], "out of memory", "");
+  for (i = 0; i < avglibsize; i++)
+    avglib[i] = NULL;
+
+
+  prune_on_size (&origlist, sizethres);
+
+  prune_on_area (&origlist, areathres);
+  if (V)
+    fprintf (stderr, "after threshold pruning, %d marks\n", count = marklist_length (origlist));
+
+
+  if (V)
+    fprintf (stderr, "starting greedy library creation...\n");
+
+  greedy_add (origlist, &librarylist);
+
+
+  for (pass = 0; pass < num_passes; pass++)
+    {
+      marklist_free (&librarylist);
+      if (V)
+	fprintf (stderr, "averaging...\n");
+      librarylist = average_library ();
+      averagedout_addagain (origlist, &librarylist);
+      greedy_prune (&librarylist);
+      if (V)
+	fprintf (stderr, "after pass %d greedy prune %d marks\n", 1 + pass, marklist_length (librarylist));
+    }
+
+
+  lib = fopen (tempn, "wb");
+  if (lib == NULL)
+    error_msg (args[0], "trouble creating prune-library file.", "");
+
+
+  if (V)
+    fprintf (stderr, "writing to file: %s...", prunename);
+  for (step = librarylist, count = 0; step; step = step->next, count++)
+    {
+      step->data.symnum = count;
+      write_library_mark (lib, step->data);
+    }
+
+  if (V)
+    fprintf (stderr, "%d marks.\n", count);
+  fclose (lib);
+
+  if (overwrite)
+    {
+      sprintf (sysstr, "mv %s %s", tempn, prunename);
+      system (sysstr);		/* move temp to proper name */
+    }
+
+  for (i = 0; i < avglibsize; i++)
+    {
+      marklist_free (&avglib[i]);
+      free (avglib[i]);
+    }
+}
Index: /indexers/branches/3.03a/mg/src/images/mgticstat.1
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgticstat.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgticstat.1	(revision 14757)
@@ -0,0 +1,57 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgticstat 1 \*(Dt CITRI
+.SH NAME
+mgticstat \- displays the statistics for the library
+.SH SYNOPSIS
+.B mgticstat
+[
+.B \-h
+]
+.I libraryfile
+.SH DESCRIPTION
+.B mgticstat
+displays statistics about the
+.I libraryfile
+file.
+The output of this program contains the average mark size, average
+centroid position, and the number of marks with an area less than or
+equal to a few powers of\ 2.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fIlibraryfile\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.I libraryfile
+This specifies the name of the library file.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1).
Index: /indexers/branches/3.03a/mg/src/images/mgticstat.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/mgticstat.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/mgticstat.c	(revision 14757)
@@ -0,0 +1,130 @@
+/**************************************************************************
+ *
+ * mgticstat.c -- Program to print out stats about a textual image library
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "marklist.h"
+#include "pbmtools.h"
+#include "extractor.h"
+#include "utils.h"
+
+void 
+usage ()
+{
+  fprintf (stderr, "usage:\n"
+	   "\tmgticstat   libraryfile\n");
+  exit (1);
+}
+
+void 
+main (int argc, char *args[])
+{
+  FILE *lib, *outf = (stdout);
+  int count;
+  int small1, small2, small4, small9, small16, small25, small36, small49,
+    small64, small81, small100;
+  marktype d;
+  int avx, avy;
+  int hhh, www, i;
+  int avruns_h = 0, avruns_v = 0;
+  int av_area = 0;
+  char *libraryname = NULL;
+
+
+  if (argc < 2)
+    usage ();
+
+  for (i = 1; i < argc; i++)
+    {
+      if (!strcmp (args[i], "-v"))
+	V = 1;
+      else if (!strcmp (args[i], "-h"))
+	usage ();
+      else if (args[i][0] == '-')
+	error_msg (args[0], "unknown switch:", args[i]);
+      else if (!libraryname)
+	libraryname = args[i];
+      else
+	error_msg (args[0], "too many filenames", "");
+    }
+
+  if (!libraryname)
+    error_msg (args[0], "please specify a library file", "");
+
+
+  lib = fopen (libraryname, "r");
+  if (lib == NULL)
+    error_msg (args[0], "Trouble opening library file", "");
+
+  count = 0;
+  small1 = small2 = small4 = small9 = small16 = small25 = small36 = small49 = small64 = small81 = small100 = 0;
+  avx = avy = 0;
+  www = hhh = 0;
+  while (!isEOF (lib))
+    {
+      if (!read_library_mark (lib, &d))
+	error_msg (args[0], "error in library file", "");
+
+      av_area += d.set;
+      if (d.set <= 1)
+	small1++;
+      if (d.set <= 2)
+	small2++;
+      if (d.set <= 4)
+	small4++;
+      if (d.set <= 9)
+	small9++;
+      if (d.set <= 16)
+	small16++;
+      if (d.set <= 25)
+	small25++;
+      if (d.set <= 36)
+	small36++;
+      if (d.set <= 49)
+	small49++;
+      if (d.set <= 64)
+	small64++;
+      if (d.set <= 81)
+	small81++;
+      if (d.set <= 100)
+	small100++;
+      avx += d.xcen;
+      avy += d.ycen;
+      www += d.w;
+      hhh += d.h;
+      avruns_h += d.h_runs;
+      avruns_v += d.v_runs;
+      pbm_freearray (&d.bitmap, d.h);
+      count++;
+      if (count % 5000 == 0)
+	fprintf (outf, "%dk ", count / 1000);
+    }
+  fprintf (outf, "number of marks=%d\n", count);
+  fprintf (outf, "average area=%d\n", av_area / count);
+  fprintf (outf, "area <=1:%d, <=2:%d, <=4:%d, <=9:%d, <=16:%d, <=25:%d, <=36:%d, <=49:%d, <=64:%d, <=81:%d, <=100:%d\n", small1, small2, small4, small9, small16, small25, small36, small49, small64, small81, small100);
+
+  fprintf (outf, "average num runs, horizontal=%d, vertical=%d\n", avruns_h / count, avruns_v / count);
+  fprintf (outf, "average centroid position=(%d,%d)\n", avx / count, avy / count);
+  fprintf (outf, "average width=%d, average height=%d\n", www / count, hhh / count);
+  fclose (lib);
+}
Index: /indexers/branches/3.03a/mg/src/images/model.h
===================================================================
--- /indexers/branches/3.03a/mg/src/images/model.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/model.h	(revision 14757)
@@ -0,0 +1,92 @@
+/**************************************************************************
+ *
+ * model.h -- Part pf PPM data compression
+ * Copyright (C) 1987  Alistair Moffat
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#define defaultkbytes	896
+#define minkbytes	56
+#define maxkbytes	((65536/1024)*sizeof(eventnode))
+
+#ifndef increment
+#define	increment	8
+#endif
+#ifndef halveat
+#define halveat		64
+#endif
+#define maxtotalcnt 	(increment*halveat)
+
+typedef int boolean;
+#define false           0
+#define true            1
+
+typedef short event;
+typedef unsigned short point;
+
+typedef struct
+  {
+    short totalcnt;
+    short notfound;
+    point list;			/* list storing the event records */
+  }
+eventset;
+
+typedef struct
+  {
+    event eventnum;
+    short count;
+    point next, prev;
+    eventset foll;
+  }
+eventnode, *eventptr;
+
+#define memsize		(kbytes*1024)
+#define maxnodes	(memsize/sizeof(eventnode))
+/* #define charsetsize     256 -- MAHE */
+#define nchars          (charsetsize+1)
+
+extern int charsetsize;		/* -- MAHE */
+
+extern eventptr E;
+extern long kbytes;
+extern point numnodes, nfreenodes;
+extern boolean excluded[];	/* -- MAHE */
+
+#define ENULL		(E)
+
+typedef unsigned u;
+#define p32(p)	(E+p)
+#define p16(p)	(p-E)
+
+/* in ppm.c */
+void write_model ();
+void encodestring ();
+void decodestring ();
+void encodefile ();
+void decodefile ();
+
+/* in lstevent.c */
+void write_method ();
+eventnode *encode_event_noex ();
+eventnode *decode_event_noex ();
+eventnode *encode_event ();
+eventnode *decode_event ();
+/* eventnode *addevent(); */
+eventnode *newnode ();
Index: /indexers/branches/3.03a/mg/src/images/pbmtools.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/pbmtools.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/pbmtools.c	(revision 14757)
@@ -0,0 +1,288 @@
+/**************************************************************************
+ *
+ * pbmtools.c -- Routines for dealing with portable bitmap files (PBM)
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "marklist.h"
+#include "pbmtools.h"
+#include "extractor.h"
+#include "utils.h"
+
+
+
+void 
+pbm_putpixel_range (Pixel ** bitmap, int c, int r, int val, int cols, int rows)
+{
+  if (((c) >= 0) && ((c) < cols) && ((r) >= 0) && ((r) < rows))
+    pbm_putpixel (bitmap, c, r, val);
+  else
+    fprintf (stderr, "putpitxel (%d %d) outside (%d %d)\n", c, r, cols, rows);
+}
+
+int 
+pbm_getpixel_range (Pixel ** bitmap, int c, int r, int cols, int rows)
+{
+  if (((c) >= 0) && ((c) < cols) && ((r) >= 0) && ((r) < rows))
+    return pbm_getpixel (bitmap, c, r);
+  else
+    {
+      fprintf (stderr, "getpixel (%d %d) outside (%d %d)\n", c, r, cols, rows);
+      return 0;
+    }
+}
+
+
+
+
+
+/*
+   Returns 1 if *fp points to a PBM (magic is P1 or P4) file.
+   leaves the fp in it's original position.
+   usage: if(pbm_isapbmfile(fp)) process(fp);
+ */
+int 
+pbm_isapbmfile (FILE * fp)
+{
+  u_long magic;
+
+  magic = getmagicno_short (fp);
+  if ((magic == MAGIC_P4) || (magic == MAGIC_P1))
+    return 1;
+  else
+    return 0;
+}
+
+
+/*
+   Frees the memory used in the bitmap structure.
+   usage: pbm_freearray(&bitmap);
+   Sets bitmap to be NULL on return.
+ */
+void 
+pbm_freearray (Pixel *** bitmap, int rows)
+{
+  int r;
+  if (rows == 0)
+    rows++;
+  for (r = 0; r < rows; r++)
+    free ((*bitmap)[r]);
+  free (*bitmap);
+  (*bitmap) = NULL;
+}
+
+
+/*
+   This function allocates the bitmap.
+   usage: bitmap=pbm_allocarray(cols,rows);
+ */
+Pixel **
+pbm_allocarray (int cols, int rows)
+{
+  Pixel **p;
+  int i, newc = (cols + PBITS) / PBITS;
+
+  if (cols == 0)
+    cols++;
+  if (rows == 0)
+    rows++;
+  p = (Pixel **) malloc (rows * sizeof (Pixel *));
+  if (p == NULL)
+    error_msg ("pbm_allocarray", "out of memory", "");
+  for (i = 0; i < rows; i++)
+    {
+      p[i] = (Pixel *) calloc (newc, sizeof (Pixel));
+      if (p[i] == NULL)
+	error_msg ("pbm_allocarray", "out of memory", "");
+    }
+  return p;
+}
+
+
+
+Pixel **
+pbm_copy (Pixel ** bitmap, int cols, int rows)
+{
+  Pixel **p;
+  int newc = (cols + PBITS) / PBITS;
+  int x, y;
+
+  p = pbm_allocarray (cols, rows);
+  for (x = 0; x < newc; x++)
+    for (y = 0; y < rows; y++)
+      p[y][x] = bitmap[y][x];
+  return p;
+}
+
+
+
+
+/*
+   Reads in a pbm file and returns a pointer to the allocated bitmap, 
+   in the P4 format.
+   Assumes fp was opened and keeps it that way.
+   usage: bitmap=pbm_readfile(fp,&cols,&rows);
+ */
+Pixel **
+pbm_readfile (FILE * fp, int *cols, int *rows)
+{
+  Pixel **p = NULL;
+  char s[100];
+  unsigned char *buf;
+  int r, c, ii = 0;
+  int p1 = 0;
+  int arg;
+
+
+  do
+    {
+      readline (s, fp);
+    }
+  while (s[0] == '#');
+
+  if (strcmp (s, "P1") == 0)
+    p1 = 1;
+  else if (strcmp (s, "P4") == 0)
+    p1 = 0;
+  else
+    error_msg ("pbm_readfile", "only pbm files are supported", "");
+
+  do
+    {
+      readline (s, fp);
+    }
+  while (s[0] == '#');
+
+  arg = sscanf (s, "%d %d", cols, rows);
+  if (arg == 1)
+    {
+      readline (s, fp);
+      arg = sscanf (s, "%d", rows);
+      if (arg != 1)
+	error_msg ("pbm_readfile", "bizzare pbm format", "");
+    }
+  p = pbm_allocarray (*cols, *rows);
+  buf = (unsigned char *) malloc ((*cols + 2) * sizeof (unsigned char));
+  if (!buf)
+    error_msg ("pbm_readfile", "out of memory", "");
+
+  if (p1)
+    {
+      for (r = 0; r < *rows; r++)
+	for (c = 0; c < *cols; c++)
+	  {
+	    fscanf (fp, "%d", &ii);
+	    pbm_putpixel (p, c, r, ii);
+	  }
+    }
+  else
+    {
+      for (r = 0; r < *rows; r++)
+	{
+	  c = 0;
+	  fread (buf, 1, (*cols + 7) / 8, fp);
+	  for (c = 0; c < *cols; c++)
+	    {
+	      if (!(c % 8))
+		ii = buf[c / 8];
+	      if (ii < 0)
+		error_msg ("pbm_readfile", "file reading error", "");
+	      pbm_putpixel (p, c, r, (ii & 128) ? 1 : 0);
+	      ii <<= 1;
+	    }
+	}
+    }				/* p4 type */
+  free (buf);
+  return p;
+}
+
+
+/*
+   Writes a pbm file given a file pointer and bitmap. Assumes that
+   fp is already open, and keeps in that way.
+   usage: pbm_writefile(fp,bitmap,cols,rows);
+ */
+void 
+pbm_writefile (FILE * fp, Pixel ** bitmap, int cols, int rows)
+{
+  int r, c, ii = 0, j;
+  unsigned char *buf;
+
+  buf = (unsigned char *) malloc (((cols + 14) / 8) * sizeof (unsigned char));
+
+  fprintf (fp, "%s\n", "P4");
+  fprintf (fp, "%d %d\n", cols, rows);
+
+  for (r = 0; r < rows; r++)
+    {
+      for (c = 0; c < cols; c += 8)
+	{
+	  ii = 0;
+	  for (j = 0; j < 8; j++)
+	    if (c + j < cols)
+	      {
+		if (pbm_getpixel (bitmap, c + j, r))
+		  ii |= (128 >> j);
+	      }
+	  buf[c / 8] = ii;
+	}
+      fwrite (buf, 1, (cols + 7) / 8, fp);
+    }
+  free (buf);
+/*      putc('\n',fp);   if this line is included programs don't say things like 'short image' &c, but then again,
+   in most cases a 'cmp' between the original will fail because of the last byte...sigh, "standards". */
+}
+
+#define BUF_SIZE 131072
+char buffer[BUF_SIZE];
+
+void 
+pbm_writenamedfile (char fn[], Pixel ** bitmap, int cols, int rows)
+{
+  FILE *tempfp;
+
+  tempfp = fopen (fn, "wb");
+  if (tempfp == NULL)
+    error_msg ("pbm_writenamedfile", "can't open file:", fn);
+  setbuffer (tempfp, buffer, BUF_SIZE);
+  pbm_writefile (tempfp, bitmap, cols, rows);
+  fclose (tempfp);
+}
+
+
+
+Pixel **
+pbm_readnamedfile (char fn[], int *cols, int *rows)
+{
+  FILE *tempfp;
+  Pixel **temp;
+
+  tempfp = fopen (fn, "rb");
+  if (tempfp == NULL)
+    return NULL;
+  setbuffer (tempfp, buffer, BUF_SIZE);
+
+  temp = pbm_readfile (tempfp, cols, rows);
+
+  fclose (tempfp);
+  return temp;
+}
Index: /indexers/branches/3.03a/mg/src/images/pbmtools.h
===================================================================
--- /indexers/branches/3.03a/mg/src/images/pbmtools.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/pbmtools.h	(revision 14757)
@@ -0,0 +1,86 @@
+/**************************************************************************
+ *
+ * pbmtools.h -- Routines for dealing with portable bitmap files (PBM)
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef __PBMTOOLS_H
+#define __PBMTOOLS_H
+
+#include "sysfuncs.h"
+#include "basictypes.h"
+
+#include "utils.h"
+#include "marklist.h"
+
+#define PBITS 32
+#define PSH 5
+
+
+/* The next two are ordered pixels col0=left, cols31=right */
+
+/*
+   #define pbm_getpixel(bitmap,c,r)  \
+   ((bitmap[r][(c)>>PSH] >> ((PBITS-1)-((c)&(PBITS-1))))&1)
+   #define pbm_putpixel(bitmap,c,r,val) \
+   if((val))  \
+   bitmap[r][(c)>>PSH] |=  (((unsigned)1<<(PBITS-1)) >> ((c)&(PBITS-1))); \
+   else \
+   bitmap[r][(c)>>PSH] &= ~(((unsigned)1<<(PBITS-1)) >> ((c)&(PBITS-1))) 
+ */
+
+
+
+
+/* The next two defines are ordered pixel cols0=right, cols31=left */
+
+#define pbm_getpixel(bitmap,c,r)                            \
+         ((bitmap[r][(c)>>PSH] >> ((c)&(PBITS-1)))&1)
+#define pbm_putpixel(bitmap,c,r,val)                        \
+         if((val))                                          \
+              bitmap[r][(c)>>PSH] |= (1<<((c)&(PBITS-1)));  \
+         else                                               \
+              bitmap[r][(c)>>PSH] &= ~(1<<((c)&(PBITS-1)))
+
+
+#define pbm_putpixel_trunc(bitmap,c,r,val,cols,rows) \
+       if(((c)>=0)&&((c)<cols)&&((r)>=0)&&((r)<rows)) \
+             pbm_putpixel(bitmap,c,r,val)
+
+#define pbm_getpixel_trunc(bitmap,c,r,cols,rows)       \
+       ((((c)>=0)&&((c)<cols)&&((r)>=0)&&((r)<rows)) ?  \
+             pbm_getpixel(bitmap,c,r) : 0)
+
+
+
+
+int pbm_isapbmfile (FILE * fp);
+void pbm_freearray (Pixel *** bitmap, int rows);
+Pixel **pbm_copy (Pixel ** bitmap, int cols, int rows);
+Pixel **pbm_allocarray (int cols, int rows);
+Pixel **pbm_readfile (FILE * fp, int *cols, int *rows);
+Pixel **pbm_readnamedfile (char fn[], int *cols, int *rows);
+void pbm_writefile (FILE * fp, Pixel ** bitmap, int cols, int rows);
+void pbm_writenamedfile (char fn[], Pixel ** bitmap, int cols, int rows);
+
+void pbm_putpixel_range (Pixel ** bitmap, int c, int r, int val, int cols, int rows);
+int pbm_getpixel_range (Pixel ** bitmap, int c, int r, int cols, int rows);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/images/ppm.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/ppm.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/ppm.c	(revision 14757)
@@ -0,0 +1,588 @@
+/**************************************************************************
+ *
+ * ppm.c -- PPM data compression
+ * Copyright (C) 1987  Alistair Moffat
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "arithcode.h"
+#include "model.h"
+
+
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:16:56  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:17:33  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:33:55  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.2  1994/09/20  04:42:02  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+/* FIXEDORDER sets the maximum context length that will be used.
+   Making FIXEDORDER large increases the compression if there is enough
+   space to store the model, but when space limit is reached increasing
+   FIXEDORDER will decrease compression because of model thrashing.
+   Third order (FIXEDORDER=3) is suitable for a few hundred Kb of model
+   space, FIXEDORDER=1 is suitable for a few tens of kB.
+   This version requires that FIXEDORDER be a preprocessor rather
+   than runtime variable to allow loops to be unrolled and make for faster
+   execution. Maximum in this implementation is 3 */
+
+#ifndef FIXEDORDER
+#define FIXEDORDER	3
+#endif
+
+/* global variables */
+eventptr E = NULL;		/* array of eventnodes */
+point numnodes = 0, nfreenodes = 0;
+long kbytes = defaultkbytes;
+/*boolean               excluded[nchars]={false};  - MAHE */
+boolean excluded[16384] =
+{false};			/* excluded characters */
+
+/* local variables */
+#define defaultchunksize        4096	/* compression chunks */
+
+#define EOSchar         (charsetsize)
+
+unsigned chunksize = defaultchunksize;
+eventptr s[FIXEDORDER + 1] =
+{NULL},				/* current contexts */
+  t[FIXEDORDER + 1] =
+{NULL};				/* new contexts */
+
+#if (FIXEDORDER==3)
+#define SHIFT_ST	s[1] = t[0]; s[2] = t[1] ; s[3] = t[2]
+#else
+#if (FIXEDORDER==2)
+#define SHIFT_ST	s[1] = t[0]; s[2] = t[1]
+#else
+#if (FIXEDORDER==1)
+#define SHIFT_ST	s[1] = t[0]
+#else
+#define SHIFT_ST
+#endif
+#endif
+#endif
+
+/* follow a character list and set the exclusions */
+#define SET_EX(p)				\
+do						\
+{	register eventptr q;			\
+	q = p32((p32(p))->next);		\
+	for (; q!=ENULL; q=p32(q->next))	\
+		excluded[q->eventnum] = true;	\
+}						\
+while (false)
+
+/* clear the exclusions */
+#define CLEAR_EX(p)				\
+do						\
+{	register eventptr q;			\
+	q = p32((p32(p))->next);		\
+	for (; q!=ENULL; q=p32(q->next))	\
+		excluded[q->eventnum] = false;	\
+}						\
+while (false)
+
+/*==================================*/
+
+void
+write_model ()
+{
+  fprintf (stderr, "ppm");
+  write_method ();
+#ifdef NOEXCLUSIONS
+  fprintf (stderr, "nx");
+#endif
+  fprintf (stderr, "-o%1d", FIXEDORDER);
+  fprintf (stderr, "-k%ld", kbytes);
+}
+
+/*==================================*/
+
+void
+encode_in_order (n, e)
+     int n;
+     event e;
+/* encode character e in order n */
+{
+  boolean encoded;
+  int i, c;
+  t[n] = encode_event_noex (&s[n]->foll, e, &encoded);
+  if (encoded)
+    c = n;
+  else
+    for (c = n - 1; c >= 0; c--)
+      {
+#ifdef NOEXCLUSIONS
+	t[c] = encode_event_noex (&s[c]->foll, e, &encoded);
+#else
+	SET_EX (s[c + 1]->foll.list);
+	t[c] = encode_event (&s[c]->foll, e, &encoded);
+#endif
+	if (encoded)
+	  break;
+      }
+  if (!encoded)
+    arithmetic_encode (e, e + 1, nchars);
+  for (i = c + 1; i <= n; i++)
+    if (i > 0)
+      t[i]->prev = p16 (t[i - 1]);
+    else
+      t[0]->prev = p16 (s[0]);
+  for (i = c - 1; i >= 0; i--)
+    t[i] = p32 (t[i + 1]->prev);
+#ifndef NOEXCLUSIONS
+  if (c != n)
+    CLEAR_EX (s[c + 1]->foll.list);
+#endif
+  SHIFT_ST;
+}
+
+/*==================================*/
+
+/* not required in this version */
+
+#if 0
+
+void
+decode_in_order (n, e)
+     int n;
+     event *e;
+{
+  boolean decoded;
+  int i, c;
+  t[n] = decode_event_noex (&s[n]->foll, &decoded, e);
+  if (decoded)
+    c = n;
+  else
+    for (c = n - 1; c >= 0; c--)
+      {
+#ifdef NOEXCLUSIONS
+	t[c] = decode_event_noex (&s[c]->foll, &decoded, e);
+#else
+	SET_EX (s[c + 1]->foll.list);
+	t[c] = decode_event (&s[c]->foll, &decoded, e);
+#endif
+	if (decoded)
+	  break;
+      }
+  if (!decoded)
+    {
+      *e = arithmetic_decode_target (nchars);
+      arithmetic_decode (*e, *e + 1, nchars);
+    }
+  for (i = c + 1; i <= n; i++)
+    {
+      t[i]->eventnum = *e;
+      if (i > 0)
+	t[i]->prev = p16 (t[i - 1]);
+      else
+	t[0]->prev = p16 (s[0]);
+    }
+  {
+    register int i;
+    for (i = c - 1; i >= 0; i--)
+      t[i] = p32 (t[i + 1]->prev);
+  }
+#ifndef NOEXCLUSIONS
+  if (c != n)
+    CLEAR_EX (s[c + 1]->foll.list);
+#endif
+  SHIFT_ST;
+}
+
+#endif
+
+/*==================================*/
+
+void
+start_model ()
+{
+  int i;
+  /* is this the first call? */
+  if (E == NULL)
+    E = (eventptr) malloc ((unsigned) kbytes * 1024);
+  /* start off with no information */
+  numnodes = 0;
+  nfreenodes = maxnodes;
+  for (i = 0; i <= FIXEDORDER; i++)
+    {
+      s[i] = newnode (NULL);
+      if (i > 0)
+	s[i]->prev = p16 (s[i - 1]);
+    }
+}
+
+/*==================================*/
+
+void
+encodestring (str, n)
+     unsigned short *str;
+     int n;
+/* encode all n characters of the supplied string str */
+{
+  event e;
+  boolean encoded;
+  register eventptr S, T;
+  int i;
+#ifndef NOEXCLUSIONS
+  register eventptr Sex;
+#endif
+
+  if (E == NULL)
+    start_model ();
+  /* set the initial context node */
+  S = s[FIXEDORDER];
+
+  for (i = 0; i < n; i++)
+    {
+      /* encode one character */
+      e = *str++;
+      /* this next monstrosity is logically equivalent to 
+         encode_in_order(FIXEDORDER,e)
+         the loop has been unrolled to make it all go faster */
+      for (;;)
+	{
+	  T = encode_event_noex (&S->foll, e, &encoded);
+	  if (encoded)
+	    break;
+	  t[FIXEDORDER] = T;
+
+#ifdef NOEXCLUSIONS
+#if (FIXEDORDER>2)
+	  S = p32 (S->prev);
+	  t[2] = encode_event_noex (&S->foll, e, &encoded);
+	  t[3]->prev = p16 (t[2]);
+	  if (encoded)
+	    break;
+#endif
+
+#if (FIXEDORDER>1)
+	  S = p32 (S->prev);
+	  t[1] = encode_event_noex (&S->foll, e, &encoded);
+	  t[2]->prev = p16 (t[1]);
+	  if (encoded)
+	    break;
+#endif
+
+#if (FIXEDORDER>0)
+	  S = p32 (S->prev);
+	  t[0] = encode_event_noex (&S->foll, e, &encoded);
+	  t[1]->prev = p16 (t[0]);
+	  if (encoded)
+	    break;
+#endif
+#else
+#if (FIXEDORDER>2)
+	  Sex = S;
+	  SET_EX (Sex->foll.list);
+	  S = p32 (S->prev);
+	  t[2] = encode_event (&S->foll, e, &encoded);
+	  t[3]->prev = p16 (t[2]);
+	  if (encoded)
+	    {
+	      CLEAR_EX (Sex->foll.list);
+	      break;
+	    }
+#endif
+
+#if (FIXEDORDER>1)
+	  Sex = S;
+	  SET_EX (Sex->foll.list);
+	  S = p32 (S->prev);
+	  t[1] = encode_event (&S->foll, e, &encoded);
+	  t[2]->prev = p16 (t[1]);
+	  if (encoded)
+	    {
+	      CLEAR_EX (Sex->foll.list);
+	      break;
+	    }
+#endif
+
+#if (FIXEDORDER>0)
+	  Sex = S;
+	  SET_EX (Sex->foll.list);
+	  S = p32 (S->prev);
+	  t[0] = encode_event (&S->foll, e, &encoded);
+	  t[1]->prev = p16 (t[0]);
+	  if (encoded)
+	    {
+	      CLEAR_EX (Sex->foll.list);
+	      break;
+	    }
+	  CLEAR_EX (Sex->foll.list);
+#endif
+#endif
+
+	  arithmetic_encode (e, e + 1, nchars);
+	  t[0]->prev = p16 (s[0]);
+	  break;
+	}
+      /* phew! Update the current context to the latest node */
+      S = p32 (T->prev);
+
+      /* is there a danger of running out of space? */
+      if (nfreenodes <= FIXEDORDER)
+	{
+	  start_model ();
+	  S = s[FIXEDORDER];
+	}
+    }
+
+  /* save the current contexts for the various order submodels */
+  s[FIXEDORDER] = S;
+  for (i = FIXEDORDER; i > 0; i--)
+    s[i - 1] = p32 (s[i]->prev);
+  /* and send the terminator character */
+  encode_in_order (FIXEDORDER, EOSchar);
+  /* and check the space again */
+  if (nfreenodes <= FIXEDORDER)
+    start_model ();
+}
+
+/*==================================*/
+
+void
+decodestring (str, n)
+     unsigned short *str;
+     int *n;
+{
+  event e;
+  boolean decoded;
+  register eventptr S, T;
+#ifndef NOEXCLUSIONS
+  register eventptr Sex;
+#endif
+
+  /* just mimic the corresponding encoding actions */
+  if (E == NULL)
+    start_model ();
+  S = s[FIXEDORDER];
+
+  *n = 0;
+  for (;;)
+    {				/* logically equivalent to "decode_in_order(FIXEDORDER,&e)" */
+
+      for (;;)
+	{
+	  T = decode_event_noex (&S->foll, &decoded, &e);
+	  if (decoded)
+	    break;
+	  t[FIXEDORDER] = T;
+
+#ifdef NOEXCLUSIONS
+#if (FIXEDORDER>2)
+	  S = p32 (S->prev);
+	  t[2] = decode_event_noex (&S->foll, &decoded, &e);
+	  t[3]->prev = p16 (t[2]);
+	  if (decoded)
+	    {
+	      t[3]->eventnum = e;
+	      break;
+	    }
+#endif
+
+#if (FIXEDORDER>1)
+	  S = p32 (S->prev);
+	  t[1] = decode_event_noex (&S->foll, &decoded, &e);
+	  t[2]->prev = p16 (t[1]);
+	  if (decoded)
+	    {
+#if (FIXEDORDER>2)
+	      t[3]->eventnum =
+#endif
+		t[2]->eventnum = e;
+	      break;
+	    }
+#endif
+
+#if (FIXEDORDER>0)
+	  S = p32 (S->prev);
+	  t[0] = decode_event_noex (&S->foll, &decoded, &e);
+	  t[1]->prev = p16 (t[0]);
+	  if (decoded)
+	    {
+#if (FIXEDORDER>2)
+	      t[3]->eventnum =
+#endif
+#if (FIXEDORDER>1)
+		t[2]->eventnum =
+#endif
+		t[1]->eventnum = e;
+	      break;
+	    }
+#endif
+#else
+#if (FIXEDORDER>2)
+	  Sex = S;
+	  SET_EX (Sex->foll.list);
+	  S = p32 (S->prev);
+	  t[2] = decode_event (&S->foll, &decoded, &e);
+	  t[3]->prev = p16 (t[2]);
+	  if (decoded)
+	    {
+	      t[3]->eventnum = e;
+	      CLEAR_EX (Sex->foll.list);
+	      break;
+	    }
+#endif
+
+#if (FIXEDORDER>1)
+	  Sex = S;
+	  SET_EX (Sex->foll.list);
+	  S = p32 (S->prev);
+	  t[1] = decode_event (&S->foll, &decoded, &e);
+	  t[2]->prev = p16 (t[1]);
+	  if (decoded)
+	    {
+#if (FIXEDORDER>2)
+	      t[3]->eventnum =
+#endif
+		t[2]->eventnum = e;
+	      CLEAR_EX (Sex->foll.list);
+	      break;
+	    }
+#endif
+
+#if (FIXEDORDER>0)
+	  Sex = S;
+	  SET_EX (Sex->foll.list);
+	  S = p32 (S->prev);
+	  t[0] = decode_event (&S->foll, &decoded, &e);
+	  t[1]->prev = p16 (t[0]);
+	  if (decoded)
+	    {
+#if (FIXEDORDER>2)
+	      t[3]->eventnum =
+#endif
+#if (FIXEDORDER>1)
+		t[2]->eventnum =
+#endif
+		t[1]->eventnum = e;
+	      CLEAR_EX (Sex->foll.list);
+	      break;
+	    }
+	  CLEAR_EX (Sex->foll.list);
+#endif
+#endif
+
+	  e = arithmetic_decode_target (nchars);
+	  arithmetic_decode (e, e + 1, nchars);
+#if (FIXEDORDER>2)
+	  t[3]->eventnum =
+#endif
+#if (FIXEDORDER>1)
+	    t[2]->eventnum =
+#endif
+#if (FIXEDORDER>0)
+	    t[1]->eventnum =
+#endif
+	    t[0]->eventnum = e;
+	  t[0]->prev = p16 (s[0]);
+	  break;
+	}
+      S = p32 (T->prev);
+
+      /* check the space requirements */
+      if (nfreenodes <= FIXEDORDER)
+	{
+	  start_model ();
+	  S = s[FIXEDORDER];
+	}
+      /* are we done?  or do we save the char */
+      if (e == EOSchar)
+	break;
+      *str++ = e;
+      (*n)++;
+    }
+  s[FIXEDORDER] = S;
+}
+
+
+#if 0				/* Writing my own version of this - MAHE */
+void
+encodefile ()
+/* encodes a file by breaking into a sequence of fixed length chunks */
+{
+  unsigned char *str;
+  int c, n = 0;
+
+  str = (unsigned char *) malloc ((unsigned) chunksize);
+  startoutputingbits ();
+  startencoding ();
+
+  /* to encode the file, break it into chunks and encode the
+     chunks one by one */
+  while ((c = getchar ()) != EOF)
+    {
+      str[n++] = c;
+      if (n == chunksize)
+	{
+	  encodestring (str, n);
+	  rawbytes += n;
+	  n = 0;
+	}
+    }
+  /* send final partial chunk */
+  if (n > 0)
+    {
+      encodestring (str, n);
+      rawbytes += n;
+    }
+  /* send EOF as an empty string */
+  encodestring (str, 0);
+  doneencoding ();
+  doneoutputingbits ();
+}
+
+void
+decodefile ()
+{
+  unsigned char *str;
+  int n, i;
+
+  str = (unsigned char *) malloc ((unsigned) chunksize);
+  startinputingbits ();
+  startdecoding ();
+  for (;;)
+    {
+      decodestring (str, &n);
+      if (n == 0)
+	break;
+      for (i = 0; i < n; i++)
+	putchar ((int) str[i]);
+      rawbytes += n;
+    }
+}
+
+#endif /* #if 0 */
Index: /indexers/branches/3.03a/mg/src/images/sortmarks.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/sortmarks.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/sortmarks.c	(revision 14757)
@@ -0,0 +1,93 @@
+/**************************************************************************
+ *
+ * sortmarks.c -- Functions which sort the marks into a "readable sequence"
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "marklist.h"
+#include "sortmarks.h"
+
+#define GAP 4
+
+
+
+static int 
+CmpOnY (const void *e1, const void *e2)
+{
+  return (((marktype *) e1)->ycen * 0 + ((marktype *) e1)->ypos) -
+    (((marktype *) e2)->ycen * 0 + ((marktype *) e2)->ypos);
+}
+
+static int 
+CmpOnX (const void *e1, const void *e2)
+{
+  return (((marktype *) e1)->xcen * 0 + ((marktype *) e1)->xpos) -
+    (((marktype *) e2)->xcen * 0 + ((marktype *) e2)->xpos);
+}
+
+
+
+
+
+
+
+
+marklistptr 
+sortmarks (marklistptr listofmarks)
+{
+  marktype *table;
+  int count = 0;
+  int i, s, e;
+
+
+  table = calloc ((unsigned int) marklist_length (listofmarks), sizeof (marklisttype));
+
+  while (listofmarks)
+    {
+      table[count] = listofmarks->data;
+      marklist_removeat (&listofmarks, 0);
+      count++;
+    }
+
+  /* sort first on the y position of their centroids */
+  qsort ((void *) table, (unsigned int) (count), sizeof (*table), CmpOnY);
+
+  for (s = 0; s < count;)
+    {
+      int c;
+
+      for (e = s + 1, c = 0; (e < count) &&
+	   ((table[e].ypos + table[e].ycen * 0) - (table[e - 1].ypos + table[e - 1].ycen * 0) <= GAP); c++, e++);
+
+      if (e < count && c >= 1)
+	qsort (&table[s], (unsigned int) (e - s), sizeof (*table), CmpOnX);
+      s = e;
+    }
+
+  for (i = 0; i < count; i++)
+    {
+      table[i].symnum = i;
+      marklist_add (&listofmarks, table[i]);
+    }
+
+  return listofmarks;
+}
Index: /indexers/branches/3.03a/mg/src/images/sortmarks.h
===================================================================
--- /indexers/branches/3.03a/mg/src/images/sortmarks.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/sortmarks.h	(revision 14757)
@@ -0,0 +1,30 @@
+/**************************************************************************
+ *
+ * sortmarks.h -- Functions which sort the marks into a "readable sequence"
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#ifndef _SortMarks_h_
+#define _SortMarks_h_
+
+marklistptr sortmarks (marklistptr listofmarks);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/images/utils.c
===================================================================
--- /indexers/branches/3.03a/mg/src/images/utils.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/utils.c	(revision 14757)
@@ -0,0 +1,270 @@
+/**************************************************************************
+ *
+ * utils.c -- Functions which are common utilities for the image programs
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "utils.h"
+
+
+int V = 0;
+
+
+int 
+isEOF (FILE * fp)
+{
+  int ch;
+
+  ch = getc (fp);
+  ungetc (ch, fp);
+  if (ch == EOF)
+    return 1;
+  return 0;
+}
+
+
+int 
+getmagicno_short (FILE * fp)
+{
+  int ch1, ch2;
+  ch1 = getc (fp);
+  if (ch1 == EOF)
+    {
+      ungetc (ch1, fp);
+      return 0;
+    }
+  ch2 = getc (fp);
+  if (ch2 == EOF)
+    {
+      ungetc (ch2, fp);
+      return 0;
+    }
+  ungetc (ch2, fp);
+  ungetc (ch1, fp);
+
+  return ((ch1 << 8) | ch2);
+}
+
+int 
+getmagicno_short_pop (FILE * fp)
+{
+  int ch1, ch2;
+  ch1 = getc (fp);
+  if (ch1 == EOF)
+    return 0;
+  ch2 = getc (fp);
+  if (ch2 == EOF)
+    return 0;
+
+  return ((ch1 << 8) | ch2);  
+}
+
+int 
+getmagicno_byte (FILE * fp)
+{
+  int ch1;
+  ch1 = getc (fp);
+  if (ch1 == EOF)
+    {
+      ungetc (ch1, fp);
+      return 0;
+    }
+  ungetc (ch1, fp);
+  return (ch1);
+}
+
+
+int 
+getmagicno_long (FILE * fp)
+{
+  int ch1, ch2, ch3, ch4;
+  ch1 = getc (fp);
+  if (ch1 == EOF)
+    {
+      ungetc (ch1, fp);
+      return 0;
+    }
+  ch2 = getc (fp);
+  if (ch2 == EOF)
+    {
+      ungetc (ch2, fp);
+      return 0;
+    }
+  ch3 = getc (fp);
+  if (ch3 == EOF)
+    {
+      ungetc (ch3, fp);
+      return 0;
+    }
+  ch4 = getc (fp);
+  if (ch4 == EOF)
+    {
+      ungetc (ch4, fp);
+      return 0;
+    }
+  ungetc (ch4, fp);
+  ungetc (ch3, fp);
+  ungetc (ch2, fp);
+  ungetc (ch1, fp);
+
+  return ((ch1 << 24) | (ch2 << 16) | (ch3 << 8) | (ch4));
+}
+
+
+
+
+void 
+error_msg (char *prog, char *message, char *extra)
+{
+  fprintf (stderr, "%s: %s %s\n", prog, message, extra);
+  exit (1);
+}
+
+void 
+warn (char *prog, char *message, char *extra)
+{
+  fprintf (stderr, "%s: %s %s\n", prog, message, extra);
+}
+
+
+
+void 
+readline (char str[], FILE * fp)
+{
+  int i = 0, ch;
+
+  while (((ch = fgetc (fp)) != '\n') && (!feof (fp)))
+    str[i++] = ch;
+  str[i] = '\0';
+}
+
+
+
+
+
+
+
+int 
+getint (FILE * fp)
+{
+  register char ch;
+  register unsigned int i = 0;
+
+  do
+    {
+      ch = getc (fp);
+      if (feof (fp))
+	return EOF;
+    }
+  while (ch < '0' || ch > '9');
+
+  do
+    {
+      i = i * 10 + ch - '0';
+      ch = getc (fp);
+      if (feof (fp))
+	return EOF;
+    }
+  while (ch >= '0' && ch <= '9');
+
+  return i;
+}
+
+/* get_header_int i.e. get an integer from a PNM header ; basically  
+   the same as
+   above except for comment checking ; above kept because of lower  
+   overhead */
+
+unsigned int 
+gethint (FILE * fp)
+{
+  register char ch, prev = '\0';
+  register unsigned int i = 0;
+
+  do
+    {
+      ch = getc (fp);
+      if ((ch == '#') && (prev == '\n'))
+	while (((ch = getc (fp)) != '\n') && !(feof (fp)));
+      prev = ch;
+      if (feof (fp))
+	return EOF;
+    }
+  while (ch < '0' || ch > '9');
+
+  do
+    {
+      i = i * 10 + ch - '0';
+      ch = getc (fp);
+      if (feof (fp))
+	return EOF;
+    }
+  while (ch >= '0' && ch <= '9');
+
+  return i;
+}
+
+
+
+
+void 
+magic_write (FILE * fp, u_long magic_num)
+{
+  HTONUL(magic_num);  /* [RPAP - Jan 97: Endian Ordering] */
+  if (fwrite (&magic_num, sizeof (magic_num), 1, fp) != 1)
+    error_msg ("magic num", "Couldn't write magic number.", "");
+}
+
+
+void 
+magic_check (FILE * fp, u_long magic_num)
+{
+  u_long magic;
+  if (fread (&magic, sizeof (magic), 1, fp) != 1 || NTOHUL(magic) != magic_num)  /* [RPAP - Jan 97: Endian Ordering] */
+    error_msg ("magic num", "Incorrect magic number.", "");
+}
+
+
+u_long 
+magic_read (FILE * fp)
+{
+  u_long magic;
+  if (fread (&magic, sizeof (magic), 1, fp) != 1)
+    error_msg ("magic num", "Couldn't read magic number.", "");
+  return NTOHUL(magic);  /* [RPAP - Jan 97: Endian Ordering] */
+}
+
+
+
+
+int 
+isinteger (char s[])
+{
+  int i = 0;
+
+  for (i = 0; s[i] != '\0'; i++)
+    if (!isdigit (s[i]))
+      return 0;
+  return 1;
+}
Index: /indexers/branches/3.03a/mg/src/images/utils.h
===================================================================
--- /indexers/branches/3.03a/mg/src/images/utils.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/images/utils.h	(revision 14757)
@@ -0,0 +1,75 @@
+/**************************************************************************
+ *
+ * utils.h -- Functions which are common utilities for the image programs
+ * Copyright (C) 1994  Stuart Inglis
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef __UTILS_H
+#define __UTILS_H
+
+#include "sysfuncs.h"
+
+extern int V;
+
+#define DEBUG
+
+#define min(a,b) ((a)<(b) ? (a) : (b))
+#define max(a,b) ((a)>(b) ? (a) : (b))
+
+#define GEN_MAGIC(a,b,c,d) ((unsigned long)(((a)<<24) + ((b)<<16) + \
+                                            ((c)<<8) + (d)))
+ 
+/* --- MG magic file codes [TS:Aug/95] --- */
+#define MAGIC_FELICS            GEN_MAGIC('M','G','F','X')
+#define MAGIC_BILEVEL           GEN_MAGIC('M','G','B','I')
+#define MAGIC_TIC               GEN_MAGIC('M','G','T','C')
+#define IS_MAGIC(a) ((((u_long)(a)) & 0xffff0000) == MAGIC_XXXX)
+/* --------------------------------------- */
+
+#define MAGIC_P1      0x5031	/* P1   - pbm */
+#define MAGIC_P2      0x5032	/* P2   - pgm */
+#define MAGIC_P3      0x5033	/* P3   - ppm */
+#define MAGIC_P4      0x5034	/* P4   - rawbits pbm */
+#define MAGIC_P5      0x5035	/* P5   - rawbits pgm */
+#define MAGIC_P6      0x5036	/* P6   - rawbits ppm */
+
+int isEOF (FILE * fp);
+int getmagicno_byte (FILE * fp);
+int getmagicno_short (FILE * fp);
+int getmagicno_short_pop (FILE * fp);
+int getmagicno_long (FILE * fp);
+
+
+
+void error_msg (char *prog, char *message, char *extra);
+void warn (char *prog, char *message, char *extra);
+
+void readline (char str[], FILE * fp);
+
+void magic_write (FILE * fp, u_long magic_num);
+void magic_check (FILE * fp, u_long magic_num);
+u_long magic_read (FILE * fp);
+/* kerry's code */
+
+int getint (FILE * fp);
+unsigned int gethint (FILE * fp);
+int isinteger (char s[]);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/scripts/Makefile.in
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/Makefile.in	(revision 14757)
@@ -0,0 +1,151 @@
+###########################################################################
+#
+# Makefile.in -- Makefile for the MG system
+# Copyright (C) 1994  Neil Sharman
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#       @(#)Makefile.in	1.10 22 Mar 1994
+#
+###########################################################################
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+ 
+SHELL = /bin/sh
+VPATH = @srcdir@
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+bindir = @bindir@
+srcdir = @srcdir@
+subdir = src/scripts
+top_srcdir = @top_srcdir@
+transform = @program_transform_name@
+ 
+DEFS = @DEFS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+TOUCH = echo timestamp >
+ 
+datadir = $(prefix)/share
+libexecdir = $(exec_prefix)/libexec
+localedir = $(datadir)/locale
+mandir = $(prefix)/man/man1
+ 
+SHFILES       =	mgbuild.sh mgbuild_4.sh mg_get.sh xmg.sh  mg_get_merge.sh mgmerge.sh
+
+MISC          = Makefile.in 
+
+ALLFILES      =	$(SHFILES) $(MISC) $(MAN)
+
+DISTFILES     = $(ALLFILES) 
+
+EXEC          = mgbuild mg_get xmg mg_get_merge mgmerge mgbuild_4
+
+MAN           = mgbuild.1 mgbuild_4.1 mg_get.1 xmg.1 mg_get_merge.1 mgmerge.1
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+all:	$(EXEC)
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+mgbuild : mgbuild.sh
+	@rm -f $@
+	cat mgbuild.sh >$@
+	chmod +x $@
+
+mgbuild_4 : mgbuild_4.sh
+	@rm -f $@
+	cat mgbuild_4.sh >$@
+	chmod +x $@
+
+mg_get : mg_get.sh
+	@rm -f $@
+	cat mg_get.sh >$@
+	chmod +x $@
+
+mgmerge : mgmerge.sh
+	@rm -f $@
+	cat mgmerge.sh >$@
+	chmod +x $@
+
+mg_get_merge : mg_get_merge.sh
+	@rm -f $@
+	cat mg_get_merge.sh >$@
+	chmod +x $@
+
+xmg : xmg.sh
+	@rm -f $@
+	cat xmg.sh >$@
+	chmod +x $@
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+install: execinstall #maninstall
+uninstall: execuninstall manuninstall
+
+execinstall: $(EXEC)
+	for name in $(EXEC); do \
+	  $(INSTALL_PROGRAM) $$name \
+	  $(bindir)/`echo $$name | sed '$(transform)'`; \
+	done
+
+execuninstall:
+	for name in $(EXEC); do \
+	 rm -f $(bindir)/`echo $$name | sed '$(transform)'`; \
+	done
+
+maninstall: $(MAN)
+	$(top_srcdir)/mkinstalldirs $(mandir); \
+	for f in $(MAN); do \
+	  $(INSTALL_DATA) $$f $(mandir)/$$f ;\
+	done
+
+manuninstall: $(MAN)
+	for f in $(MAN); do \
+	  rm -f $(mandir)/$$f ;\
+	done
+
+mostlyclean:
+ 
+clean: mostlyclean
+	rm -f $(EXEC)
+ 
+distclean: clean
+	rm -f ansi2knr
+	rm -f Makefile
+ 
+maintainer-clean: distclean
+	@echo "This command is intended only for maintainers to use;"
+	@echo "rebuilding the deleted files may require special tools."
+ 
+dist: $(DISTFILES)
+	for file in $(DISTFILES); do \
+	  ln $(srcdir)/$$file $(distdir) 2> /dev/null \
+	  || cp -p $(srcdir)/$$file $(distdir); \
+	done
+
+# screws up distclean (jrm21) 
+#Makefile: Makefile.in ../../../../config.status
+#	cd ../../../.. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
+ 
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /indexers/branches/3.03a/mg/src/scripts/mg_get.1
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/mg_get.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/mg_get.1	(revision 14757)
@@ -0,0 +1,154 @@
+.TH mg_get 1 "31 January 1994"
+.SH NAME
+mg_get \- output source texts for processing
+.SH SYNOPSIS
+ 
+.B mg_get
+.I collection-name
+.RB [ \-init | \-i | \-text\fP|\fB\-t\fP|\fB\-cleanup\fP|\fB\-c\fP]
+.SH DESCRIPTION
+.LP
+This program is the default one used by mgbuild to generate the source text for the MG system. Any program may be used to generate the source text for mgbuild as long as it confirms to the interface specified here. 
+.SH OPTIONS
+.LP
+The
+.I collection\-name
+must appear before any other option. Only the first option has any significance. If no option is specified
+.B \-text
+is assumed.
+.RS
+.TP
+.BR \-init " and " \-i
+The program is called once with this flag at the start of building a collection.
+.TP
+.BR \-text " and " \-t
+The program is called with this flag multiple times during the building of a collection. The program outputs (on stdout) the text of the collection. \*(lq\fBDocuments\fP\*(rq within the collection are separated with by ctrl-B's (ASCII code 2). \*(lq\fBParagraphs\fP\*(rq within the collection are separated with ctrl-C's (ASCII code 3). A collection need not contain paragraphs unless a level 3 inverted file is being generated (see 
+.B mgbuild 
+and 
+.BR mg_passes ). 
+.TP
+.BR \-cleanup " and " \-c
+The program is called once with this flag at the completion of building a collection.
+.SH ENVIRONMENT
+.TP
+.SB MGDATA
+If this environment variable exists then its value is used a the default 
+directory where the mg collection files are. If this variable does not exist
+then the directory \*(lq\fB.\fP\*(rq is used by default. The command line 
+option 
+.BI \-d " directory"
+overrides the directory in 
+.BR MGDATA .
+.TP
+.SB MG_GETRC
+This environment variable specifies where the file containing the users 
+mg source configurations is. If not set, mg_get uses a default of 
+.B \*\~/.mg_getrc.
+
+This file contains TAB delimited lines of the form
+.RS 
+.RS 
+.I CollectionName
+.I CollectionType
+.I files or directory
+.RE
+
+.I CollectionName
+is the name of the collection supplied to mg_get.
+
+.I CollectionType
+specifies how mg_get should process the
+named files and directories and are descibed below.
+
+.I files or directory
+is either a list of files separted by blanks or a single directory.
+Some of the
+.I CollectionTypes
+deal with files and others with just a single directory.
+Any files used ending with .gz or .Z are decompressed with gzip before
+processing. References to '~' expands to the users HOME directory.
+
+.I CollectionType
+is one of
+.RS
+.TP
+.BR PARA
+For text based documents. The list of files specified are treated as
+a series of paragraphs separated by blank lines. Each paragraph becomes
+a seperate document on the indexed collection.
+.TP
+.BR MAIL
+for mail files. The list of files specified are treated as UNIX mail
+files separated by lines starting with 'From'. Each mail message becomes
+a seperate document on the indexed collection. As a extra feature any
+embedded tarmail encoded contents (enclosed by a 'xbtoa Begin' and 'xbtoa End'
+pair are removed.
+.TP
+.BR DIR
+(and DIR2)
+For a single directory of files. Each file in the directory (and in any of
+it's subdirectories) are treated as a single document. With
+.I DIR
+the pathname of the file is prefixed to the contents of each file as an
+extra line while this is not done for
+.I DIR2
+collections.
+.TP
+.BR BIB
+for biblography files. The list of files specified are treated as
+a series of biblography files (eg BIBTEX or TROFF) separated by lines
+starting with '@'. Each reference  becomes a seperate document on the indexed
+collection.
+.TP
+.BR TXTIMG
+for integrated collections of text and images. The single directory should
+contain files that have the same prefix if they are related. For example,
+monaLisa.pgm might be a gray-level image, and monaLisa.txt would be a textual
+file describing the image. The suffixes recognised are:
+.BR   .txt
+for  ascii text
+.BR  .ptm
+for  scanned text stored as a bilevel image
+.BR  .pbm
+for a black and white image (typically a line drawing)
+.BR  .pgm
+for a gray-scale image
+.BR In addition, if no corresponding ascii text file is found for
+a .pbm or .pgm file, then one is created with suffix .tmp.txt,
+and it stores the name of the image file (in principle it could
+store the OCR of a .txt.pbm file). At present the .tmp.txt files
+are deleted by the '-cleanup' option.
+
+.SH "EXAMPLE"
+
+An example ~/.mg_getrc file might look like:
+   alice   PARA    /users/alice13a.txt.Z
+   mail95  MAIL    ~/MAIL/1995/*
+   doc     DIR     ~/documents
+   bibs    BIB     ~/etc/REFS/*.bib ~/etc/REFS/CC/*.bib
+   letters DIR     ~/LETTERS
+   davinci TXTIMG  ~/images/davinci
+
+.SH "SEE ALSO"
+.LP
+.BR mg_compression_dict (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_make_fast_dict (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1)
+
Index: /indexers/branches/3.03a/mg/src/scripts/mg_get.sh
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/mg_get.sh	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/mg_get.sh	(revision 14757)
@@ -0,0 +1,447 @@
+#! /bin/csh -f
+###########################################################################
+#
+# mg_get.sh -- script to get text for mgbuild
+# Copyright (C) 1994  Tim Bell
+# Changed to allow it to be driven from a file ~/.mg_getrc
+# by Bruce McKenzie, Oct 1994
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#       @(#)mg_get.sh	1.11 25 Mar 1994
+#
+###########################################################################
+#
+# "mg_get" formats the text for mgbuild by collecting the appropriate
+#   documents, and outputing them with control-B after each document.
+#   The name of the text must be supplied as an argument.
+#   mg_get is called with -i (init) first, then with -t (text) each time the 
+#   text is needed, then with -c (cleanup).
+#   e.g. mg_get alice -t
+#
+# The file ~/.mg_get contains lines of the form:
+#     name	TYPE	files and directories
+# where name is the name supplied to mg_get, TYPE is one of
+# PARA, MAIL, DIR, DIR2, BIB or TXTIMG and says how mg_get should process the
+# named files and directories
+#
+###########################################################################
+
+if ($?MG_GETRC) then
+  set mg_getrc = $MG_GETRC
+else
+  set mg_getrc = ~/.mg_getrc
+endif
+
+# Added by [TS:May/95]
+# if we don't have an mg_getrc file in existence then create a default one
+if !(-e $mg_getrc) then 
+  echo "Can not find a .mg_getrc, so creating a default one: $mg_getrc"
+
+  if ($?MGSAMPLE) then
+    set SampleData = $MGSAMPLE
+  else
+    set SampleData = ./SampleData
+  endif
+
+  cat > $mg_getrc << END
+alice	PARA	$SampleData/alice13a.txt.Z
+davinci	TXTIMG	$SampleData/davinci
+mailfiles	MAIL	~/mbox ~/.sentmail
+allfiles	DIR	~/Mail
+mods	LINESEP	$SampleData/MODIFICATIONS
+bible	PLAIN	$SampleData/bible/genesis.txt.Z $SampleData/bible/revelation.txt.Z
+END
+endif
+
+if (! $?MGIMAGEVIEWER) then
+  setenv MGIMAGEVIEWER "xv -"
+endif
+
+set rm = /bin/rm
+
+switch ($#argv)
+  case 1:
+  set flag = '-text'
+  breaksw
+
+  case 2:
+  set flag = $2
+  switch ($flag)
+     case '-i':
+	set flag = '-init'
+	breaksw
+     case '-t':
+	set flag = '-text'
+	breaksw
+     case '-c':
+	set flag = '-cleanup'
+	breaksw
+     case '-init':
+     case '-text':
+     case '-cleanup':
+     breaksw
+     default:
+     echo 'Usage: mg_get <document> [-i | -t | -c]'
+     exit(1)
+     endsw
+  breaksw
+
+  default:
+  echo 'Usage: get <document> [-i | -t | -c]'
+  exit(1)
+  endsw
+
+set COLLECTION = $1
+set TYPE  = `grep \^$1 $mg_getrc | cut -f2`
+set FILES = `grep \^$1 $mg_getrc | cut -f3`
+
+set bindir = $0
+set bindir = $bindir:h
+
+switch ($TYPE)
+  case PLAIN:
+# Just outputs the given text, assumes ^Bs already inserted 
+  switch ($flag)
+     case '-init':
+     breaksw
+
+     case '-text':
+      foreach f ($FILES)
+	if ($f:e == 'Z') then
+	  set decoder=zcat
+	else if ($f:e == 'gz') then
+	  set decoder=gunzip
+	else
+	  set decoder=cat
+	endif
+        $decoder < $f
+      end
+     breaksw #-text
+
+     case '-cleanup':
+     breaksw
+  endsw #flag
+  breaksw
+
+  case LINESEP:
+# Assumes that the documents are separated by a line of =====
+  switch ($flag)
+     case '-init':
+     breaksw
+
+     case '-text':
+      foreach f ($FILES)
+	if ($f:e == 'Z') then
+	  set decoder=zcat
+	else if ($f:e == 'gz') then
+	  set decoder=gunzip
+	else
+	  set decoder=cat
+	endif
+        $decoder < $f |  sed -e '/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/s/.*//' < $f
+      end
+     breaksw #-text
+
+     case '-cleanup':
+     breaksw
+  endsw #flag
+  breaksw
+
+  case PARA:
+# Splits the file at blank lines, which corresponds to paragraphs.
+  switch ($flag)
+     case '-init':
+     breaksw
+
+     case '-text':
+      foreach f ($FILES)
+	if ($f:e == 'Z') then
+	  set decoder=zcat
+	else if ($f:e == 'gz') then
+	  set decoder=gunzip
+	else
+	  set decoder=cat
+	endif
+      $decoder <$f |awk '   /^ *$/ {if (b!=1) printf "";b=1} \
+		\!/^ *$/ {print;b=0} \
+		 END {printf ""}'
+       end #foreach
+     breaksw #-text
+
+     case '-cleanup':
+     breaksw
+  endsw #flag
+  breaksw
+
+  case BIB:
+# Takes a list of files that contain bibliographies, and splits them up 
+#   by putting ^B after each reference. Assumes that each reference
+#   begins with a line '^@'.
+
+  switch ($flag)
+    case '-init':
+    breaksw
+ 
+    case '-text':
+      foreach f ($FILES)
+	if ($f:e == 'Z') then
+	  set decoder=zcat
+	else if ($f:e == 'gz') then
+	  set decoder=gunzip
+	else
+	  set decoder=cat
+	endif
+      $decoder <$f |awk '/^@/&&NR!=1{printf ""} {print $0} END{print ""}'
+      end # foreach
+    breaksw #-text
+ 
+    case '-cleanup':
+    breaksw #-cleanup
+  endsw #flag
+  breaksw #BIB
+
+  case MAIL:
+# Takes a list of files that contain mail, and splits them up 
+#   by putting ^B after each message. Assumes that each message
+#   begins with a line '^From '.
+
+  switch ($flag)
+    case '-init':
+    breaksw
+ 
+    case '-text':
+      foreach f ($FILES)
+	if ($f:e == 'Z') then
+	  set decoder=zcat
+	else if ($f:e == 'gz') then
+	  set decoder=gunzip
+	else
+	  set decoder=cat
+	endif
+      $decoder <$f| awk '/xbtoa Begin/,/xbtoa End/ {next} /^From /&&NR!=1{printf ""} {print $0} END{print ""}'
+      end # foreach
+    breaksw #-text
+ 
+    case '-cleanup':
+    breaksw #-cleanup
+  endsw #flag
+  breaksw #MAIL
+
+  case DIR:
+# Recursively concatenates every file in every subdirectory of the given
+#   directory.
+
+  switch ($flag)
+    case '-init':
+    breaksw
+
+    case '-text'
+      find $FILES -type f -name '*.gz' -exec echo '<' {} '>' \;		\
+			 -exec gzcat {} \; -exec echo -n '' \;
+      find $FILES -type f -name '*.Z' -exec echo '<' {} '>' \;		\
+			 -exec zcat {} \; -exec echo -n '' \;
+#     find $FILES -type f -not -regex '.*\.\(gz\|Z\)' -exec echo '<' {} \
+#			'>' \; -exec cat {} \; -exec echo -n '' \;
+      find $FILES -type f \! \( -name '*.gz' -o -name '*.Z' \) \
+			-exec echo '<' {} '>' \; \
+			-exec cat {} \; -exec echo -n '' \;
+
+    breaksw
+
+    case '-cleanup':
+    breaksw #-cleanup
+  endsw #flag
+  breaksw #DIR
+
+
+
+  case DIR2:
+# Recursively concatenates every file in every subdirectory of the given
+#   directory. Does not include filename
+
+  switch ($flag)
+    case '-init':
+    breaksw
+
+    case '-text'
+      find $FILES -type f -name '*.gz'  		\
+			 -exec gzcat {} \; -exec echo -n '' \;
+      find $FILES -type f -name '*.Z' 	 		\
+			 -exec zcat {} \; -exec echo -n '' \;
+#     find $FILES -type f -not -regex '.*\.\(gz\|Z\)'	\
+#			-exec cat {} \; -exec echo -n '' \;
+      find $FILES -type f \! \( -name '*.gz' -o -name '*.Z' \) \
+			-exec cat {} \; -exec echo -n '' \;
+    breaksw
+
+    case '-cleanup':
+    breaksw #-cleanup
+  endsw #flag
+  breaksw #DIR2
+
+
+
+
+  case TXTIMG:
+# compress and index the collection of text and images
+# (this code is suitable for all sorts of integrated collections
+#  of text and images)
+# Files that are related have the same prefix. For example,
+#  monaLisa.pgm might be a gray-level image, and
+#  monaLisa.txt would be a textual file describing the image.
+# The suffixes recognised are:
+#    .txt	ascii text
+#    .ptm	scanned text stored as a bilevel image
+#    .pbm	a black and white image (typically a line drawing)
+#    .pgm	a gray-scale image
+# In addition, if no corresponding ascii text file is found for
+#  a .pbm or .pgm file, then one is created with suffix .tmp.txt,
+#  and it stores the name of the image file (in principle it could
+#  store the OCR of a .txt.pbm file). At present the .tmp.txt files
+#  are deleted by the '-cleanup' option.
+  
+#### the next two 'set' statements define which directory the files
+#    come from, and where they will be stored. This is the only
+#    part of this code that is specific to the 'davinci' collection
+  set sourceDir = $FILES
+  set targetDir = $MGDATA/$COLLECTION
+
+  switch ($flag)
+    case '-init':
+      mkdir $targetDir >&/dev/null	   # create the directory to store
+					   # compressed images in
+      $rm -rf $targetDir/* >&/dev/null     # in case it already existed
+    
+      # take care if no match to foreach statements
+      set nonomatch
+
+      # process all pbm (black and white) images of text
+      foreach f ($sourceDir/*.ptm)
+        if ($f == "$sourceDir/*.ptm") then
+                break
+        endif
+	set base = $f:t
+	
+        $bindir/mgticbuild $targetDir/$base:r.ticlib.$$ $f
+        $bindir/mgticprune $targetDir/$base:r.ticlib.$$
+
+	$bindir/mgtic -L -e $targetDir/$base:r.ticlib.$$ $f >$targetDir/$base:r.tic
+	$rm $targetDir/$base:r.ticlib.$$
+	set r = $f:r	#root name of file
+	if (! (-e $r.txt || -e $r.tmp)) then
+	# creates a file; could do OCR here to get its contents
+	    echo "No corresponding txt file for" $f "- creating" $r.tmp
+	    echo '#######' $f > $r.tmp
+	endif
+      end
+      # process all pgm (gray scale) images
+      foreach f ($sourceDir/*.pgm)
+        if ($f == "$sourceDir/*.pgm") then
+                break
+        endif
+	set base = $f:t
+	$bindir/mgfelics -e $f >$targetDir/$base:r.flx
+	set r = $f:r	#root name of file
+	if (! (-e $r.txt || -e $r.tmp)) then
+	# creates a file; could do image recognition here to create one(!)
+	    echo "No corresponding txt file for" $f "- creating" $r.tmp
+	    echo '#######' $f > $r.tmp
+	endif
+      end
+      # process all pbm (black and white) images
+      foreach f ($sourceDir/*.pbm)
+        if ($f == "$sourceDir/*.pbm") then
+                break
+        endif
+	set base = $f:t
+	$bindir/mgbilevel -e $f >$targetDir/$base:r.blv
+	set r = $f:r	#root name of file
+	if (! (-e $r.txt || -e $r.tmp)) then
+	# creates a file; could do drawing recognition here to create one(!)
+	    echo "No corresponding txt file for" $f "- creating" $r.tmp
+	    echo '####### No corresponding text file available for this image' >$r.tmp
+	    echo 'Original image file name was' $f >> $r.tmp
+	endif
+      end
+      unset nonomatch
+    breaksw #-init
+
+    case '-text'
+      # take care if no match to foreach statements
+      set nonomatch
+
+      #output each text file and tmp.txt, with names of other associated files
+
+      foreach f ($sourceDir/*.txt $sourceDir/*.tmp)
+        if ($f == "$sourceDir/*.txt") then
+           continue
+        endif
+        if ($f == "$sourceDir/*.tmp") then
+           continue
+        endif
+	set r = $f:r	#root name of file
+	set base = $r:t
+        set first_image = 1 # set so that I print out image header once
+                            # also signifies if header printed out at all
+
+	foreach d ($targetDir/$base.*)
+          if ($d == "$targetDir/$base.*") then
+                break
+          endif
+
+          if ($first_image) then
+            set first_image = 0
+            echo '::::::::::'  #separate the image information from the text
+            echo 'Image(s) available:'
+          endif
+
+	  switch ($d:e)	# work out decoding method from suffix
+            case 'tic':
+              echo 'MGDATA (mgtic -d ' $d '  | '$MGIMAGEVIEWER') '
+            breaksw
+            case 'flx':
+              echo 'MGDATA (mgfelics -d ' $d '  | '$MGIMAGEVIEWER')'
+            breaksw
+            case 'blv':
+              echo 'MGDATA (mgbilevel -d ' $d '  | '$MGIMAGEVIEWER')'
+	    breaksw
+	  endsw # $d:e (suffix)
+
+	end #foreach d (associated file)
+
+        if (! $first_image) then
+	  echo '::::::::::'  #separate the image information from the text
+        endif
+
+	cat $f  # output the text associated with the images
+	echo -n ''
+      end #foreach f (text file)
+      unset nonomatch
+    breaksw #-text
+
+    case '-cleanup':
+      #remove temporary text files
+      $rm $sourceDir/*.tmp
+    breaksw #-cleanup
+  endsw #flag
+  breaksw #IMGTXT
+
+
+  default:
+    echo 'Sorry, I do not know how to get' $1
+    exit 1	
+endsw
+exit 0
Index: /indexers/branches/3.03a/mg/src/scripts/mg_get_merge.1
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/mg_get_merge.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/mg_get_merge.1	(revision 14757)
@@ -0,0 +1,86 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_get_merge 1 \*(Dt CITRI
+.SH NAME
+mg_get_merge \- output source texts for processing
+.SH SYNOPSIS
+.B mg_get_merge
+.I collection-name
+.if n .ti +9n
+[
+.BR \-init " |"
+.BR \-i " |"
+.BR \-text " |"
+.BR \-t " |"
+.BR \-cleanup " |"
+.B  \-c
+]
+.SH DESCRIPTION
+This program is the default one used by
+.BR mgmerge (1)
+to generate the source text for new documents to appended to
+an
+.BR mg (1)
+system database.
+Its function is exactly the same as
+.BR mg_get (1)
+except that it generates the 
+.I new 
+documents to be added to an
+.BR mg (1)
+system database that has already been built using
+.BR mgbuild(1).
+Any program may be used to generate the source
+text for
+.BR mgmerge (1),
+as long as it confirms to the interface specified
+here.
+.SH OPTIONS
+The
+.I collection-name
+must appear before any other option.  Only the first option has any
+significance.  If no option is specified,
+.B \-text
+is assumed.
+.TP "\w'\fB\-cleanup\fP and \fB\-c\fP'u+2n"
+.BR \-init " and " \-i
+The program is called once with this flag at the start of merging a
+collection.
+.TP
+.BR \-text " and " \-t
+The program is called with this flag multiple times during the
+merging of a collection.  The program outputs (on
+.IR stdout )
+the text of the collection.
+.I Documents
+within the collection are separated by ctrl-B's (ASCII code 2).
+.TP
+.BR \-cleanup " and " \-c
+The program is called once with this flag at the completion of
+merging a collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_get (1),
+.BR mgbuild (1),
+.BR mgmerge (1),
+.BR mg_text_merge (1),
+.BR mg_invf_merge (1).
Index: /indexers/branches/3.03a/mg/src/scripts/mg_get_merge.sh
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/mg_get_merge.sh	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/mg_get_merge.sh	(revision 14757)
@@ -0,0 +1,313 @@
+#! /bin/csh -f
+###########################################################################
+#
+# mg_get_merge.sh -- script to get text for mgbuild
+# Copyright (C) 1994  Tim Bell, Shane Hudson (mods. for merging)
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+###########################################################################
+#
+# "mg_get_merge" formats the text for mgbuild by collecting the appropriate
+#   documents, and outputing them with control-B after each document.
+#   The name of the text must be supplied as an argument.
+#   mg_get is called with -i (init) first, then with -t (text) each time the 
+#   text is needed, then with -c (cleanup).
+#   e.g. mg_get alice -t
+#
+###########################################################################
+
+
+
+# The directory containing the data files is stored in the environment
+#   variable MGSAMPLE
+
+if ($?MGSAMPLE) then
+  set SampleData = $MGSAMPLE
+else
+  set SampleData = ./SampleData
+endif
+
+if (! $?MGIMAGEVIEWER) then
+  setenv MGIMAGEVIEWER "xv -"
+endif
+
+set rm = /bin/rm
+
+switch ($#argv)
+  case 1:
+  set flag = '-text'
+  breaksw
+
+  case 2:
+  set flag = $2
+  switch ($flag)
+     case '-i':
+	set flag = '-init'
+	breaksw
+     case '-t':
+	set flag = '-text'
+	breaksw
+     case '-c':
+	set flag = '-cleanup'
+	breaksw
+     case '-init':
+     case '-text':
+     case '-cleanup':
+     breaksw
+     default:
+     echo 'Usage: get <document> [-i | -t | -c]'
+     exit(1)
+     endsw
+  breaksw
+
+  default:
+  echo 'Usage: get <document> [-i | -t | -c]'
+  exit(1)
+  endsw
+
+set bindir = $0
+set bindir = $bindir:h
+
+switch ($1)
+  case alice:
+  switch ($flag)
+     case '-init':
+     breaksw
+
+     case '-text':
+	echo "This is a test document 1 2 3 4 5 6 7 8 9 "
+	echo ""
+	echo "A B C"
+     breaksw
+
+     case '-cleanup':
+     breaksw
+  endsw #flag
+  breaksw
+
+  case bible:
+  switch ($flag)
+    case '-init':
+    breaksw
+
+    case '-text':
+       # use uncompressed file if it exists
+       # revelation.txt already contains '^B' characters between verses
+       if (-e $SampleData/bible/revelation.txt) then
+          cat $SampleData/bible/revelation.txt
+       else
+          uncompress <$SampleData/bible/revelation.txt.Z
+    breaksw #-text
+
+    case '-cleanup':
+    breaksw #-cleanup
+
+  endsw #flag
+  breaksw #bible
+
+
+
+  case mailfiles:
+# Takes a list of files that contain mail, and splits them up 
+#   by putting ^B after each message. Assumes that each message
+#   begins with a line '^From '.
+# If messages are already in individual files, use "get allfiles"
+#   rather than this one.
+# The EXTRA documents added are in files in the directory mailextra
+#### The variable 'mailfiles' contains a list of files to be split up
+  set mailfiles = '~/mbox ~/.sentmail'
+  set mailextra = '~/extra/*'
+
+  switch ($flag)
+    case '-init':
+    breaksw
+
+    case '-text':
+      foreach f ($mailextra)
+	awk '/^From /&&NR!=1{print ""} {print $0} END{print ""}' $f
+      end # foreach
+    breaksw #-text
+
+    case '-cleanup':
+    breaksw #-cleanup
+
+  endsw #flag
+  breaksw #mailfiles
+
+
+
+  case allfiles:
+# Recursively concatenates every file in every subdirectory of the given
+#   directory.
+
+# The variable 'directory' on the next line contains the directory to be used
+  set directory = ~/Mail
+
+# The date of the file ".mgbuildtime" in 'directory' is the last
+# build or merge. At the start of the merge ("-init" argument) the
+# file ".mgmergetime" is touched. Only files newer than ".mgbuildtime"
+# but older than ".mgmergetime" are output by mg_get_merge
+
+  switch ($flag)
+    case '-init':
+        touch $directory/.mgmergetime
+    breaksw
+
+    case '-text'
+      find $directory -type f -newer $directory/.mgbuildtime \! -newer $directory/.mgmergetime \! -name '.*' -exec echo '<' {} '>' \; -exec cat {} \; -exec echo -n '' \;
+    breaksw
+
+    case '-cleanup':
+        touch $directory/.mgmergetime
+        touch $directory/.mgbuildtime
+    breaksw #-cleanup
+  endsw #flag
+  breaksw #allfiles
+
+
+
+
+  case davinci:
+# compress and index the DaVinci collection of text and images
+# (this code is suitable for all sorts of integrated collections
+#  of text and images)
+# It assumes that all files are in one directory ($sourceDir).
+# Files that are related have the same prefix. For example,
+#  monaLisa.img.pgm might be a gray-level image, and
+#  monaLisa.txt.txt would be a textual file describing the image.
+# The suffixes recognised are:
+#    .txt.txt	ascii text
+#    .txt.pbm	scanned text stored as a bilevel image
+#    .img.pbm	a black and white image (typically a line drawing)
+#    .img.pgm	a gray-scale image
+# In addition, if no corresponding ascii text file is found for
+#  a .pbm or .pgm file, then one is created with suffix .tmp.txt,
+#  and it stores the name of the image file (in principle it could
+#  store the OCR of a .txt.pbm file). At present the .tmp.txt files
+#  are deleted by the '-cleanup' option.
+  
+#### the next two 'set' statements define which directory the files
+#    come from, and where they will be stored. This is the only
+#    part of this code that is specific to the 'davinci' collection
+  set sourceDir = $SampleData/davinci
+  set targetDir = $MGDATA/davinci
+
+  switch ($flag)
+    case '-init':
+      mkdir $targetDir >&/dev/null	   #create the directory to store
+					   # compressed images in
+      $rm -rf $targetDir/* >&/dev/null #in case it already existed
+    
+      # process all pbm (black and white) images of text
+      foreach f ($sourceDir/*.ptm)
+	set base = $f:t
+	
+        $bindir/mgticbuild $targetDir/$base:r.ticlib.$$ $f
+        $bindir/mgticprune $targetDir/$base:r.ticlib.$$
+
+	$bindir/mgtic -L -e $targetDir/$base:r.ticlib.$$ $f >$targetDir/$base:r.tic
+	$rm $targetDir/$base:r.ticlib.$$
+	set r = $f:r	#root name of file
+	if (! (-e $r.txt || -e $r.tmp)) then
+	# creates a file; could do OCR here to get its contents
+	    echo "No corresponding txt file for" $f "- creating" $r.tmp
+	    echo '#######' $f > $r.tmp
+	endif
+      end
+      # process all pgm (gray scale) images
+      foreach f ($sourceDir/*.pgm)
+	set base = $f:t
+	$bindir/mgfelics -e $f >$targetDir/$base:r.flx
+	set r = $f:r	#root name of file
+	if (! (-e $r.txt || -e $r.tmp)) then
+	# creates a file; could do image recognition here to create one(!)
+	    echo "No corresponding txt file for" $f "- creating" $r.tmp
+	    echo '#######' $f > $r.tmp
+	endif
+      end
+      # process all pbm (black and white) images
+      foreach f ($sourceDir/*.pbm)
+	set base = $f:t
+	$bindir/mgbilevel -e $f >$targetDir/$base:r.blv
+	set r = $f:r	#root name of file
+	if (! (-e $r.txt || -e $r.tmp)) then
+	# creates a file; could do drawing recognition here to create one(!)
+	    echo "No corresponding txt file for" $f "- creating" $r.tmp
+	    echo '####### No corresponding text file available for this image' >$r.tmp
+	    echo 'Original image file name was' $f >> $r.tmp
+	endif
+      end
+    breaksw #-init
+
+    case '-text'
+      #output each text file and tmp.txt, with names of other associated files
+      foreach f ($sourceDir/*.txt $sourceDir/*.tmp)
+	set r = $f:r	#root name of file
+	set base = $r:t
+	set n = `/bin/ls $sourceDir/$base.* | wc -l`
+	if ($n != 1) then # more files than just the text one
+	 echo '::::::::::'  #separate the image information from the text
+	 echo 'Image(s) available:'
+	 foreach d ($targetDir/$base.*)
+	  switch ($d:e)	# work out decoding method from suffix
+            case 'tic':
+              echo 'MGDATA (mgtic -d ' $d '  | '$MGIMAGEVIEWER') '
+            breaksw
+            case 'flx':
+              echo 'MGDATA (mgfelics -d ' $d '  | '$MGIMAGEVIEWER')'
+            breaksw
+            case 'blv':
+              echo 'MGDATA (mgbilevel -d ' $d '  | '$MGIMAGEVIEWER')'
+	    breaksw
+	  endsw # $d:e (suffix)
+	 end #foreach d (associated file)
+	echo '::::::::::'  #separate the image information from the text
+	endif # if more than one file
+	cat $f  # output the text associated with the images
+	echo -n ''
+      end #foreach f (text file)
+    breaksw #-text
+
+    case '-cleanup':
+      #remove temporary text files
+      $rm $sourceDir/*.tmp
+    breaksw #-cleanup
+  endsw #flag
+  breaksw #davinci
+
+
+#---------------------------
+  case mods:
+# Splits the modifications file at the mod separator "--------"
+  switch ($flag)
+     case '-init':
+     breaksw
+ 
+     case '-text':
+       sed -e 's/^---.*//g' < ${SampleData}/MODIFICATIONS
+     breaksw
+ 
+     case '-cleanup':
+     breaksw
+  endsw #flag
+  breaksw #mods
+
+  default:
+    echo 'Sorry, I do not know how to get' $1
+    exit 1	
+endsw
+exit 0
Index: /indexers/branches/3.03a/mg/src/scripts/mgbuild.1
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/mgbuild.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/mgbuild.1	(revision 14757)
@@ -0,0 +1,169 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgbuild 1 \*(Dt CITRI
+.SH NAME
+mgbuild \- build an mg system database
+.SH SYNOPSIS
+.B mgbuild
+[
+.B \-c
+]
+[
+.BI \-g " get"
+]
+[
+.BI \-s " source"
+]
+[
+.BI \-d " mgdata dir"
+]
+.I collection-name
+.SH DESCRIPTION
+.B mgbuild
+is a
+.B csh
+script that executes all the appropriate programs in the correct order
+to completely build an
+.BR mg (1)
+system database ready for queries to be made
+by
+.BR mgquery.
+This program makes use of the
+.BR mg_get (1)
+script to obtain the text of the collection.
+.SH OPTIONS
+Options can occur in any order, but the collection name must be last.
+.TP "\w'\fIcollection-name\fP'u+2n"
+.BI \-c
+This specifies whether the
+.I get
+program is \*(lqcomplex\*(rq.  If a
+.I get
+program is \*(lqcomplex\*(rq, then it requires initialisation and
+cleanup with the
+.B \-i
+and
+.B \-c
+options.
+.TP
+.BI \-g " get"
+This specifies the program to use for getting the source text for the
+build.  If no
+.B \-g
+option is given, the default program
+.BR mg_get (1)
+is used.
+.TP
+.BI \-s " source"
+The
+.B mgbuild
+program consists of two parts.  The first part initializes variables
+to default values.  The second part uses these variables to control
+how the
+.BR mg (1)
+database is built.  This option specifies a program to execute between
+the first and second parts.  The details of what the variables are, and
+how they may be changed, are in comments in the
+.B mgbuild
+program.
+.TP
+.BI \-d " mgdata dir"
+Setting this option allows one to override the MGDATA environment variable.
+.TP
+.I collection-name
+This is the collection name, as required by the
+.BR mg_get (1)
+program.  It serves both as a
+.I case
+statement selector, and as the name of a subdirectory that holds the
+indexing files.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.chunk
+Inverted file chunk descriptor file.  When the inverted file is
+created, it is written in chunks that use no more than a set amount of
+memory.  This file describes those chunks.
+.TP
+.B *.invf.chunk.trans
+Word-occurrence-order to lexical-order translation file.  The
+.B *.invf.chunk
+file is written in word-occurrence order but is required by
+.B \-N2
+to be in lexical order.
+.TP
+.B *.invf.dict
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict.blocked
+The `on-disk' stemmed dictionary.
+.TP
+.B *.invf.dict.hash
+Data for an order-preserving perfect hash function.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.B *.text
+Compressed documents.
+.TP
+.B *.text.stats
+Text statistics.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.text.idx.wgt
+Interleaved index into the compressed documents and document weights.
+.TP
+.B *.weight.approx
+Approximate document weights.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/scripts/mgbuild.sh
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/mgbuild.sh	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/mgbuild.sh	(revision 14757)
@@ -0,0 +1,339 @@
+#!/bin/csh -f
+###########################################################################
+#
+# mgbuild.sh -- Script used to build mg text collection.
+# Copyright (C) 1994  Neil Sharman
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#       @(#)mgbuild.sh	1.9 16 Mar 1994
+#
+###########################################################################
+#  mg.build
+# Creates a Full Text Retrieval database
+#
+#  @(#)mgbuild.sh	1.9 16 Mar 1994
+#
+
+set complex = ""
+
+# Parse the command line arguments
+while ($#argv >= 1)
+  if ("$1" == "-s") then
+    shift
+    if ($#argv >= 1) then
+      set source = $1
+      shift
+    endif
+  else if ("$1" == "-d") then
+    shift
+    if ($#argv >= 1) then
+      set mgdata = $1
+      shift
+    endif
+  else if ("$1" == "-g") then
+    shift
+    if ($#argv >= 1) then
+      set get = $1
+      shift
+    endif
+  else if ("$1" == "-c") then
+    set complex = "-text"
+    shift
+  else
+    if ($?text == "0") then
+      set text = $1
+    endif
+    shift
+  endif
+    
+end
+
+if ($?text == "0") then
+  set prog = $0
+  echo "USAGE:"
+  echo "     "$prog:t" [-s config-script] [-g get-program] [-d mgdata dir] [-c] source"
+  echo ""
+  echo " The config-script is only needed if a non-standard build is required."
+  echo " The get-program defaults to mg_get if not specified."
+  exit 1	
+endif
+
+set bindir = $0
+set bindir = $bindir:h
+
+# if $pipe == 1 then pipe in the source text using $get and $text otherwise
+# read the source text directly from the file names specified in $input_files
+set pipe = 1
+
+if ($?get == "0") then
+  set complex = "-text"
+  set get = $bindir/mg_get
+endif
+
+if ($?mgdata) then
+  setenv MGDATA $mgdata
+endif
+
+if (-e $MGDATA/${text}.chunks) then
+  set input_files = `cat $MGDATA/${text}.chunks`
+endif
+
+# Set the stemming method
+#   Bit 0 = case folding
+#   Bit 1 = S stemmer
+set stem_method = 3
+
+
+# [RPAP - Jan 97: Stem Index Change]
+# If do_indexes == 1 then build collection with full indexes to blocked file
+# overriding stem_method (stem_method will be set to 0)
+# Otherwise don't build with indexes
+set do_indexes = 0
+
+
+# If do_text == 1 then do the text component of building a mg database. 
+# Otherwise don't do the text component.
+set do_text = 1
+
+
+# If do_invf == 1 then do the inversion component of building a mg database. 
+# Otherwise don't do the inversion component.
+set do_invf = 1
+
+
+# If do_pass1 == 1 then do pass1 of building a mg database. 
+# Otherwise don't do pass1.
+set do_pass1 = 1
+
+# If do_pass2 == 1 then do pass2 of building a mg database. 
+# Otherwise don't do pass2.
+set do_pass2 = 1
+
+
+# $invf_mem specifies the amount of memory to use for the pass2 inversion
+set invf_mem = 32
+
+
+# $num_chunks specifies the number of interium chunks of inverted file that
+# may be written to disc before a merge into the invf file is done
+set num_chunks = 3
+
+# $invf_level specifies the level of the inverted file that will be generated.
+set invf_level = 2
+
+
+# If $strip_sgml == 1 then sgml tags are stripped from the inversion phase.
+# Otherwise sgml tags are kepted.
+set strip_sgml = 1
+
+
+# $trace specifies the interval between trace entries in Mb.
+# If this is not set no trace entries will be generated.
+set trace = 10
+
+
+# $weight_bits specifies the number of bits of precision bo be given to the 
+# approximate weights.
+set weight_bits = 6
+
+
+# $mcd specifies the commandline arguments for the mg_compression_dict program
+#### Note: Set -S so novel words can be encoded, as this will happen if
+#### mgmerge is used.
+set mcd = -S
+
+
+# Source the parameter file to modify parameters of the build.
+if ($?source) then
+  source ${source}
+endif
+
+
+# [RPAP - Jan 97: Stem Index Change]
+# If do_indexes == 1 then set stem_method = 0
+if ("$do_indexes" == "1") then
+  set stem_method = 0
+endif
+
+
+# Generate the collection name.
+set coll_name = ${text}
+if ("$invf_level" == "3") then
+  set coll_name = ${text}-p
+endif
+
+# Generate the directory for the collection.
+if (-e $MGDATA/${coll_name}) then
+else
+  mkdir $MGDATA/${coll_name}
+endif
+
+# Generate the base name for the collection.
+set bname = ${coll_name}/${coll_name}
+
+
+#build up the command lines for pass 1 and 2
+set pass1 = (-f ${bname} -${invf_level} -m ${invf_mem} -s ${stem_method})
+set pass2 = (-f ${bname} -${invf_level} -c ${num_chunks})
+
+if ($strip_sgml) then
+  set pass1 = (${pass1} -G)
+  set pass2 = (${pass2} -G)
+endif
+
+if ($?trace) then
+  set pass1 = (${pass1} -t ${trace})
+  set pass2 = (${pass2} -t ${trace})
+endif
+
+if ($do_text) then
+  set pass1 = (${pass1} -T1)
+  set pass2 = (${pass2} -T2)
+endif
+
+if ($do_invf) then
+  set pass1 = (${pass1} -I1)
+  set pass2 = (${pass2} -I2)
+endif
+  
+if ($?trace_name) then
+  set pass1 = (${pass1} -n ${trace_name})
+  set pass2 = (${pass2} -n ${trace_name})
+endif
+  
+if ($?comp_stats) then
+  set pass2 = (${pass2} -C ${comp_stats})
+endif
+
+echo "-----------------------------------"
+echo "`uname -n`, `date`"
+echo "${text} --> ${bname}"
+echo "-----------------------------------"
+if ($pipe) then
+  if ("$complex" != "") then
+    echo "$get $text -init"
+    $get $text -init
+    if ("$status" != "0") exit 1 
+    echo "-----------------------------------"
+  endif  
+endif
+
+if (${do_pass1}) then
+  if ($pipe) then
+    if ($?pass1filter) then
+      echo "$get $text $complex | $pass1filter | mg_passes ${pass1}"
+      $get $text $complex| $pass1filter | $bindir/mg_passes ${pass1}
+      if ("$status" != "0") exit 1 
+    else
+      echo "$get $text $complex | mg_passes ${pass1}"
+      $get $text $complex| $bindir/mg_passes ${pass1}
+      if ("$status" != "0") exit 1 
+    endif
+  else
+    echo mg_passes ${pass1} ${input_files}
+    $bindir/mg_passes ${pass1} ${input_files}
+    if ("$status" != "0") exit 1 
+  endif
+  echo "-----------------------------------"
+
+  echo "mg_perf_hash_build -f ${bname}"
+  $bindir/mg_perf_hash_build -f ${bname}
+  if ("$status" != "0") exit 1 
+
+  echo "-----------------------------------"
+  echo "mg_compression_dict -f ${bname} ${mcd}"
+  $bindir/mg_compression_dict -f ${bname} ${mcd}
+  if ("$status" != "0") exit 1 
+  echo "-----------------------------------"
+endif
+
+if (${do_pass2}) then
+  if ($pipe) then
+    if ($?pass2filter) then
+      echo "$get $text $complex | $pass2filter | mg_passes ${pass2}"
+      $get $text $complex | $pass2filter | $bindir/mg_passes ${pass2}
+      if ("$status" != "0") exit 1 
+    else
+      echo "$get $text $complex | mg_passes ${pass2}"
+      $get $text $complex | $bindir/mg_passes ${pass2}
+      if ("$status" != "0") exit 1 
+    endif
+  else
+    echo mg_passes ${pass2} ${input_files}
+    $bindir/mg_passes ${pass2} ${input_files}
+    if ("$status" != "0") exit 1 
+  endif
+  echo "-----------------------------------"
+endif
+
+echo "mg_weights_build -f ${bname} -b ${weight_bits}"
+$bindir/mg_weights_build -f ${bname} -b ${weight_bits}
+if ("$status" != "0") exit 1 
+
+echo "-----------------------------------"
+
+echo "mg_invf_dict -f ${bname} -b 4096"
+$bindir/mg_invf_dict -f ${bname} -b 4096
+if ("$status" != "0") exit 1 
+
+echo "-----------------------------------"
+
+# [RPAP - Jan 97: Stem Index Change]
+if ("$do_indexes" == "1") then
+  echo "mg_stem_idx -f ${bname} -b 4096 -s1"
+  $bindir/mg_stem_idx -f ${bname} -b 4096 -s1
+  if ("$status" != "0") exit 1 
+
+  echo ""
+
+  echo "mg_stem_idx -f ${bname} -b 4096 -s2"
+  $bindir/mg_stem_idx -f ${bname} -b 4096 -s2
+  if ("$status" != "0") exit 1 
+
+  echo ""
+
+  echo "mg_stem_idx -f ${bname} -b 4096 -s3"
+  $bindir/mg_stem_idx -f ${bname} -b 4096 -s3
+  if ("$status" != "0") exit 1 
+
+  echo "-----------------------------------"
+endif
+
+echo "mgstat -f ${bname} -E"
+$bindir/mgstat -f ${bname} -E
+if ("$status" != "0") exit 1 
+
+if ($pipe) then
+  if ("$complex" != "") then
+    echo "-----------------------------------"
+    echo "$get $text -cleanup"
+    $get $text -cleanup
+    if ("$status" != "0") exit 1 
+  endif
+endif
+
+echo "-----------------------------------"
+echo "`uname -n`, `date`"
+echo "-----------------------------------"
+
+echo "-- The fast-loading compression dictionary has not been built."
+echo "-- If you wish to build it, execute the following command:"
+echo "-- "$bindir/mg_fast_comp_dict -f ${bname}
+
+echo "-----------------------------------"
+
+echo ""
+
Index: /indexers/branches/3.03a/mg/src/scripts/mgbuild_4.1
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/mgbuild_4.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/mgbuild_4.1	(revision 14757)
@@ -0,0 +1,53 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgbuild_4 1 \*(Dt CITRI
+.SH NAME
+mgbuild_4 \- build an mg system database using 4 passes instead of 2
+.SH SYNOPSIS
+.B mgbuild_4
+[
+.B \-c
+]
+[
+.BI \-g " get"
+]
+[
+.BI \-s " source"
+]
+[
+.BI \-d " mgdata dir"
+]
+.I collection-name
+.SH DESCRIPTION
+.B mgbuild_4
+is a
+.B csh
+script that executes all the appropriate programs in the correct order
+to completely build an
+.BR mg (1)
+system database ready for queries to be made
+by
+.BR mgquery.
+This program makes use of the
+.BR mg_get (1)
+script to obtain the text of the collection.
+In 
+.BR mgbuild (1)
+the build is done by two passes over the input text. The first
+pass creates the compressed text dictionary and inverted file dictionary,
+the second pass creates the compressed text and inverted file. What 
+.BR mgbuild_4
+does is use a separate pass for each function. This will be slower but will
+not require as much RAM at one time. Therefore, if your build is failing
+due to running short of memory, then 
+.BR mgbuild_4
+is worth a try.
+.SH "SEE ALSO"
+.na
+.BR mgbuild (1)
Index: /indexers/branches/3.03a/mg/src/scripts/mgbuild_4.sh
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/mgbuild_4.sh	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/mgbuild_4.sh	(revision 14757)
@@ -0,0 +1,435 @@
+#!/bin/csh -f
+###########################################################################
+#
+# mgbuild_4.sh -- Script used to build mg text collection in 4 passes.
+# Copyright (C) 1994  Neil Sharman; Modified by tes@kbs 1995
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+###########################################################################
+#
+# Does an mgbuild in 4 passes instead of 2 passes.
+# This is useful if one does not have as much RAM and a large collection.
+#
+
+set complex = ""
+
+# ************ parse the command line arguments ************
+
+while ($#argv >= 1)
+  if ("$1" == "-s" || "$1" == "--source") then
+    shift
+    if ($#argv >= 1) then
+      set source = $1
+      shift
+    endif
+  else if ("$1" == "-g" || "$1" == "--get") then
+    shift
+    if ($#argv >= 1) then
+      set get = $1
+      shift
+    endif
+  else if ("$1" == "-c" || "$1" == "--complex") then
+    set complex = "-text"
+    shift
+  else
+    if (! $?text ) then
+      set text = $1
+    endif
+    shift
+  endif
+    
+end
+
+if (! $?text ) then
+  set prog = $0
+  echo "USAGE:"
+  echo "     "$prog:t" [-s config-script] [-g get-program] [-c] source"
+  echo ""
+  echo " The config-script is only needed if a non-standard build is required."
+  echo " The get-program defaults to mg_get if not specified."
+  exit 1	
+endif
+
+set bindir = `which $0` # find which one we are executing
+set bindir = $bindir:h # use it as the bindir path
+
+# ************ set up shell variables ************
+# Override these by providing a script to source using the -s option
+
+# if $pipe == 1 then pipe in the source text using $get and $text otherwise
+# read the source text directly from the file names specified in $input_files
+set pipe = 1
+
+set get_options = ""
+
+
+if (! $?get ) then
+  set complex = "-text"
+  set get = $bindir/mg_get $get_options
+endif
+
+
+if (-e $MGDATA/${text}.chunks) then
+  set input_files = `cat $MGDATA/${text}.chunks`
+endif
+
+# Set the stemming method
+#   Bit 0 = case folding
+#   Bit 1 = S stemmer
+set stem_method = 3
+
+
+# [RPAP - Jan 97: Stem Index Change]
+# If do_indexes == 1 then build collection with full indexes to blocked file
+# overriding stem_method (stem_method will be set to 0)
+# Otherwise don't build with indexes
+set do_indexes = 0
+
+
+# whether to build weights or not
+set do_weights = 1
+
+# If do_pass1 == 1 then do pass1 of building a mg database. 
+# Otherwise don't do pass1.
+# Text 1st pass
+set do_pass1 = 1
+
+# If do_pass2 == 1 then do pass2 of building a mg database. 
+# Otherwise don't do pass2.
+# Text 2nd pass
+set do_pass2 = 1
+
+# If do_pass3 == 1 then do pass3 of building a mg database. 
+# Otherwise don't do pass3.
+# Invf 1st pass
+set do_pass3 = 1
+
+# If do_pass4 == 1 then do pass4 of building a mg database. 
+# Otherwise don't do pass4.
+# Invf 2nd pass
+set do_pass4 = 1
+
+# Buffer size used by mg_passes
+# Should be big enough to hold largest document
+# In Kilobytes
+set buf_size = 3072
+
+# $invf_mem specifies the amount of memory to use for the pass2 inversion
+set invf_mem = 5
+
+# $num_chunks specifies the number of interium chunks of inverted file that
+# may be written to disc before a merge into the invf file is done
+set num_chunks = 3
+
+# $invf_level specifies the level of the inverted file that will be generated.
+set invf_level = 2
+
+
+# If $strip_sgml == 1 then sgml tags are stripped from the inversion phase.
+# Otherwise sgml tags are kepted.
+set strip_sgml = 1
+
+
+# $trace specifies the interval between trace entries in Mb.
+# If this is not set no trace entries will be generated.
+set trace = 10
+
+
+# $weight_bits specifies the number of bits of precision bo be given to the 
+# approximate weights.
+set weight_bits = 6
+
+
+# $mcd specifies the commandline arguments for the mg_compression_dict program
+set mcd = -C
+
+
+# Source the parameter file to modify parameters of the build.
+if ($?source) then
+  source ${source}
+endif
+
+
+# [RPAP - Jan 97: Stem Index Change]
+# If do_indexes == 1 then set stem_method = 0
+if ("$do_indexes" == "1") then
+  set stem_method = 0
+endif
+
+
+# Generate the collection name.
+set coll_name = ${text}
+if ("$invf_level" == "3") then
+  set coll_name = ${text}-p
+endif
+
+# Generate the directory for the collection.
+if (-e $MGDATA/${coll_name}) then
+else
+  mkdir $MGDATA/${coll_name}
+endif
+
+# Generate the base name for the collection.
+set bname = ${coll_name}/${coll_name}
+
+# ************ set up pass parameters ************
+
+if ($do_pass1) then
+  set pass1_text = (-f ${bname} -T1)
+endif
+
+if ($do_pass2) then
+  set pass2_text = (-f ${bname} -T2)
+endif
+
+if ($do_pass3) then
+  set pass3_invf = (-f ${bname} -${invf_level} -m ${invf_mem} -s ${stem_method})
+  set pass3_invf = (${pass3_invf} -N1)
+endif
+
+if ($do_pass4) then
+  set pass4_invf = (-f ${bname} -${invf_level} -N2)
+endif
+
+if ($strip_sgml) then
+  set pass1_text = (${pass1_text} -G)
+  set pass2_text = (${pass2_text} -G)
+  set pass3_invf = (${pass3_invf} -G)
+  set pass4_invf = (${pass4_invf} -G)
+endif
+
+if ($?trace) then
+  set pass1_text = (${pass1_text} -t ${trace})
+  set pass2_text = (${pass2_text} -t ${trace})
+  set pass3_invf = (${pass3_invf} -t ${trace})
+  set pass4_invf = (${pass4_invf} -t ${trace})
+endif
+
+if ($?trace_name) then
+  set pass1_text = (${pass1_text} -n ${trace_name})
+  set pass2_text = (${pass2_text} -n ${trace_name})
+  set pass3_invf = (${pass3_invf} -n ${trace_name})
+  set pass4_invf = (${pass4_invf} -n ${trace_name})
+endif
+
+if ($buf_size) then
+  set pass1_text = (${pass1_text} -b ${buf_size})
+  set pass2_text = (${pass2_text} -b ${buf_size})
+  set pass3_invf = (${pass3_invf} -b ${buf_size})
+  set pass4_invf = (${pass4_invf} -b ${buf_size})
+endif
+  
+if ($?comp_stats) then
+  set pass2_text = (${pass2_text} -C ${comp_stats})
+endif
+
+echo "-----------------------------------"
+echo "`uname -n`, `date`"
+echo "${text} --> ${bname}"
+echo "-----------------------------------"
+
+# ************ init get ************
+
+if ($pipe) then
+  if ("$complex" != "") then
+    echo "$get $text -init"
+    $get $text -init
+    if ("$status" != "0") exit 1 
+    echo "-----------------------------------"
+  endif  
+endif
+
+# ************************************* T E X T **********************************
+
+# ************ pass 1_text ************
+
+if (${do_pass1}) then
+  if ($pipe) then
+    if ($?pass1filter) then
+      echo "$get $text $complex | $pass1filter | mg_passes ${pass1_text}"
+      $get $text $complex| $pass1filter | $bindir/mg_passes ${pass1_text}
+      if ("$status" != "0") exit 1 
+    else
+      echo "$get $text $complex | mg_passes ${pass1_text}"
+      $get $text $complex| $bindir/mg_passes ${pass1_text}
+      if ("$status" != "0") exit 1 
+    endif
+  else
+    echo mg_passes ${pass1_text} ${input_files}
+    $bindir/mg_passes ${pass1_text} ${input_files}
+    if ("$status" != "0") exit 1 
+  endif
+  echo "-----------------------------------"
+endif
+
+# ************ compression dict  ************
+if ($do_pass2) then 
+  echo "mg_compression_dict -f ${bname} ${mcd}"
+  $bindir/mg_compression_dict -f ${bname} ${mcd}
+  if ("$status" != "0") exit 1 
+  echo "-----------------------------------"
+endif
+
+# ************ pass 2_text ************
+if (${do_pass2}) then
+  if ($pipe) then
+    if ($?pass2filter) then
+      echo "$get $text $complex | $pass2filter | mg_passes ${pass2_text}"
+      $get $text $complex| $pass2filter | $bindir/mg_passes ${pass2_text}
+      if ("$status" != "0") exit 1 
+    else
+      echo "$get $text $complex | mg_passes ${pass2_text}"
+      $get $text $complex| $bindir/mg_passes ${pass2_text}
+      if ("$status" != "0") exit 1 
+    endif
+  else
+    echo mg_passes ${pass2_text} ${input_files}
+    $bindir/mg_passes ${pass2_text} ${input_files}
+    if ("$status" != "0") exit 1 
+  endif
+  echo "-----------------------------------"
+endif
+
+# ************************************* I N V F **********************************
+
+# ************ pass 3_invf ************
+if (${do_pass3}) then
+  if ($pipe) then
+    if ($?pass3filter) then
+      echo "$get $text $complex | $pass3filter | mg_passes ${pass3_invf}"
+      $get $text $complex| $pass3filter | $bindir/mg_passes ${pass3_invf}
+      if ("$status" != "0") exit 1 
+    else
+      echo "$get $text $complex | mg_passes ${pass3_invf}"
+      $get $text $complex| $bindir/mg_passes ${pass3_invf}
+      if ("$status" != "0") exit 1 
+    endif
+  else
+    echo mg_passes ${pass3_invf} ${input_files}
+    $bindir/mg_passes ${pass3_invf} ${input_files}
+    if ("$status" != "0") exit 1 
+  endif
+  echo "-----------------------------------"
+endif
+
+# ************ perfect hash  ************
+if ($do_pass4) then
+  echo "mg_perf_hash_build -f ${bname}"
+  $bindir/mg_perf_hash_build -f ${bname}
+  if ("$status" != "0") exit 1 
+
+  echo "-----------------------------------"
+endif
+
+# ************ pass 4_invf ************
+if (${do_pass4}) then
+  if ($pipe) then
+    if ($?pass4filter) then
+      echo "$get $text $complex | $pass4filter | mg_passes ${pass4_invf}"
+      $get $text $complex| $pass4filter | $bindir/mg_passes ${pass4_invf}
+      if ("$status" != "0") exit 1 
+    else
+      echo "$get $text $complex | mg_passes ${pass4_invf}"
+      $get $text $complex| $bindir/mg_passes ${pass4_invf}
+      if ("$status" != "0") exit 1 
+    endif
+  else
+    echo mg_passes ${pass4_invf} ${input_files}
+    $bindir/mg_passes ${pass4_invf} ${input_files}
+    if ("$status" != "0") exit 1 
+  endif
+  echo "-----------------------------------"
+endif
+
+
+# ************ build invf dictionary ************
+
+if ($do_pass4) then
+  echo "mg_invf_dict -f ${bname} -b 4096"
+  $bindir/mg_invf_dict -f ${bname} -b 4096
+  if ("$status" != "0") exit 1 
+  echo "-----------------------------------"
+endif
+
+# ******** build indexes to stem dict *********
+
+# [RPAP - Jan 97: Stem Index Change]
+if ($do_pass4 && "$do_indexes" == "1") then
+  echo "mg_stem_idx -f ${bname} -b 4096 -s1"
+  $bindir/mg_stem_idx -f ${bname} -b 4096 -s1
+  if ("$status" != "0") exit 1 
+
+  echo ""
+
+  echo "mg_stem_idx -f ${bname} -b 4096 -s2"
+  $bindir/mg_stem_idx -f ${bname} -b 4096 -s2
+  if ("$status" != "0") exit 1 
+
+  echo ""
+
+  echo "mg_stem_idx -f ${bname} -b 4096 -s3"
+  $bindir/mg_stem_idx -f ${bname} -b 4096 -s3
+  if ("$status" != "0") exit 1 
+
+  echo "-----------------------------------"
+endif
+
+# ************ build weights ************
+
+if ($do_pass4 && $do_weights) then
+  echo "mg_weights_build -f ${bname} -b ${weight_bits} "
+  $bindir/mg_weights_build -f ${bname} -b ${weight_bits}
+  if ("$status" != "0") exit 1 
+  echo "-----------------------------------"
+endif
+
+# *******************************************************************************
+
+
+# ************ print out statistics ************
+if ($do_pass1 && $do_pass2 && $do_pass3 && $do_pass4) then
+  echo "mgstat -f ${bname} -E"
+  $bindir/mgstat -f ${bname} -E
+  if ("$status" != "0") exit 1 
+endif
+
+
+# ************ cleanup get ************
+
+if ($pipe) then
+  if ("$complex" != "") then
+    echo "-----------------------------------"
+    echo "$get $text -cleanup"
+    $get $text -cleanup
+    if ("$status" != "0") exit 1 
+  endif
+endif
+
+echo "-----------------------------------"
+echo "`uname -n`, `date`"
+echo "-----------------------------------"
+
+if ($do_pass2) then
+  echo "-- The fast-loading compression dictionary has not been built."
+  echo "-- If you wish to build it, execute the following command:"
+  echo "-- "$bindir/mg_fast_comp_dict -f ${bname}
+
+  echo "-----------------------------------"
+endif
+
+echo ""
+
Index: /indexers/branches/3.03a/mg/src/scripts/mgmerge.1
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/mgmerge.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/mgmerge.1	(revision 14757)
@@ -0,0 +1,175 @@
+`.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgmerge 1 \*(Dt CITRI
+.SH NAME
+mgmerge \- update an mg system database with new documents
+.SH SYNOPSIS
+.B mgmerge
+[
+.B \-c
+]
+[
+.BI \-g " get"
+]
+[
+.BI \-s " source"
+]
+[
+.B \-S
+]
+[
+.B \-w
+]
+.I collection-name
+.SH DESCRIPTION
+.B mgmerge
+is a
+.B csh
+script that executes all the appropriate programs in the correct order
+to completely merge a current
+.BR mg (1)
+system database ready with some new documents, saving the need for a complete
+database rebuild with
+.B mgbuild.
+It does this by building a second
+.BR mg (1)
+system database from the new documents and then merging this database
+with the old one.
+This program makes use of the
+.BR mg_get_merge (1)
+script to obtain the text of the collection.
+.B mgmerge
+cannot edit or delete documents already in a database; only new documents
+can be added.
+.SH OPTIONS
+Options can occur in any order, but the collection name must be last.
+.TP "\w'\fIcollection-name\fP'u+2n"
+.BI \-c
+This specifies whether the
+.I get
+program is \*(lqcomplex\*(rq.  If a
+.I get
+program is \*(lqcomplex\*(rq, then it requires initialisation and
+cleanup with the
+.B \-i
+and
+.B \-c
+options.
+.TP
+.BI \-g " get"
+This specifies the program to use for getting the source text for the
+build.  If no
+.B \-g
+option is given, the default program
+.BR mg_get_merge (1)
+is used.
+.TP
+.BI \-s " source"
+The
+.B mgmerge
+program consists of two parts.  The first part initializes variables
+to default values.  The second part uses these variables to control
+how the
+.BR mg (1)
+database is built.  This option specifies a program to execute between
+the first and second parts.  The details of what the variables are, and
+how they may be changed, are in comments in the
+.B mgmerge
+program.
+If this option is used, the program should ideally be the same one that
+was called by
+.BR mgbuild (1)
+to build the database since some parameters need to be consistent between
+.B mgbuild
+and
+.B mgmerge.
+.TP
+.B \-S
+This option will cause a slow merge to be performed on the inverted files,
+where each inverted file entry is decoded and recoded.
+The default is a fast merge. Accumulated fast merges slowly degrade
+compression performance on the resulting inverted file so
+a periodic slow merge is recommended.
+.TP
+.B \-w
+Adding new documents can have an effect on the weight of the previous ones.
+By default the weights for documents already in the collection are not 
+recomputed since the change in their values is usually small.
+This option forces new weights to be recomputed.
+Periodic use of this option, as for the "-S" option, is recomended,
+otherwise query rankings may become inaccurate.
+.TP
+.I collection-name
+This is the collection name, as required by the
+.BR mg_get_merge (1)
+program.  It serves both as a
+.I case
+statement selector, and as the name of a subdirectory that holds the
+indexing files.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+Note that a temporary directory under the
+.B MGDATA
+directory is used to perform the merge.
+The default name for this directory is
+.BR MERGE .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.dict
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict.blocked
+The `on-disk' stemmed dictionary.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.B *.text
+Compressed documents.
+.TP
+.B *.text.stats
+Text statistics.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.text.idx.wgt
+Interleaved index into the compressed documents and document weights.
+.TP
+.B *.weight.approx
+Approximate document weights.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mgbuild (1),
+.BR mg_get_merge (1),
+.BR mg_get (1),
+.BR mg_invf_merge (1),
+.BR mg_text_merge (1),
+.BR mg_query (1),
+.BR mg_weights_build (1).
Index: /indexers/branches/3.03a/mg/src/scripts/mgmerge.sh
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/mgmerge.sh	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/mgmerge.sh	(revision 14757)
@@ -0,0 +1,417 @@
+#!/bin/csh -f
+###########################################################################
+#
+# mgmerge.sh -- Script used to build mg text collection.
+# Copyright (C) 1994  Neil Sharman, Shane Hudson (mods. for merging)
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+###########################################################################
+
+set complex = ""
+set slow_merge = ""
+set guess_weights = "-w "
+# [RPAP - Feb 97: Level 3 Merge]
+set text_pass = 1
+
+# Parse the command line arguments
+while ($#argv >= 1)
+  if ("$1" == "-s") then
+    shift
+    if ($#argv >= 1) then
+      set source = $1
+      shift
+    endif
+  else if ("$1" == "-g") then
+    shift
+    if ($#argv >= 1) then
+      set get = $1
+      shift
+    endif
+  else if ("$1" == "-c") then
+    set complex = "-text"
+    shift
+  else if ("$1" == "-S") then
+# set slow merge option in mg_invf_merge
+    set slow_merge = "-s "
+    shift
+  else if ("$1" == "-w") then
+# turn weights guessing off (rebuild weights file from scratch)
+    set guess_weights = ""
+    shift
+
+# [RPAP - Feb 97: Level 3 Merge]
+  else if ("$1" == "-T") then
+# turn text pass off
+    set text_pass = 0
+    shift
+
+  else
+    if ($?text == "0") then
+      set text = $1
+    endif
+    shift
+  endif
+    
+end
+
+if ($?text == "0") then
+  set prog = $0
+  echo "USAGE:"
+  echo "     "$prog:t" [-s config-script] [-g get-program] [-c] source"
+  echo ""
+  echo " The config-script is only needed if a non-standard build is required."
+  echo " The get-program defaults to mg_get if not specified."
+  exit 1	
+endif
+
+set bindir = $0
+set bindir = $bindir:h
+
+# if $pipe == 1 then pipe in the source text using $get and $text otherwise
+# read the source text directly from the file names specified in $input_files
+set pipe = 1
+
+if ($?get == "0") then
+  set complex = "-text"
+  set get = $bindir/mg_get_merge
+endif
+
+if (-e $MGDATA/${text}.chunks) then
+  set input_files = `cat $MGDATA/${text}.chunks`
+endif
+
+# Set the inversion method this may be either "I" or "N"
+# N is memory-efficient, I is faster for small collections
+set invf_method = N
+
+
+# Set the stemming method
+#   Bit 0 = case folding
+#   Bit 1 = S stemmer
+set stem_method = 3
+
+
+# [RPAP - Jan 97: Stem Index Change]
+# If do_indexes == 1 then build collection with full indexes to blocked file
+# overriding stem_method (stem_method will be set to 0)
+# Otherwise don't build with indexes
+set do_indexes = 0
+
+
+# $invf_mem specifies the amount of memory to use for the pass2 inversion
+# This only has an effect if $invf_method is "N".
+set invf_mem = 32
+
+
+# $num_chunks specifies the number of interium chunks of inverted file that
+# may be written to disc before a merge into the invf file is done
+# This only has an effect if $invf_method is "N".
+set num_chunks = 3
+
+# $invf_level specifies the level of the inverted file that will be generated.
+# Note: The value *MUST* be the same as was used to build the collection
+# that is being merged.
+# In the current mg_invf_merge implementation the maximum level is 2. 
+# Paragraph-level inversion (invf_level = 3) is NOT supported.
+set invf_level = 2
+
+
+# If $strip_sgml == 1 then sgml tags are stripped from the inversion phase.
+# Otherwise sgml tags are kepted.
+set strip_sgml = 1
+
+
+# $trace specifies the interval between trace entries in Mb.
+# If this is not set no trace entries will be generated.
+set trace = 10
+
+
+# $weight_bits specifies the number of bits of precision bo be given to the 
+# approximate weights.
+set weight_bits = 6
+
+
+# $mcd specifies the commandline arguments for the mg_compression_dict program
+set mcd = -S
+
+# $merge_name is the name of the subdirectory under ${MGDATA} where
+# the mergeing steps will be performed. There should NOT be an mg
+# collection with this name! The default is "MERGE"
+set merge = "MERGE"
+
+# Source the parameter file to modify parameters of the build.
+if ($?source) then
+  source ${source}
+endif
+
+
+# [RPAP - Jan 97: Stem Index Change]
+# If do_indexes == 1 then set stem_method = 0
+if ($do_indexes) then
+  set stem_method = 0
+endif
+
+
+# Generate the collection name.
+set coll_name = ${text}
+
+# Generate the directory where merging will take place
+if (-e $MGDATA/${merge}) then
+else
+  mkdir $MGDATA/${merge}
+endif
+
+# Generate the base name for the collection.
+# [RPAP - Feb 97: Level 3 Merge]
+set bname = ${coll_name}
+
+# generate the old, new and merge names in the $merge directory
+set oldname = ${merge}/${coll_name}.old
+set newname = ${merge}/${coll_name}.new
+set mergename = ${merge}/${coll_name}
+
+# build up the command lines for pass 1 and 2 to build a
+# dummy collection for the new documents
+set pass1 = (-f ${newname} -${invf_level} -m ${invf_mem} -s ${stem_method})
+set pass2 = (-f ${newname} -${invf_level} -c ${num_chunks})
+
+if ($strip_sgml) then
+  set pass1 = (${pass1} -G)
+  set pass2 = (${pass2} -G)
+endif
+
+if ($?trace) then
+  set pass1 = (${pass1} -t ${trace})
+  set pass2 = (${pass2} -t ${trace})
+endif
+
+# Note that a -T1 pass isnt done since the old .text.stats file is used
+# as the compression model for compressing the new documents.
+
+# [RPAP - Feb 97: Level 3 Merge]
+# Do not perform -T2 pass if text_pass == 0
+if ($text_pass) then
+  set pass2 = (${pass2} -T2)
+endif
+
+set pass1 = (${pass1} -${invf_method}1)
+set pass2 = (${pass2} -${invf_method}2)
+
+
+if ($?trace_name) then
+  set pass1 = (${pass1} -n ${trace_name})
+  set pass2 = (${pass2} -n ${trace_name})
+endif
+  
+if ($?comp_stats) then
+  set pass2 = (${pass2} -C ${comp_stats})
+endif
+
+########################################################################
+# Here is where mgmerge goes to work.
+
+echo "--------------------------------------------------------------"
+echo "`uname -n`, `date`"
+echo "MGMERGE collection: ${bname}"
+echo "--------------------------------------------------------------"
+echo "FIRST PHASE: build new collection from new documents"
+echo "--------------------------------------------------------------"
+
+# move and rename the text dictionary file
+# [RPAP - Feb 97: Level 3 Merge] - only if performing text pass
+if ($text_pass) then
+  mv $MGDATA/${bname}.text.dict $MGDATA/${newname}.text.dict
+endif
+
+if ($pipe) then
+  if ("$complex" != "") then
+    echo ">> $get $text -init"
+    $get $text -init
+    if ("$status" != "0") exit 1 
+    echo "-----------------------------------"
+  endif  
+endif
+
+if ($pipe) then
+  if ($?pass1filter) then
+    echo ">> $get $text $complex | $pass1filter | mg_passes ${pass1}"
+    $get $text $complex| $pass1filter | $bindir/mg_passes ${pass1}
+    if ("$status" != "0") exit 1 
+  else
+    echo ">> $get $text $complex | mg_passes ${pass1}"
+    $get $text $complex| $bindir/mg_passes ${pass1}
+    if ("$status" != "0") exit 1 
+  endif
+else
+  echo ">> mg_passes ${pass1} ${input_files}"
+  $bindir/mg_passes ${pass1} ${input_files}
+  if ("$status" != "0") exit 1 
+endif
+echo "-----------------------------------"
+
+echo "mg_perf_hash_build -f ${newname}"
+$bindir/mg_perf_hash_build -f ${newname}
+if ("$status" != "0") exit 1 
+echo "-----------------------------------"
+
+if ($pipe) then
+  if ($?pass2filter) then
+    echo ">> $get $text $complex | $pass2filter | mg_passes ${pass2}"
+    $get $text $complex | $pass2filter | $bindir/mg_passes ${pass2}
+    if ("$status" != "0") exit 1 
+  else
+    echo ">> $get $text $complex | mg_passes ${pass2}"
+    $get $text $complex | $bindir/mg_passes ${pass2}
+    if ("$status" != "0") exit 1 
+  endif
+else
+  echo ">> mg_passes ${pass2} ${input_files}"
+  $bindir/mg_passes ${pass2} ${input_files}
+  if ("$status" != "0") exit 1 
+endif
+echo "-----------------------------------"
+
+if ($pipe) then
+  if ("$complex" != "") then
+    echo "-----------------------------------"
+    echo ">> $get $text -cleanup"
+    $get $text -cleanup
+    if ("$status" != "0") exit 1 
+  endif
+endif
+
+echo "---------------------------------------"
+date
+echo "--------------------------------------------------------------"
+echo "SECOND PHASE: merge the two collections"
+echo "--------------------------------------------------------------"
+
+# move the appropriate files from the base directory to the merge dir
+echo "(moving files....)"
+# [RPAP - Feb 97: Level 3 Merge]
+# Move files if doing text pass
+if ($text_pass) then
+  mv $MGDATA/${bname}.text       $MGDATA/${oldname}.text
+  mv $MGDATA/${bname}.text.idx   $MGDATA/${oldname}.text.idx
+else
+# Need this file if building weights
+  cp -d $MGDATA/${bname}.text.idx   $MGDATA/${mergename}.text.idx
+endif
+mv $MGDATA/${bname}.invf       $MGDATA/${oldname}.invf
+mv $MGDATA/${bname}.invf.idx   $MGDATA/${oldname}.invf.idx
+mv $MGDATA/${bname}.invf.dict  $MGDATA/${oldname}.invf.dict
+# the old weight file may be used for the new file
+mv $MGDATA/${bname}.weight     $MGDATA/${mergename}.weight
+# EOC: the old invf.paragraph file may be used for the new file for Level 3 Invf
+if (-e $MGDATA/${bname}.invf.paragraph) then
+  mv $MGDATA/${bname}.invf.paragraph  $MGDATA/${mergename}.invf.paragraph
+endif
+echo "---------------------------------------"
+
+# [RPAP - Feb 97: Level 3 Merge]
+# Only merge text if doing text pass
+if ($text_pass) then
+  echo ">> mg_text_merge -f ${mergename}"
+  $bindir/mg_text_merge -f $mergename
+  echo "---------------------------------------"
+endif
+
+echo ">> mg_invf_merge ${slow_merge}${guess_weights} -f ${mergename}"
+$bindir/mg_invf_merge ${slow_merge}${guess_weights} -f ${mergename}
+echo "---------------------------------------"
+
+#remove .weight file, so a new one will be created by mg_weights_build
+if ("$guess_weights" == "") then
+  echo "rm ${mergename}.weight"
+  rm $MGDATA/${mergename}.weight
+endif
+
+# mv $MGDATA/${mergename}.weight $MGDATA/${mergename}.w2
+
+echo ">> mg_weights_build -f ${mergename} -b ${weight_bits}"
+$bindir/mg_weights_build -f ${mergename} -b ${weight_bits}
+if ("$status" != "0") exit 1 
+
+echo "---------------------------------------"
+
+echo ">> mg_invf_dict -f ${mergename} -b 4096"
+$bindir/mg_invf_dict -f ${mergename} -b 4096
+
+# [RPAP - Jan 97: Stem Index Change]
+if ($do_indexes) then
+  echo "-----------------------------------"
+
+  echo "mg_stem_idx -f ${mergename} -b 4096 -s1"
+  $bindir/mg_stem_idx -f ${mergename} -b 4096 -s1
+  if ("$status" != "0") exit 1 
+
+  echo ""
+
+  echo "mg_stem_idx -f ${mergename} -b 4096 -s2"
+  $bindir/mg_stem_idx -f ${mergename} -b 4096 -s2
+  if ("$status" != "0") exit 1 
+
+  echo ""
+
+  echo "mg_stem_idx -f ${mergename} -b 4096 -s3"
+  $bindir/mg_stem_idx -f ${mergename} -b 4096 -s3
+  if ("$status" != "0") exit 1 
+endif
+
+echo "--------------------------------------------------------------"
+
+# move files back to base dir
+# [RPAP - Feb 97: Level 3 Merge]
+# mv the text files if doing text pass
+if ($text_pass) then
+  mv $MGDATA/${oldname}.text         $MGDATA/${bname}.text
+  mv $MGDATA/${mergename}.text.idx   $MGDATA/${bname}.text.idx
+  mv $MGDATA/${newname}.text.dict    $MGDATA/${bname}.text.dict
+endif
+mv $MGDATA/${mergename}.invf       $MGDATA/${bname}.invf
+mv $MGDATA/${mergename}.invf.idx   $MGDATA/${bname}.invf.idx
+mv $MGDATA/${mergename}.invf.dict  $MGDATA/${bname}.invf.dict
+mv $MGDATA/${mergename}.invf.dict.blocked  $MGDATA/${bname}.invf.dict.blocked
+
+# [RPAP - Jan 97: Stem Index Change]
+if ($do_indexes) then
+  mv $MGDATA/${mergename}.invf.dict.blocked.1 $MGDATA/${bname}.invf.dict.blocked.1
+  mv $MGDATA/${mergename}.invf.dict.blocked.2 $MGDATA/${bname}.invf.dict.blocked.2
+  mv $MGDATA/${mergename}.invf.dict.blocked.3 $MGDATA/${bname}.invf.dict.blocked.3
+endif
+
+mv $MGDATA/${mergename}.weight     $MGDATA/${bname}.weight
+mv $MGDATA/${mergename}.weight.approx $MGDATA/${bname}.weight.approx
+mv $MGDATA/${mergename}.text.idx.wgt $MGDATA/${bname}.text.idx.wgt
+
+# EOC: mv .invf.paragraph file if exists
+if (-e $MGDATA/${mergename}.invf.paragraph) then
+  mv $MGDATA/${mergename}.invf.paragraph   $MGDATA/${bname}.invf.paragraph
+endif
+
+# remove old files in the MERGE directory
+rm -f $MGDATA/${merge}/*
+
+echo "mgstat -f ${bname} -E"
+$bindir/mgstat -f ${bname} -E
+if ("$status" != "0") exit 1 
+
+echo "--------------------------------------------------------------"
+echo "`uname -n`, `date`"
+echo "--------------------------------------------------------------"
+
+echo ""
Index: /indexers/branches/3.03a/mg/src/scripts/xmg.1
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/xmg.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/xmg.1	(revision 14757)
@@ -0,0 +1,130 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH xmg 1 \*(Dt CITRI
+.SH NAME
+xmg \- An X interface to mgquery
+.SH SYNOPSIS
+.B xmg
+[
+.I collection-name
+]
+.SH DESCRIPTION
+.B xmg
+is an X interface to the
+.BR mg (1)
+information retrieval system.
+.PP
+Type a query in the ``Query'' box.  The escape key clears the query text.
+.PP
+The first line or so of each matching document is listed.
+.PP
+Click on any line to show the complete document.
+.PP
+Shift-click to show the document in a new window.
+.PP
+Press
+.I Next
+and
+.I Previous
+to cycle through the list of documents (shift works here too).
+.PP
+If you change the query, existing windows continue to refer to the
+original query.
+.PP
+You can select either Boolean or ranked queries:
+.RS
+.TP "\w'\fIBoolean queries:\fP'u+2n"
+.I "Boolean queries:"
+use ``&'' for AND, ``|'' for OR, ``!'' for NOT, and parentheses for
+grouping.
+.TP
+.I "Ranked queries:"
+Documents are listed in order of relevance.  A weight is shown
+alongside each.  Weights are normalized to 100 for the most relevant
+document.  Choose
+.I "Approximate Ranking"
+for greater retrieval speed.
+.RE
+.PP
+In document windows (other than the main window):
+.RS
+.br
+Typing `n' = next document;
+.br
+Typing `N' = next document in new window;
+.br
+Typing `p' = previous document;
+.br
+Typing `P' = previous document in new window;
+.br
+Typing `q' = close window.
+.RE
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.TP
+.SB Xdefaults
+To override the default font options, use RESOURCE_MANAGER properties
+like the following in your
+.I .Xdefaults
+file:
+.IP
+.RS
+.nf
+.I "xmg.textfont: fixed"
+.I "xmg.buttonfont: fixed"
+.fi
+.RE
+.IP
+To override the default query type of ranked, use
+.IP
+.RS
+.I "xmg.querytype: boolean"
+.RE
+.IP
+To override the default collection name (the first one listed by
+.BR ls (1)
+from your MGDATA environment variable), use
+.IP
+.RS
+.I "xmg.collection: mail93"
+.RE
+.SH "SEE ALSO"
+.na
+.BR ls (1),
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/scripts/xmg.sh
===================================================================
--- /indexers/branches/3.03a/mg/src/scripts/xmg.sh	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/scripts/xmg.sh	(revision 14757)
@@ -0,0 +1,1376 @@
+#!/usr/local/bin/wish -f
+# Edit the line above to point to your version of wish
+#
+###############################################################################
+#
+# xmg -- X interface to the mg information retrieval system
+# Copyright (C) 1994  Bruce McKenzie, Ian Witten and Craig Nevill-Manning
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#       @(#)xmg.sh	1.4 25 Mar 1994
+#
+###############################################################################
+#
+# "xmg" is an X interface to the mg information retrieval system.
+#
+# Type a query in the "Query" box.
+# The first line or so of each matching document is listed.
+# Click on any line to show the complete document.
+# Shift-click to show the document in a new window.
+# Press Next and Previous to cycle through the list of documents (Shift works
+#   here too). 
+# If you change the query, existing windows continue to refer to the original
+#   query. 
+# 
+# You can select either Boolean or Ranked queries.
+# Boolean queries: use "&" for AND, "|" for OR, "!" for NOT, and parentheses
+# for grouping 
+# Ranked queries:  - documents are listed in order of relevance; a weight is
+# 		     shown alongside each 
+#                  - weights are normalized to 100 for the most relevant
+#		     document 
+#                  - choose Approximate Ranking for greater retrieval speed. 
+# 
+# In document windows (other than the main window): 
+#		Typing 'n' = next document
+#		Typing 'N' = next document in new window
+#		Typing 'p' = previous document
+#		Typing 'P' = previous document in new window
+#		Typing 'q' = close window
+#
+###############################################################################
+
+# Date: 13 March 1994
+# Authors: Bruce McKenzie, Ian Witten and Craig Nevill-Manning
+
+###############################################################################
+# Customizing xmg
+###############################################################################
+
+# To override the default font options, use RESOURCE_MANAGER properties like
+# the following in your .Xdefaults file
+#
+#	xmg.textfont: fixed
+#	xmg.buttonfont: fixed
+#
+# To override the default query type of ranked, use
+#
+#	xmg.querytype: boolean
+#
+# To override the default collection name (the first one listed by /bin/ls from
+# your MGDATA environment variable), use
+#
+#	xmg.collection: mail93
+
+###############################################################################
+# Global variables
+###############################################################################
+
+#   genuine constants:
+#
+#	env		the environment variables
+#	Terminator	terminator for mgquery
+#	MaxWindowHeight	the maximum height permitted for a document window
+#	ListBoxLength	the number of items in the document list
+#	HeadLength	the length document head displayed in the list box
+#	ImageString	the string at the start of a document associated
+#			with an image
+#
+#   things that rarely get changed:
+#
+#	querytype	the current query type (boolean, ranked, approx-ranked)
+#	booleanquery	says whether the query is boolean or ranked
+#	approxquery	says whether ranking is to be approximate or not
+#	collection	the name of the document collection being used
+#	fileId		file identifer for a pipe to the mgquery process
+#       errorOccurred	flag to say that there has been an I/O error on the
+#			current collection
+#
+#   things that reflect items in the main panel
+#
+#	query		the current query
+#	hits		number of hits for the current query
+#	display		shell command to display the image associated with
+#			the last document retrieved
+#	scrolledto	document prefixes have been obtained for all documents
+#			up to this position in the document list
+#
+#   static variable needed in just one procedure
+#
+#	top_rank	weight associated with the first document retrieved
+#	windowname	unique id for each document window
+
+###############################################################################
+# High-level procedures
+###############################################################################
+
+proc SaveDocument {w} {
+  set file [FSBox "Save document to file:"]
+
+  if {$file != ""} {
+    if [file exists $file] {
+      toplevel .r
+      wm title .r "\n"
+      .r configure -borderwidth 2 -relief raised 
+      focus .r
+      label .r.message -text "The file already exists"
+      button .r.replace -text "Replace" -width 10 -height 2 \
+          -command "destroy .r; WriteDocument $file \"w\" $w" 
+      button .r.append -text "Append" -width 10 -height 2 \
+          -command "destroy .r; WriteDocument $file \"a\" $w"
+      button .r.cancel -text "Cancel" -command {destroy .r} -width 10 -height 2
+      pack .r.message -side top -pady 10 -padx 20
+      pack .r.replace .r.append .r.cancel -side left -pady 10 -padx 20
+
+    } else {
+       WriteDocument $file "w" $w
+    }
+  }
+}
+
+proc Dialog {text command} {
+      if {![winfo exists .r] } { toplevel .r }
+      wm title .r "\n"
+      .r configure -borderwidth 2 -relief raised 
+      focus .r
+      label .r.message -text $text
+      button .r.ok -text "OK" -width 10 -height 2 \
+          -command "destroy .r $command"
+      pack .r.message -side top -pady 10 -padx 20
+      pack .r.ok -side bottom -pady 10 -padx 20
+}
+
+proc WriteDocument {file mode w} {
+    if {[catch {set f [open $file $mode]}] == 0} {
+        if [winfo exists $w] {
+            puts $f [$w get 0.0 end]
+        } else {
+            Dialog "Unable to save text" ""
+        }
+        flush $f
+        close $f
+    } else {
+        Dialog "Unable to open file for writing" "; SaveDocument $w"
+    }
+}
+
+# Send a query to mg and enter the response in the document list
+#
+proc sendQuery {window} {
+    global query hits querytype errorOccurred scrolledto
+
+    .m.t.q.retrieved.label configure -foreground Gray
+    .m.t.q.retrieved.hits configure -foreground Gray
+
+    sendto ".set query \"$querytype\""
+    sendto ".set mode \"docnums\""
+    foreach f "sdocnums sdocs srank" { $window.$f delete 0 end }
+    disableButton .m.d.buttons.previous
+    disableButton .m.d.buttons.next
+    if {[string index $query 0] == "." || [string length $query] > 255} {
+        set doclist ""
+    } else { set doclist [sendandget $query] }
+
+    if {$errorOccurred} {
+        enterText .m.d.text [mgqueryFailure]
+        .m.t.q.retrieved.label configure -foreground Black
+        .m.t.q.retrieved.hits configure -foreground Black 
+        update
+        return
+    }
+    sendto ".set query \"DocNums\""
+    sendto ".set mode  \"text\""
+    .m.t.q.retrieved.label configure -foreground Black
+    .m.t.q.retrieved.hits configure -foreground Black 
+    set hits [llength $doclist]
+    set i 0
+    global top_rank
+
+    scan [lindex $doclist 0] "%d %f %d" d rank size
+    set top_rank $rank
+    if {$top_rank == 0} {set top_rank 1}
+
+    while {$i < $hits} {
+	scan [lindex $doclist $i] "%d %f %d" d rank size
+        if {$rank == "Inf"} {set rank 1}
+	if {$querytype == "boolean"} {
+	    $window.srank insert end ""
+	} else {
+	    $window.srank insert end \
+		[format "%3.0f" [expr $rank / $top_rank * 99 + 1]]
+	}
+	$window.sdocnums insert end [format " %d" $d]
+	incr i
+    }
+
+    set scrolledto 0
+    scroll $window 0
+    bind $window.sdocs <ButtonRelease-1> \
+	"showDocument $window.sdocs %y .m.d \"$doclist\" \"$query\""
+    bind $window.sdocs <Shift-ButtonRelease-1> \
+	"showDocument $window.sdocs %y New \"$doclist\" \"$query\""
+    enterText .m.d.text ""
+}
+
+# Scrolling routine for the document list
+#
+proc scroll {window n} {
+    global hits scrolledto ListBoxLength Terminator fileId ImageString
+
+    $window.sdocnums yview $n
+    $window.sdocs yview $n
+    $window.srank yview $n
+    set last $n
+    if {$last <= 0} {set last 0}
+    incr last $ListBoxLength
+    if {$last > $hits} {set last $hits}
+
+#    .m config -cursor {watch}
+#    update
+    sendto ".set mode \"heads\""
+    sendto ".set terminator \"\""
+    while {$scrolledto < $last} {
+	if {[scan [$window.sdocnums get $scrolledto] "%d" d] == 1} {
+            sendto $d
+            gets $fileId line
+            set i [string first " " $line]
+            if {$i != -1} {set line [string range $line [expr $i + 1] end]}
+            if {[string compare $ImageString [string range $line 0 9]] == 0} {
+                set line [getImageDocumentHead $d]
+            }
+	    $window.sdocs insert $scrolledto $line
+	}
+	incr scrolledto
+    }
+    sendto ".set terminator \"$Terminator\\n\""
+    sendto ".set mode text"
+#   .m config -cursor {}
+}
+
+proc getImageDocumentHead {d} {
+    global HeadLength ImageString fileId
+
+    sendto ".set heads_length 1000"
+    sendto $d
+    gets $fileId line
+
+    set line [string range $line 11 end]
+
+    set s [string first $ImageString $line]
+    if {$s != -1} {
+        incr s 11
+        set line [string range $line $s [expr $s + $HeadLength]]
+    }
+  
+    sendto ".set heads_length $HeadLength"
+
+    return "* $line"
+}
+
+# Show document from the document list
+#
+proc showDocument {window y newWindow doclist query} {
+    showThisDocument [$window nearest $y] $doclist $newWindow $query
+}
+
+proc adjacentDocument {index doclist window q button} {
+    global ListBoxLength
+
+    showThisDocument $index $doclist $window $q
+
+    if {$window == ".m.d"} {
+      set first [.m.t.q.r.sdocs nearest 0]
+      if {$index < $first || $index >= $first + $ListBoxLength} {
+          scroll .m.t.q.r [expr $index - $ListBoxLength / 2]
+      }
+      .m.t.q.r.sdocs select from $index
+    } 
+}
+
+
+# Show document with this index in the document list
+#
+proc showThisDocument {index doclist window q} {
+    global collection MaxWindowHeight display windowname
+
+    set document ""
+    scan [lindex $doclist $index] "%d %f" document rank
+    if {$document == ""} { return }
+    set textlist [sendandget $document]
+	
+    if {[string length $display] != 0} { exec csh -c $display >& /dev/null & }
+	
+# throw away the first line
+    set text [join [lrange $textlist 1 end] "\n"]
+
+# if necessary, create a new window for this document
+    if {$window == "New"} {
+        .m.t.q.r.sdocs select clear
+	set window .m.document$windowname
+        incr windowname
+        set existing ""
+        set raised 0
+        foreach w [lrange [winfo children .m] 2 end] {
+           if {[lindex [$w.docnum configure -text] 4] == $index && \
+               [lindex [$w.query configure -text] 4] == $q} {
+              if {$raised} {
+                 closeDocumentWindow $w
+              } else {
+                  raise $w
+		  getFocus $w
+                  set window $w
+                  set raised 1
+              }
+           }
+        }
+  
+        if {!$raised} {
+   	    toplevel $window
+            $window configure -borderwidth 2 -relief raised
+            wm protocol $window WM_TAKE_FOCUS "getFocus $window"
+	    getFocus $window
+	    makeDocumentPanel $window
+            bind $window q "$window.buttons.close invoke"
+            label $window.docnum -text $index
+            label $window.query -text $q
+       }
+    }
+
+# configure the window for this document
+    set rows [expr [llength $textlist] - 1]
+    if {$window != ".m.d"} {
+	wm title $window "$collection \"$q\""
+	wm iconname $window "$document"
+	$window.text configure -height $rows
+	if {$rows > $MaxWindowHeight} {
+	    $window.text configure -height $MaxWindowHeight
+	}
+    }
+
+# show the document text in the window
+    enterText $window.text $text
+
+# configure the window's Previous and Next buttons
+    if {$index == 0} {
+        disableButton $window.buttons.previous
+    } else {
+	set newindex [expr $index-1]
+	bindBoth $window previous $newindex $doclist $q
+        bind $window p [bind $window.buttons.previous <1>]
+        bind $window P [bind $window.buttons.previous <Shift-1>]
+    }
+    if {$index == [expr [llength $doclist]-1]} {
+	disableButton $window.buttons.next 
+    } else {
+	set newindex [expr $index+1]
+	bindBoth $window next $newindex $doclist $q
+        bind $window n [bind $window.buttons.next <1>]
+        bind $window N [bind $window.buttons.next <Shift-1>]
+    }
+
+    if {$window != ".m.d"} { $window.docnum configure -text $index }
+
+    if {[string length $display] != 0} { 
+        set on "{
+            if \[winfo exists $window\] \{
+                 $window.buttons.image configure \
+                   -foreground Black
+                 update\}
+        }"
+        set off "{
+            if \[winfo exists $window\] \{
+                 $window.buttons.image configure \
+                   -foreground [lindex [.m.d configure -background] 4]
+                 update\}
+        }"
+        set t 0
+        while {$t < 5} {
+            after [expr $t * 1000] eval $on
+            after [expr $t * 1000 + 500] eval $off
+            incr t
+        }   
+    }
+}
+
+# Bind both Button-1 and Shift-Button-1 commands
+#
+proc bindBoth {window button index doclist query} {
+    $window.buttons.$button configure -state normal
+    bind $window.buttons.$button <Button-1> \
+	"adjacentDocument $index \"$doclist\" $window \"$query\" $button"
+    bind $window.buttons.$button <Shift-Button-1> \
+	"adjacentDocument $index \"$doclist\" New \"$query\" $button"
+}
+
+# Change the type of query
+#
+proc changeQuerytype {name element op} {
+    global querytype booleanquery approxquery
+
+    if {$booleanquery} {
+	.m.t.b.type.approx configure -state disabled
+	.m.t.q.retrieved.weight configure \
+             -foreground [lindex [.m configure -background] 4]
+	set querytype boolean
+    } else {
+	.m.t.b.type.approx configure -state normal
+	.m.t.q.retrieved.weight configure -foreground Black
+	if {$approxquery} {
+	    set querytype "approx-ranked"
+	} else {
+	    set querytype "ranked"
+	}
+    }
+}
+
+proc enterText {window text} {
+    $window configure -state normal
+    $window delete 0.0 end
+    $window insert 0.0 $text
+    $window configure -state disabled
+}
+
+###############################################################################
+# IO and initialization
+###############################################################################
+
+# Send a message to mg and return the reply
+#
+proc sendandget {message} {
+    global fileId Terminator display errorOccurred ImageString
+    set display ""
+
+    .m config -cursor {watch}
+    update idletasks
+    set reply ""
+    sendto "$message\n"
+    if {$message != "" && !$errorOccurred} {
+        gets $fileId line
+    	while {[string compare $Terminator $line] != 0} {
+            lappend reply $line;
+            gets $fileId line
+        }
+
+        if {[string compare $ImageString [lindex $reply 1]] == 0 } {
+          if {[string compare "MGDATA" [string range [lindex $reply 3] 0 5]] == 0} {
+             set display [string range [lindex $reply 3] 7 end];
+          }
+          set reply [lrange $reply 4 end]
+        }
+    }
+
+    .m config -cursor {}
+    return $reply
+}
+    
+# Send a message to mg
+#
+proc sendto {message} {
+    global fileId errorOccurred
+
+    puts $fileId $message
+    set errorOccurred [catch {flush $fileId}]
+}
+
+# Reinitialise mgquery to work with a new document collection
+#
+proc reInitMG {c} {
+    global fileId
+    catch {close $fileId}
+    initMG $c
+}
+
+# Initialize mgquery to work with a specified text collection
+#
+proc initMG {c} {
+    global query hits fileId collection Terminator env errorOccurred
+    global HeadLength
+
+    set collection $c
+    set query ""
+    set hits 0
+    set errorOccurred 0
+
+    foreach f "sdocs srank" { .m.t.q.r.$f delete 0 end }
+    enterText .m.d.text ""
+    .m.t.b.collect.m configure -text $collection
+    foreach w [winfo children .m] {
+	if {[string first ".m.document" $w] == 0} { closeDocumentWindow $w }
+    }
+
+    disableButton .m.d.buttons.previous 
+    disableButton .m.d.buttons.next
+
+    if {$c != ""} {
+        set f $env(MGDATA)/$c
+
+        if {[file exists $f] && [file readable $f]} {
+    	    set fileId [open "| mgquery $collection" RDWR]
+	    sendto ".set expert \"true\""
+	    sendto ".set terminator \"$Terminator\\n\""
+	    sendto ".set pager \"cat\""
+            sendto ".set heads_length $HeadLength"
+	    return
+        }
+    }
+    bind .m.t.q.e.entry <Return> {null}
+    enterText .m.d.text [initializationFailure]
+    update
+}
+
+# Routine to obtain values from RESOURCE_MANAGER
+#
+proc query_resource {option class default} {
+	set val [option get . $option $class]
+	if {[string length $val] == 0} { return $default }
+	return $val
+}
+
+
+proc disableButton {b} {
+    bind $b <Button-1> {null}
+    bind $b <Shift-Button-1> {null}
+    $b configure -state disabled
+}
+
+proc null {} {}
+
+###############################################################################
+# Setting up windows
+###############################################################################
+
+proc removeFromWindowList {window} {
+    global stacking
+
+    set i 0
+    while {$i < [llength $stacking]} {
+      if {$window == [lindex $stacking $i]} {
+         set stacking [lreplace $stacking $i $i]
+      }
+      incr i
+    }
+}
+
+proc getFocus {window} {
+    global stacking
+
+    focus $window
+    removeFromWindowList $window
+    set stacking [linsert $stacking 0 $window]
+}
+
+proc closeDocumentWindow {w} {
+   global stacking
+   removeFromWindowList $w
+   set t [lindex $stacking 0]
+
+   if {$t != ""} {
+     focus $t
+     raise $t
+  }
+  destroy $w
+}
+
+# Make a "document" panel, including Previous, Next, and Close buttons
+#
+proc makeDocumentPanel {window} {
+    frame $window.buttons
+    button $window.buttons.previous -text "Previous" -width 10 -state disabled
+    button $window.buttons.next -text "Next" -width 10 -state disabled
+    button $window.buttons.close -text "Close" -width 10 \
+	-command "closeDocumentWindow $window"
+    button $window.buttons.save -text "Save" -width 10 \
+        -command "SaveDocument $window.text"
+
+    label $window.buttons.image -text "Fetching image..." \
+            -foreground [lindex [$window configure -background] 4]
+    pack $window.buttons.previous $window.buttons.next -side left
+    pack $window.buttons.image -side left -padx 10
+    pack $window.buttons.close $window.buttons.save -side right 
+    pack $window.buttons -side top -fill x 
+
+    text $window.text -borderwidth 2 -relief raised \
+             -setgrid true -width 80 -state disabled
+
+    $window.text configure -yscrollcommand "$window.sy set" 
+    scrollbar $window.sy -relief flat -command "$window.text yview"
+    pack $window.sy -side right -fill y 
+    pack $window.text -side top -expand yes -fill both
+}
+
+# Make the "buttons" panel, with the query type and collection name
+#
+proc mkButtons {window} {
+    global collection booleanquery approxquery env
+    frame $window.type
+    label $window.type.label -text "Query type"
+
+    radiobutton $window.type.boolean -text "Boolean" -variable booleanquery \
+	  -value 1 -relief flat
+
+    radiobutton $window.type.ranked -text "Ranked" -variable booleanquery \
+	  -value 0 -relief flat
+
+    checkbutton $window.type.approx -text "Approximate" -variable approxquery \
+	  -relief flat
+
+    trace variable booleanquery w changeQuerytype
+    trace variable approxquery w changeQuerytype
+
+    pack $window.type.label   -side top -anchor w
+    pack $window.type.boolean -side top -anchor w -padx 12
+    pack $window.type.ranked  -side top -anchor w -padx 12
+    pack $window.type.approx  -side top -anchor w -padx 36
+
+    pack $window.type -side top -anchor w -pady 12
+
+    frame $window.collect
+    label $window.collect.label -text "Collection: "
+    pack $window.collect.label -side left -anchor w
+
+    getViewer
+
+    set dirs [getMGDATA]
+    set collection ""
+    if {$dirs != ""} { set collection [lindex $dirs 0] }
+   
+    menubutton $window.collect.m -menu $window.collect.m.menu \
+	-relief sunken
+    menu $window.collect.m.menu
+    foreach c $dirs {
+        if {[file readable $env(MGDATA)/$c] && 
+            [file isdirectory $env(MGDATA)/$c]} {
+    	    $window.collect.m.menu add command -label $c \
+	        -command "reInitMG $c"
+        }
+    }
+    pack $window.collect.m -side left
+    pack $window.collect -side bottom -anchor w
+
+
+}
+
+# Check that the MGDATA environment variable is set, and is non-null
+#
+proc getMGDATA {} {
+    global env
+
+    set MGDATA 0
+    foreach i [array names env] {
+	if {$i == "MGDATA"} {
+	    set dirs [exec /bin/ls $env(MGDATA)]
+	    if {[info exists dirs]} { return $dirs }
+	}
+    }
+
+    return ""
+}
+
+proc getViewer {} {
+    global env
+
+    set viewer 0
+    foreach i [array names env] {
+	if {$i == "MGIMAGEVIEWER"} {set viewer $env(MGIMAGEVIEWER)}
+    }
+
+    if {$viewer == 0} {set env(MGIMAGEVIEWER) "xloadimage -quiet -fit stdin"}
+}
+
+# Make the "query" panel, with the query and list of retrieved documents
+#
+proc mkQuery {window} {
+    global hits ListBoxLength
+
+# at the top of the "query" panel is the "entry" frame
+    frame $window.e
+    label $window.e.label -text "Query"
+    entry $window.e.entry -relief sunk -width 47 -textvariable query
+    pack $window.e.label -side left
+    pack $window.e.entry -side right -expand yes -fill x
+    focus default $window.e.entry
+    focus $window.e.entry
+
+    bind $window.e.entry <Control-Key> {null}
+    bind $window.e.entry <Return> "sendQuery $window.r"
+    bind $window.e.entry <Escape> { set query "" }
+    bind $window.e.entry <2> {
+	%W insert insert [selection get STRING]
+	tk_entrySeeCaret %W
+    }
+
+# next is the "retrieved" frame
+    frame $window.retrieved
+    label $window.retrieved.weight -text "Weight"
+    label $window.retrieved.label -text "   Documents retrieved: "
+    label $window.retrieved.hits -width 4 -relief sunk -textvariable hits
+    set documentsRetrieved 0
+    pack $window.retrieved.weight $window.retrieved.label \
+        $window.retrieved.hits -side left
+
+# next is the "results" frame (note that the docnums listbox doesn't appear on
+# the screen)
+    frame $window.r
+    scrollbar $window.r.sscroll -relief sunken -command "scroll $window.r"
+#    bind $window.r.sscroll <ButtonRelease-1> "updateSdocs $window.r.sdocs $window.r.sdocnums"
+    listbox $window.r.sdocnums
+    listbox $window.r.sdocs -relief sunken \
+            -setgrid 1 -geometry 50x$ListBoxLength
+    listbox $window.r.srank -yscroll "$window.r.sscroll set" \
+            -setgrid 1 -geometry 4x$ListBoxLength
+  
+    bind $window.r.srank <Any-1> {null}
+    bind $window.r.srank <Any-2> {null}
+    bind $window.r.srank <Any-3> {null}
+
+    bind $window.r.srank <Any-B1-Motion> {null}
+    bind $window.r.srank <Any-B2-Motion> {null}
+    bind $window.r.srank <Any-B3-Motion> {null}
+
+    bind $window.r.sdocs <Any-2> {null}
+    bind $window.r.sdocs <Any-B2-Motion> {null}
+
+    pack $window.r.sscroll -side right -fill y
+    pack $window.r.srank -side left 
+    pack $window.r.sdocs -side left -fill x -expand yes
+
+# pack them up
+    pack $window.e -side top -anchor e -pady 10 -fill x -expand yes
+    pack $window.retrieved -anchor w
+    pack $window.r -side bottom -anchor e -pady 10 -fill x -expand yes
+}
+
+# Make a "help" window
+#
+proc mkHelp {} {
+    if [winfo exists .help] { destroy .help }
+    toplevel .help
+    wm title .help "X interface to the mg information retrieval system"
+    wm iconname .help "About xmg"
+    frame .help.buttons
+    button .help.buttons.close -text Close -command "destroy .help" -width 10
+    button .help.buttons.help -text Help -width 10
+    button .help.buttons.conditions -text Conditions -width 10
+    button .help.buttons.warranty -text Warranty -width 10
+    button .help.buttons.bugs -text Bugs -width 10
+
+    frame .help.t
+    text .help.t.text -relief raised -bd 2 -setgrid true -height 24 -width 95
+    .help.t.text configure -yscrollcommand ".help.t.sy set" 
+    scrollbar .help.t.sy -relief flat -command ".help.t.text yview"
+    
+    pack .help.buttons.close .help.buttons.help -side right -fill x
+    pack .help.buttons.conditions .help.buttons.warranty \
+         .help.buttons.bugs -side left
+    pack .help.buttons -side bottom -fill x
+
+    pack .help.t.text -side left -expand yes -fill both
+    pack .help.t.sy -side right -fill y 
+    pack .help.t -side top -fill both -expand yes
+    enterText .help.t.text [HelpText]
+    grayButton help
+}
+
+proc grayButton {button} {
+    bind .help.buttons.help <1> "enterText .help.t.text \[HelpText\]
+         grayButton help" 
+    .help.buttons.help configure -state normal
+
+    bind .help.buttons.bugs <1> "enterText .help.t.text \[Bugs\]
+         grayButton bugs" 
+    .help.buttons.bugs configure -state normal
+
+    bind .help.buttons.warranty <1> "enterText .help.t.text \[Warranty\]
+         grayButton warranty"
+    .help.buttons.warranty configure -state normal
+
+    bind .help.buttons.conditions <1> "enterText .help.t.text \[Conditions\]
+         grayButton conditions" 
+    .help.buttons.conditions configure -state normal
+    disableButton .help.buttons.$button
+}
+
+# The text for errors in the MG environment variable
+#
+
+
+proc bookDetails {} {
+  return { \
+
+ This X interface was written by Bruce McKenzie, Ian Witten and Craig Nevill-Manning.  
+ For information on mg, see
+             Witten, I.H.,  Moffat, A. and Bell, T.C. (1994) "Managing gigabytes: compressing
+             and indexing documents and images." Van Nostrand Reinhold, New York.
+             ISBN 0-442-01863-0, US $54.95; call 1 (800) 544-0550 to order.
+}
+}
+
+proc initializationFailure {} {
+    return [format "%s\n%s" {\
+In order to run XMG you need to have already created and indexed some document collections,
+ and placed them in a directory whose name is given by the environment variable MGDATA.
+ Your MGDATA variable is unset or does not specify a directory with files in; therefore XMG
+ cannot proceed.
+} [bookDetails]]
+}
+
+proc mgqueryFailure {} {
+    return [format "%s\n%s" {\
+In order to run XMG you need to have already created and indexed some document collections,
+ and placed them in a directory whose name is given by the environment variable MGDATA.
+ There is a problem with the collection that you have chosen. Please re-index the collection before
+ you use it again.
+} [bookDetails]]
+
+}
+
+# The text for the help message
+#
+proc HelpText {} {
+    return [format "%s\n%s" {\
+This is an X interface to the mg information retrieval system.
+
+ Type a query in the "Query" box.
+ The first line or so of each matching document is listed. 
+ Click on any line to show the complete document.
+ Shift-click to show the document in its own window
+ Press Next and Previous to cycle through the list of documents (Shift works here too).
+ In document windows (other than the main window), typing n or p shows the next and previous 
+ documents; N or P creates a new window for them. q closes the most recently created window.
+ If you change the query, existing windows continue to refer to the original query.
+ 
+ You can select either Boolean or Ranked queries.
+ Boolean queries: use & for AND, | for OR, ! for NOT, and parentheses for grouping
+ Ranked queries:  documents are listed in order of relevance; a weight is shown alongside each
+                                  weights are normalized to 100 for the most relevant document
+                                  choose Approximate Ranking for greater retrieval speed. 
+ } [bookDetails]]
+}
+
+proc reformat {text} {
+    regsub -all "\n *\n *" $text "BLEQUEWFI" text
+    regsub -all "\[ \t\n\r\]+" $text " " text
+    regsub -all "BLEQUEWFI" $text "\n\n" text
+    return $text
+}
+
+proc Conditions {} {
+    return [reformat [join [sendandget ".conditions\nTHISWILLNEVERMATCHANYTHING\n"] "\n"]]
+}
+
+proc Warranty {} {
+    return [reformat [join [sendandget ".warranty\nTHISWILLNEVERMATCHANYTHING\n"] "\n"]]
+}
+
+proc Bugs {} {
+    return [reformat {
+Known shortcomings of xmg include:
+
+    Slow picture viewing.  Pictures are decompressed in their entirety before a window is created 
+        for the picture.  This often results in a long delay with no feedback. Moreover, when 
+        an image's document is displayed repeatedly, multiple identical images are shown.
+
+    Sequential viewing.  There is no way of going to the next document in the collection to see the
+        context of documents that have been retrieved.  This would be trivial to implement but
+        conflicts with the interpretation of the "previous" and "next" buttons.
+    }]
+}
+
+###############################################################################
+# The main program
+###############################################################################
+
+scan [info tclversion] "%d.%d" major minor
+
+if {$major < 7} {
+    puts "xmg requires version 7.0 of the tcl interpreter. You are using version $major.$minor"
+    exit
+}
+
+# Default font settings
+set defaulttextfont   -adobe-times-medium-r-normal--14-140-75-75-p-74-iso8859-1
+set defaultbuttonfont -adobe-times-bold-r-normal--14-140-75-75-p-77-iso8859-1
+set textfont   [query_resource textfont Textfont $defaulttextfont]
+set buttonfont [query_resource buttonfont Buttonfont $defaultbuttonfont]
+
+set MaxWindowHeight 10
+set HeadLength 100
+set scrolledto 0
+set ListBoxLength 12
+set windowname 0
+set Terminator "RECORD_END"
+set fileId ""
+set query ""
+set ImageString "::::::::::"
+set stacking ".m.t"
+
+tk_listboxSingleSelect Listbox
+option add *Text.wrap word
+
+option add *Text.font $textfont
+option add *Listbox.font $textfont
+option add *Entry.font $textfont
+
+option add *Button.font $buttonfont
+option add *Menubutton.font $buttonfont
+option add *Radiobutton.font $buttonfont
+option add *Checkbutton.font $buttonfont
+option add *Label.font $buttonfont
+option add *Menu.font $buttonfont
+
+wm title . "Managing Gigabytes"
+wm iconname . "xmg"
+frame .m -borderwidth 5 -relief raised
+
+# top part of frame
+frame .m.t
+
+# on the left side of the top part is the "buttons" panel
+frame .m.t.b
+mkButtons .m.t.b
+
+# on the right side is the "query" panel
+frame .m.t.q
+mkQuery .m.t.q
+
+set q [query_resource querytype Querytype approx-ranked]
+set booleanquery [expr \"$q\" == \"boolean\"]
+set approxquery [expr \"$q\" == \"approx-ranked\"]
+# the above lines will trigger changeQuerytype
+
+pack .m.t.b -side left -anchor nw
+pack .m.t.q -side right -anchor ne -fill both -expand yes
+
+# at the bottom is the "document" panel
+frame .m.d
+makeDocumentPanel .m.d
+
+.m.d.buttons.close configure -text "Exit" \
+    -command "destroy ."
+button .m.d.buttons.help -text "Help" -width 10 \
+	-command "mkHelp"
+
+pack .m.d.buttons.help -side right
+pack .m.t -side top -fill x -expand yes
+pack .m.d -side bottom -fill both -expand yes
+
+pack .m -fill both -expand yes
+wm geometry . +300+85
+
+set collection [query_resource collection Collection $collection]
+if {$argc>0} { set collection $argv }
+
+enterText .m.d.text [HelpText]
+
+initMG $collection
+
+###############################################################################
+###############################################################################
+# The following file selection box procedure was written by Andrew Donkin
+# of the University of Waikato. 
+###############################################################################
+
+proc FSBox { {fsBoxMessage "Select file:"}} {
+# xf ignore me 5
+  global fsBox
+
+  set fsBox(name) ""
+  set fsBox(internalPath) [pwd]
+  set fsBox(pattern) "*"
+  set fsBox(all) 0
+
+  # build widget structure
+
+  # start build of toplevel
+  if {"[info commands XFDestroy]" != ""} {
+    catch {XFDestroy .fsBox}
+  } {
+    catch {destroy .fsBox}
+  }
+  toplevel .fsBox -borderwidth 0
+  wm geometry .fsBox 350x300 
+  wm title .fsBox {File select box}
+  wm maxsize .fsBox 1000 1000
+  wm minsize .fsBox 100 100
+  # end build of toplevel
+
+  label .fsBox.message1 -anchor c -text "$fsBoxMessage"
+  frame .fsBox.frame1  -borderwidth 0  -relief raised
+
+  button .fsBox.frame1.ok  -text "OK"  -command "
+      global fsBox
+      set fsBox(name) \[.fsBox.file.file get\]
+      set fsBox(path) \[.fsBox.path.path get\]
+
+      set fsBox(internalPath) \[.fsBox.path.path get\]
+
+      if {\"\[info commands XFDestroy\]\" != \"\"} {
+        catch {XFDestroy .fsBox}
+      } {
+        catch {destroy .fsBox}
+      }"
+
+  button .fsBox.frame1.rescan -text "Rescan" -command {
+      global fsBox
+      FSBoxFSShow [.fsBox.path.path get] [.fsBox.pattern.pattern get] $fsBox(all)
+  }
+
+  button .fsBox.frame1.cancel -text "Cancel" -command "
+      global fsBox
+      set fsBox(name) {}
+      set fsBox(path) {}
+
+      if {\"\[info commands XFDestroy\]\" != \"\"} {
+        catch {XFDestroy .fsBox}
+      } {
+        catch {destroy .fsBox}
+      }"
+
+  frame .fsBox.path -borderwidth 0 -relief raised
+  frame .fsBox.path.paths 
+  label .fsBox.path.paths.paths -borderwidth 0 -text "Pathname:"
+
+  entry .fsBox.path.path -relief sunken
+  .fsBox.path.path insert 0 $fsBox(internalPath)
+  frame .fsBox.pattern -borderwidth 0 -relief raised
+  frame .fsBox.pattern.patterns 
+
+  label .fsBox.pattern.patterns.patterns -borderwidth 0 -text "Selection pattern:"
+  entry .fsBox.pattern.pattern -relief sunken
+  .fsBox.pattern.pattern insert 0 $fsBox(pattern)
+  
+  frame .fsBox.files -borderwidth 0 -relief raised
+  scrollbar .fsBox.files.vscroll -relief raised -command ".fsBox.files.files yview"
+  scrollbar .fsBox.files.hscroll -orient horiz -relief raised -command ".fsBox.files.files xview" 
+  listbox .fsBox.files.files -exportselection false -relief raised -xscrollcommand \
+        ".fsBox.files.hscroll set" -yscrollcommand ".fsBox.files.vscroll set"
+  frame .fsBox.file -borderwidth 0 -relief raised
+  label .fsBox.file.labelfile -text "Filename:"
+  entry .fsBox.file.file -relief sunken
+  focus .fsBox.file.file
+
+  .fsBox.file.file delete 0 end
+  .fsBox.file.file insert 0 $fsBox(name)
+  
+  checkbutton .fsBox.pattern.all -offvalue 0 -onvalue 1 -text "Show all files" -variable fsBox(all) -command {
+      global fsBox
+      FSBoxFSShow [.fsBox.path.path get] [.fsBox.pattern.pattern get] $fsBox(all)
+    }
+
+  FSBoxFSShow $fsBox(internalPath) $fsBox(pattern) $fsBox(all)
+
+  # bindings
+  bind .fsBox.files.files <Double-Button-1> "FSBoxFSFileSelectDouble %W %y"
+  bind .fsBox.files.files <ButtonPress-1> "FSBoxFSFileSelect %W %y"
+  bind .fsBox.files.files <Button1-Motion> "FSBoxFSFileSelect %W %y"
+  bind .fsBox.files.files <Shift-Button1-Motion> "FSBoxFSFileSelect %W %y"
+  bind .fsBox.files.files <Shift-ButtonPress-1> "FSBoxFSFileSelect %W %y"
+
+  bind .fsBox.path.path <Return> {
+    global fsBox
+    FSBoxFSShow [.fsBox.path.path get] [.fsBox.pattern.pattern get] $fsBox(all)
+    .fsBox.file.file icursor end
+    focus .fsBox.file.file}
+  catch "bind .fsBox.path.path <Up> {}"
+  bind .fsBox.path.path <Down> {
+    .fsBox.file.file icursor end
+    focus .fsBox.file.file}
+
+  bind .fsBox.file.file <Return> "
+    global fsBox
+    set fsBox(name) \[.fsBox.file.file get\]
+    set fsBox(path) \[.fsBox.path.path get\]
+    set fsBox(internalPath) \[.fsBox.path.path get\]
+
+    if {\"\[info commands XFDestroy\]\" != \"\"} {
+      catch {XFDestroy .fsBox}
+    } {
+      catch {destroy .fsBox}
+    }"
+  bind .fsBox.file.file <Up> {.fsBox.path.path icursor end
+    focus .fsBox.path.path}
+  bind .fsBox.file.file <Down> {.fsBox.pattern.pattern icursor end
+    focus .fsBox.pattern.pattern}
+
+  bind .fsBox.pattern.pattern <Return> {
+    global fsBox
+    FSBoxFSShow [.fsBox.path.path get] [.fsBox.pattern.pattern get] $fsBox(all)}
+  bind .fsBox.pattern.pattern <Up> {
+    .fsBox.file.file icursor end
+    focus .fsBox.file.file}
+  catch "bind .fsBox.pattern.pattern <Down> {}"
+
+  # packing
+  pack .fsBox.files.vscroll -side left -fill y 
+  pack .fsBox.files.hscroll -side bottom -fill x
+  pack .fsBox.files.files -side left -fill both -expand yes
+
+  pack .fsBox.file.labelfile -side left
+  pack .fsBox.file.file -side left -fill  both -expand yes
+
+  pack .fsBox.frame1.ok -side left -fill both -expand yes
+  pack .fsBox.frame1.rescan -side left -fill both -expand yes
+  pack .fsBox.frame1.cancel -side left -fill both -expand yes
+
+  pack .fsBox.path.paths.paths -side left
+
+  pack .fsBox.pattern.patterns.patterns -side left
+
+  pack .fsBox.path.paths -side left
+  pack .fsBox.path.path -side left -fill both -expand yes
+
+  pack .fsBox.pattern.patterns -side left
+  pack .fsBox.pattern.all -side right -fill both
+  pack .fsBox.pattern.pattern -side left -fill both -expand yes
+
+  pack .fsBox.message1 -side top -fill both
+  pack .fsBox.frame1 -side bottom -fill both
+  pack .fsBox.pattern -side bottom -fill both
+  pack .fsBox.file -side bottom -fill both
+  pack .fsBox.path -side bottom -fill both
+  pack .fsBox.files -side left -fill both -expand yes
+
+  update idletask
+  grab .fsBox
+  tkwait window .fsBox
+
+  if {"[string trim $fsBox(path)]" != "" ||
+      "[string trim $fsBox(name)]" != ""} {
+    if {"[string trimleft [string trim $fsBox(name)] /]" == ""} {
+      return [string trimright [string trim $fsBox(path)] /]
+    } {
+      return [string trimright [string trim $fsBox(path)] /]/[string trimleft [string trim $fsBox(name)] /]
+    }
+  }
+}
+
+proc FSBoxBindSelectOne { fsBoxW fsBoxY} {
+# xf ignore me 6
+
+  set fsBoxNearest [$fsBoxW nearest $fsBoxY]
+  if {$fsBoxNearest >= 0} {
+    $fsBoxW select from $fsBoxNearest
+    $fsBoxW select to $fsBoxNearest
+  }
+}
+
+proc FSBoxFSFileSelect { fsBoxW fsBoxY} {
+# xf ignore me 6
+  global fsBox
+
+  FSBoxBindSelectOne $fsBoxW $fsBoxY
+  set fsBoxNearest [$fsBoxW nearest $fsBoxY]
+  if {$fsBoxNearest >= 0} {
+    set fsBoxTmpEntry [$fsBoxW get $fsBoxNearest]
+    if {"[string index $fsBoxTmpEntry           [expr [string length $fsBoxTmpEntry]-1]]" == "/" ||
+        "[string index $fsBoxTmpEntry           [expr [string length $fsBoxTmpEntry]-1]]" == "@"} {
+      set fsBoxFileName [string range $fsBoxTmpEntry 0             [expr [string length $fsBoxTmpEntry]-2]]
+      if {![IsADir [string trimright $fsBox(internalPath)/$fsBoxFileName @]] &&
+          ![IsASymlink [string trimright $fsBox(internalPath)/$fsBoxFileName @]]} {
+        set fsBoxFileName $fsBoxTmpEntry
+      }
+    } {
+      if {"[string index $fsBoxTmpEntry             [expr [string length $fsBoxTmpEntry]-1]]" == "*"} {
+        set fsBoxFileName [string range $fsBoxTmpEntry 0           [expr [string length $fsBoxTmpEntry]-2]]
+        if {![file executable $fsBox(internalPath)/$fsBoxFileName]} {
+          set fsBoxFileName $fsBoxTmpEntry
+        }
+      } {
+        set fsBoxFileName $fsBoxTmpEntry
+      }
+    }
+    if {![IsADir [string trimright $fsBox(internalPath)/$fsBoxFileName @]]} {
+      set fsBox(name) $fsBoxFileName
+      .fsBox.file.file delete 0 end
+      .fsBox.file.file insert 0 $fsBox(name)
+    }
+  }
+}
+
+proc FSBoxFSFileSelectDouble { fsBoxW fsBoxY} {
+# xf ignore me 6
+  global fsBox
+
+  FSBoxBindSelectOne $fsBoxW $fsBoxY
+  set fsBoxNearest [$fsBoxW nearest $fsBoxY]
+  if {$fsBoxNearest >= 0} {
+    set fsBoxTmpEntry [$fsBoxW get $fsBoxNearest]
+    if {"$fsBoxTmpEntry" == "../"} {
+      set fsBoxTmpEntry [string trimright [string trim $fsBox(internalPath)] "@/"]
+      if {"$fsBoxTmpEntry" == ""} {
+        return
+      }
+      FSBoxFSShow [file dirname $fsBoxTmpEntry]         [.fsBox.pattern.pattern get] $fsBox(all)
+      .fsBox.path.path delete 0 end
+      .fsBox.path.path insert 0 $fsBox(internalPath)
+    } {
+      if {"[string index $fsBoxTmpEntry [expr [string length $fsBoxTmpEntry]-1]]" == "/" ||
+          "[string index $fsBoxTmpEntry [expr [string length $fsBoxTmpEntry]-1]]" == "@"} {
+        set fsBoxFileName [string range $fsBoxTmpEntry 0               [expr [string length $fsBoxTmpEntry]-2]]
+        if {![IsADir [string trimright $fsBox(internalPath)/$fsBoxFileName @]] &&
+            ![IsASymlink [string trimright $fsBox(internalPath)/$fsBoxFileName @]]} {
+          set fsBoxFileName $fsBoxTmpEntry
+        }
+      } {
+        if {"[string index $fsBoxTmpEntry [expr [string length $fsBoxTmpEntry]-1]]" == "*"} {
+          set fsBoxFileName [string range $fsBoxTmpEntry 0                 [expr [string length $fsBoxTmpEntry]-2]]
+          if {![file executable $fsBox(internalPath)/$fsBoxFileName]} {
+            set fsBoxFileName $fsBoxTmpEntry
+          }
+        } {
+          set fsBoxFileName $fsBoxTmpEntry
+        }
+      }
+      if {[IsADir [string trimright $fsBox(internalPath)/$fsBoxFileName @]]} {
+        set fsBox(internalPath) "[string trimright $fsBox(internalPath) {/@}]/$fsBoxFileName"
+        FSBoxFSShow $fsBox(internalPath) [.fsBox.pattern.pattern get] $fsBox(all)
+        .fsBox.path.path delete 0 end
+        .fsBox.path.path insert 0 $fsBox(internalPath)
+      } {
+        set fsBox(name) $fsBoxFileName
+        set fsBox(path) $fsBox(internalPath)
+        if {"[info commands XFDestroy]" != ""} {
+          catch {XFDestroy .fsBox}
+        } {
+          catch {destroy .fsBox}
+        }
+      }
+    }
+  }
+}
+
+proc FSBoxFSShow { fsBoxPath fsBoxPattern fsBoxAll} {
+# xf ignore me 6
+  global fsBox
+
+  set fsBox(pattern) $fsBoxPattern
+
+  if {[file exists $fsBoxPath] && [file readable $fsBoxPath] &&
+      [IsADir $fsBoxPath]} {
+    set fsBox(internalPath) $fsBoxPath
+  } {
+    if {[file exists $fsBoxPath] && [file readable $fsBoxPath] &&
+        [IsAFile $fsBoxPath]} {
+      set fsBox(internalPath) [file dirname $fsBoxPath]
+      .fsBox.file.file delete 0 end
+      .fsBox.file.file insert 0 [file tail $fsBoxPath]
+      set fsBoxPath $fsBox(internalPath)
+    } {
+      while {"$fsBoxPath" != "" && "$fsBoxPath" != "/" &&
+             ![file isdirectory $fsBoxPath]} {
+        set fsBox(internalPath) [file dirname $fsBoxPath]
+         set fsBoxPath $fsBox(internalPath)
+      }
+    }
+  }
+  if {"$fsBoxPath" == ""} {
+    set fsBoxPath "/"
+    set fsBox(internalPath) "/"
+  }
+  .fsBox.path.path delete 0 end
+  .fsBox.path.path insert 0 $fsBox(internalPath)
+
+  if {[.fsBox.files.files size] > 0} {
+    .fsBox.files.files delete 0 end
+  }
+  if {$fsBoxAll} {
+    if {[catch "exec ls -F -a $fsBoxPath" fsBoxResult]} {
+      puts stderr "$fsBoxResult"
+    }
+  } {
+    if {[catch "exec ls -F $fsBoxPath" fsBoxResult]} {
+      puts stderr "$fsBoxResult"
+    }
+  }
+  set fsBoxElementList [lsort $fsBoxResult]
+
+  foreach fsBoxCounter [winfo children .fsBox.pattern.patterns.patterns] {
+    if {[string length [info commands XFDestroy]] > 0} {
+      catch {XFDestroy $fsBoxCounter}
+    } {
+      catch {destroy $fsBoxCounter}
+    }
+  }
+  menu .fsBox.pattern.patterns.patterns.menu
+
+  if {"$fsBoxPath" != "/"} {
+    .fsBox.files.files insert end "../"
+  }
+  foreach fsBoxCounter $fsBoxElementList {
+    if {[string match $fsBoxPattern $fsBoxCounter] ||
+        [IsADir [string trimright $fsBoxPath/$fsBoxCounter "/@"]]} {
+      if {"$fsBoxCounter" != "../" &&
+          "$fsBoxCounter" != "./"} {
+        .fsBox.files.files insert end $fsBoxCounter
+      }
+    }
+  }
+}
+
+proc IsADir { pathName} {
+# xf ignore me 5
+  if {[file isdirectory $pathName]} {
+    return 1
+  } {
+    catch "file type $pathName" fileType
+    if {"$fileType" == "link"} {
+      if {[catch "file readlink $pathName" linkName]} {
+        return 0
+      }
+      catch "file type $linkName" fileType
+      while {"$fileType" == "link"} {
+        if {[catch "file readlink $linkName" linkName]} {
+          return 0
+        }
+        catch "file type $linkName" fileType
+      }
+      return [file isdirectory $linkName]
+    }
+  }
+  return 0
+}
+
+proc IsAFile { fileName} {
+# xf ignore me 5
+  if {[file isfile $fileName]} {
+    return 1
+  } {
+    catch "file type $fileName" fileType
+    if {"$fileType" == "link"} {
+      if {[catch "file readlink $fileName" linkName]} {
+        return 0
+      }
+      catch "file type $linkName" fileType
+      while {"$fileType" == "link"} {
+        if {[catch "file readlink $linkName" linkName]} {
+          return 0
+        }
+        catch "file type $linkName" fileType
+      }
+      return [file isfile $linkName]
+    }
+  }
+  return 0
+}
+
+proc IsASymlink { fileName} {
+# xf ignore me 5
+  catch "file type $fileName" fileType
+  if {"$fileType" == "link"} {
+    return 1
+  }
+  return 0
+}
Index: /indexers/branches/3.03a/mg/src/text/GCC.mak
===================================================================
--- /indexers/branches/3.03a/mg/src/text/GCC.mak	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/GCC.mak	(revision 14757)
@@ -0,0 +1,205 @@
+###########################################################################
+#
+# gcc win32 makefile -- mg\src\text
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2000  The New Zealand Digital Library Project
+#
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+AR = ar
+RANLIB = ranlib
+CC = gcc
+DELETE = del
+INSTALL = copy
+
+o = .o
+e = .exe
+/ = \\
+
+CPPFLAGS = -g
+DEFS = -DNZDL -DQUIET -DSHORT_SUFFIX -DPARADOCNUM -DHAVE_CONFIG_H \
+       -D_LITTLE_ENDIAN
+LIBS = ..$/..$/lib$/libmg.a
+ 
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(LDFLAGS) -o $@
+ 
+.SUFFIXES:
+.SUFFIXES: .c $o
+.c$o:
+	$(COMPILE) $<
+ 
+INCLUDES = -I"..$/.." -I"..$/..$/lib"
+
+
+SOURCES = \
+  backend.c               locallib.c              mg_weights_build.c   \
+  bool_optimiser.c        mg.special.c            mgdictlist.c         \
+  bool_parser.c           mg_compression_dict.c   mgquery.c            \
+  bool_query.c            mg_errors.c             mgstat.c             \
+  bool_tester.c           mg_fast_comp_dict.c     mg_decompress_text.c \
+  bool_tree.c             mg_files.c              query.docnums.c      \
+  commands.c              mg_hilite_words.c       query.ranked.c       \
+  comp_dict.c             mg_invf_dict.c          read_line.c          \
+  environment.c           mg_invf_dump.c          stem_search.c        \
+  mg_invf_merge.c         stemmer.c               mg_stem_idx.c        \
+  mg_invf_rebuild.c       term_lists.c            mgstemidxlist.c      \
+  invf_get.c              mg_passes.c             text.pass1.c         \
+  ivf.pass1.c             mg_perf_hash_build.c    text.pass2.c         \
+  ivf.pass2.c             mg_text_estimate.c      text_get.c           \
+  lists.c                 mg_text_merge.c         weights.c            \
+  query_term_list.c       words.c
+
+HEADERS = \
+  backend.h          conditions.h       locallib.h         term_lists.h \
+  bool_optimiser.h   environment.h      mg.h               text.h       \
+  bool_parser.h      globals.h          mg_errors.h        text_get.h   \
+  bool_query.h       hash.h             mg_files.h         warranty.h   \
+  bool_tree.h        help.mg.h          mg_merge.h         weights.h    \
+  build.h            invf.h             read_line.h        words.h      \
+  commands.h         invf_get.h         stem_search.h                   \
+  comp_dict.h        lists.h            stemmer.h                       \
+  query_term_list.h
+
+EXEC = \
+  mgquery$e mg_weights_build$e mgstat$e mg_invf_dump$e \
+  mg_invf_dict$e mg_invf_rebuild$e mgdictlist$e \
+  mg_passes$e mg_perf_hash_build$e mg_compression_dict$e \
+  mg_text_estimate$e mg_fast_comp_dict$e mg_hilite_words$e \
+  mg_invf_merge$e mg_text_merge$e bool_tester$e \
+  mg_stem_idx$e  mgstemidxlist$e mg_decompress_text$e
+
+all:    $(EXEC) libtextin.a
+
+HILITE_OBJS = mg_hilite_words$o stemmer$o locallib$o words$o
+mg_hilite_words$e: $(HILITE_OBJS)
+	$(LINK) $(HILITE_OBJS) $(LIBS)
+
+BOOL_OBJS = bool_tree$o bool_parser$o bool_optimiser$o bool_tester$o \
+	    term_lists$o stemmer$o stem_search$o mg_errors$o query_term_list$o \
+	    words$o
+bool_tester$e: $(BOOL_OBJS)
+	$(LINK) $(BOOL_OBJS) $(LIBS)
+
+QUERY_OBJS = \
+	mgquery$o locallib$o lists$o \
+	query.ranked$o query.docnums$o stem_search$o \
+	environment$o commands$o weights$o text_get$o stemmer$o \
+	read_line$o mg_errors$o backend$o invf_get$o \
+	term_lists$o bool_tree$o bool_parser$o bool_optimiser$o bool_query$o \
+	query_term_list$o words$o
+mgquery$e: $(QUERY_OBJS)
+	$(LINK) $(QUERY_OBJS) $(LIBS)
+
+commands$o : help.mg.h warranty.h conditions.h
+
+PASSES_OBJS = \
+	mg_passes$o text.pass1$o comp_dict$o stemmer$o \
+	text.pass2$o locallib$o \
+	ivf.pass1$o ivf.pass2$o mg.special$o mg_files$o \
+	words$o
+mg_passes$e: $(PASSES_OBJS)
+	$(LINK) $(PASSES_OBJS) $(LIBS)
+
+WEIGHTS_BUILD_OBJS = mg_weights_build$o mg_files$o
+mg_weights_build$e: $(WEIGHTS_BUILD_OBJS)
+	$(LINK) $(WEIGHTS_BUILD_OBJS) $(LIBS)
+
+COMP_DICT_OBJS = mg_compression_dict$o mg_files$o locallib$o
+mg_compression_dict$e: $(COMP_DICT_OBJS)
+	$(LINK) $(COMP_DICT_OBJS) $(LIBS)
+
+FAST_COMP_OBJS = mg_fast_comp_dict$o mg_files$o locallib$o
+mg_fast_comp_dict$e: $(FAST_COMP_OBJS)
+	$(LINK) $(FAST_COMP_OBJS) $(LIBS)
+
+TEXT_EST_OBJS = mg_text_estimate$o locallib$o comp_dict$o mg_files$o
+mg_text_estimate$e: $(TEXT_EST_OBJS)
+	$(LINK) $(TEXT_EST_OBJS) $(LIBS)
+
+STAT_OBJS = mgstat$o mg_files$o locallib$o
+mgstat$e: $(STAT_OBJS)
+	$(LINK) $(STAT_OBJS) $(LIBS)
+
+INVF_DUMP_OBJS = mg_invf_dump$o locallib$o mg_files$o
+mg_invf_dump$e: $(INVF_DUMP_OBJS)
+	$(LINK) $(INVF_DUMP_OBJS) $(LIBS)
+
+INVF_DICT_OBJS = mg_invf_dict$o mg_files$o locallib$o
+mg_invf_dict$e: $(INVF_DICT_OBJS)
+	$(LINK) $(INVF_DICT_OBJS) $(LIBS)
+
+INVF_REB_OBJS = mg_invf_rebuild$o locallib$o
+mg_invf_rebuild$e: $(INVF_REB_OBJS)
+	$(LINK) $(INVF_REB_OBJS) $(LIBS)
+
+DICTLIST_OBJS = mgdictlist$o locallib$o
+mgdictlist$e: $(DICTLIST_OBJS)
+	$(LINK) $(DICTLIST_OBJS) $(LIBS)
+
+PERF_HASH_OBJS = mg_perf_hash_build$o mg_files$o
+mg_perf_hash_build$e: $(PERF_HASH_OBJS)
+	$(LINK) $(PERF_HASH_OBJS) $(LIBS)
+
+STEM_IDX_OBJS = mg_stem_idx$o mg_files$o stemmer$o locallib$o \
+                mg_errors$o term_lists$o
+mg_stem_idx$e: $(STEM_IDX_OBJS)
+	$(LINK) $(STEM_IDX_OBJS) $(LIBS)
+
+STEM_IDX_LIST_OBJS = mgstemidxlist$o mg_files$o
+mgstemidxlist$e: $(STEM_IDX_LIST_OBJS)
+	$(LINK) $(STEM_IDX_LIST_OBJS) $(LIBS)
+
+DECOMPRESS_TEXT_OBJS = mg_decompress_text$o query_term_list$o mg_files$o mg_errors$o \
+                       text_get$o locallib$o backend$o stem_search$o \
+                       term_lists$o stemmer$o weights$o invf_get$o lists$o
+mg_decompress_text$e: $(DECOMPRESS_TEXT_OBJS)
+	$(LINK) $(DECOMPRESS_TEXT_OBJS) $(LIBS)
+
+TEXT_MERGE_OBJS = mg_text_merge$o mg_files$o locallib$o
+mg_text_merge$e: $(TEXT_MERGE_OBJS)
+	$(LINK) $(TEXT_MERGE_OBJS) $(LIBS)
+
+INVF_MERGE_OBJS = mg_invf_merge$o mg_files$o locallib$o
+mg_invf_merge$e: $(INVF_MERGE_OBJS)
+	$(LINK) $(INVF_MERGE_OBJS) $(LIBS)
+
+install: 
+	$(INSTALL) *$e ..$/..$/..$/..$/bin$/windows
+
+LIB_OBJS = \
+	query_term_list$o \
+	locallib$o lists$o \
+	query.ranked$o query.docnums$o stem_search$o \
+	environment$o commands$o weights$o text_get$o stemmer$o \
+	read_line$o mg_errors$o backend$o invf_get$o \
+	term_lists$o bool_tree$o bool_parser$o bool_optimiser$o \
+	bool_query$o words$o
+
+libtextin.a: $(LIB_OBJS)
+	$(DELETE) libtextin.a
+	$(AR) cru libtextin.a $(LIB_OBJS)
+	$(RANLIB) libtextin.a
+
+clean:
+	$(DELETE) *$o 
+	$(DELETE) *$e
Index: /indexers/branches/3.03a/mg/src/text/MGPASS.C
===================================================================
--- /indexers/branches/3.03a/mg/src/text/MGPASS.C	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/MGPASS.C	(revision 14757)
@@ -0,0 +1,510 @@
+/**************************************************************************
+ *
+ * mgpass.cpp -- Driver for the various passes -
+
+	V1 -  removed all the pipe processing and replaced with
+	      code to directly explore a directory of files.
+	V2 -  rebuilt to extract non text files from web browser
+	      'catch' file.  Also to display progress count
+			   GH/WJR
+
+ * Copyright (C) 1994  Neil Sharman, ..
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include <malloc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "memlib.h"
+#include "messages.h"
+
+#include "longlong.h"
+
+#include "mg_files.h"
+#include "mg.h"
+#include "build.h"
+#include "text.h"
+#include "stemmer.h"
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:23  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.2  2001/09/20 02:32:00  cs025
+   a few fixes for compiling under windows with new long long stuff in mg
+
+   Revision 1.1  1999/08/10 21:17:39  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.5  1998/12/02 01:32:40  sjboddie
+   fixed 1 missing semi-colon..
+
+   Revision 1.4  1998/12/02 00:57:10  rjmcnab
+
+   Fixed to compile with the changes to the stemming.
+
+   Revision 1.3  1998/11/24 03:39:23  rjmcnab
+
+   Fixed a small error in the windows compilation
+
+   Revision 1.2  1998/11/24 01:29:39  rjmcnab
+
+   Fixed a few problems with the windows build
+
+   Revision 1.1  1998/11/17 09:34:12  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:56:57  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:52  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+#define MAX_PASSES 5
+
+#define SPECIAL 1
+#define TEXT_PASS_1 2
+#define TEXT_PASS_2 4
+#define IVF_PASS_1 8
+#define IVF_PASS_2 16
+
+#define MIN_BUF 8192
+#define path_length 256
+
+unsigned long buf_size = 3 * 1024 * 1024;       /* 3Mb */
+unsigned long invf_buffer_size = 5 * 1024 * 1024;       /* 5Mb */
+unsigned long ChunkLimit = 0;
+char InvfLevel = 2;
+char SkipSGML = 0;
+char MakeWeights = 0;
+FILE *Comp_Stats = NULL;
+int comp_stat_point = 0;
+mg_ullong bytes_processed = 0;
+int num_docs = 0;
+mg_ullong bytes_received = 0;
+int stem_method = 0;
+int stemmer_num = 0; /* default to the Lovin stemmer */
+
+static char Passes = 0;
+static unsigned long trace = 0;
+static int Dump = 0;
+static char **files = NULL;
+static int num_files = 0;
+static char *trace_name = NULL;
+
+static char dirname[path_length], wildname[path_length];
+static int by_para = 0, recurse = 0, html_catch = 0;
+static char *buffer;
+char *line_start, *data_end, *base, *scan;
+
+typedef struct pass_data
+  {
+    char *name;
+    int (*init) (char *);
+    int (*process) (u_char *, int);
+    int (*done) (char *);
+  }
+pass_data;
+
+static pass_data PassData[MAX_PASSES] =
+{
+  {"special", init_special, process_special, done_special},
+  {"text.pass1", init_text_1, process_text_1, done_text_1},
+  {"text.pass2", init_text_2, process_text_2, done_text_2},
+  {"ivf.pass1", init_ivf_1, process_ivf_1, done_ivf_1},
+  {"ivf.pass2", init_ivf_2, process_ivf_2, done_ivf_2},
+};
+
+static char *usage_str = "\nUSAGE:\n"
+"  %s [-h] [-G] [-D] [-1|-2|-3] [-T1] [-T2] [-I1] [-I2] [-N1]\n"
+"  %*s [-N2] [-W] [-S] [-b buffer-size] [-d dictionary-directory]\n"
+"  %*s [-t trace-point Mb] [-m invf-memory] [-c chunk-limit]\n"
+"  %*s [-n trace-name] [-C comp-stat-size] [-s stem_method] -f doc-collection-name\n"
+"  %*s [source directory\\] [source file]\n";
+
+static void usage (char *err)
+{
+  if (err) Message (err);
+  fprintf (stderr, usage_str, msg_prefix, strlen (msg_prefix), "",
+    strlen (msg_prefix), "", strlen (msg_prefix), "");
+  exit (1);
+}
+
+void do_process(char *buffer, int num)
+{
+  int pass;
+  if (num == 0) Message ("Warning : Processing zero length document");
+  num_docs++;
+  bytes_processed += num;
+  for (pass = 0; pass < MAX_PASSES; pass++)
+    if (Passes & (1 << pass))
+	if (PassData[pass].process((u_char *)buffer, num) == COMPERROR)
+	   FatalError(1, "Error during file processing");
+}
+
+int refill(int in_fd)
+{
+  int num, bitleft;
+  bitleft = data_end - base;
+  memmove(buffer, base, bitleft);
+  if (buf_size - bitleft < MIN_BUF)
+    FatalError(1, "Paragraph too big for buffer");
+  num = read(in_fd, &buffer[bitleft], buf_size - bitleft);
+  line_start -= (base - buffer);
+  scan -= (base - buffer);
+  base = buffer;
+  data_end = buffer + bitleft + num;
+  if (num > 0) return 1; else return 0;
+}
+
+char *scanpara(int in_fd)
+{
+  int num, blank, in_blank, at_end;
+  num = read(in_fd,buffer,buf_size);
+  in_blank = 1;  base = buffer;  line_start = buffer;  scan = buffer;
+  data_end = buffer + num;  at_end = 0;
+  for (;;) {
+    blank = 1;  line_start = scan;                   // Get a line
+    while (scan < data_end  &&  *scan != '\n')
+      if (*scan++ > ' ') blank = 0;
+    if (scan >= data_end) {
+      if (refill(in_fd)) {
+	while (scan < data_end  &&  *scan != '\n')
+	  if (*scan++ > ' ') blank = 0;
+	if (scan < data_end) scan++;
+	}
+      else at_end = 1;
+      }
+    else scan++;
+    if (line_start < scan) {                         // If we have a line
+      if (in_blank) {
+	if (!blank) { in_blank = 0; base = line_start; }
+	}
+      else {
+	if (blank) {
+	  do_process(base, line_start - base);
+	  in_blank = 1;  base = line_start;
+	  }
+	}
+      }
+    if (at_end) break;
+    }
+  if (in_blank) base = scan;
+  if (scan + 2 <= buffer + buf_size) {
+    *scan++ = 26;  *scan++ = 10;
+    }
+  if (base < scan) do_process(base, scan - base);
+  return NULL;
+}
+
+char *scanfile(int in_fd)
+{
+  int num = read(in_fd,buffer,buf_size);  /*expect to read the whole file*/
+  if (num < 0) return "file locked";
+  if (num >= buf_size-1) return "file too long";
+  do_process(buffer, num);
+  return NULL;
+}
+
+void search(char *dname, char *fname)
+{
+  long dirtag;  struct _finddata_t dirinfo;  int in_fd;  char *res;
+  char search_name[path_length], found_name[path_length];
+
+  sprintf(search_name, "%s%s", dname, fname);    /*Scan files*/
+  dirtag = _findfirst(search_name, &dirinfo);
+  if (dirtag >= 0) {
+    do {
+      if ((dirinfo.attrib & (_A_SUBDIR | _A_HIDDEN | _A_SYSTEM)) == 0) {
+	sprintf(found_name,"%s%s",dname,dirinfo.name);
+	in_fd = open(found_name,O_RDONLY|O_BINARY);
+	if (in_fd >= 0) {
+	  if (by_para)
+	    res = scanpara(in_fd);
+	  else
+	    res = scanfile(in_fd);
+	  if (res != NULL) {
+	    Message("Error %s in processing file %s\n", res, found_name);
+	    exit(1);
+	    }
+	  close(in_fd);
+	  }
+	}
+      } while (_findnext(dirtag, &dirinfo) == 0);
+    _findclose(dirtag);
+    }
+
+  if (recurse == 0) return;
+
+  sprintf(search_name, "%s*.*", dname);          /*Look for subdirs*/
+  dirtag = _findfirst(search_name, &dirinfo);
+  if (dirtag < 0) return;
+  do {
+    if ( ((dirinfo.attrib & (_A_HIDDEN | _A_SYSTEM)) == 0)  &&
+	 ((dirinfo.attrib & _A_SUBDIR) != 0)  &&
+	 strcmp(dirinfo.name,".") != 0 &&
+	 strcmp(dirinfo.name,"..") != 0) {
+      sprintf(found_name,"%s%s",dname,dirinfo.name);
+      strcat(found_name,"\\");
+      search(found_name,fname);
+      }
+    } while (_findnext(dirtag, &dirinfo) == 0);
+  _findclose(dirtag);
+}
+
+static int toobig(int n)
+{
+  if (n > path_length) {
+    printf("Cannot handle urls > %d characters in length\n", path_length);
+    exit(1);
+    }
+  return 0;
+}
+
+void scan_catch(char *dname, char *fname)
+{
+  int in_fd, urllen, conlen, filesize;  char catch_name[path_length];
+  int filecount = 0;
+  enum { filekind_redirected, filekind_text, filekind_other } filekind;
+  sprintf(catch_name, "%s%s", dname, fname);
+  in_fd = open(catch_name,O_RDONLY|O_BINARY);
+  if (in_fd < 0)
+    FatalError(1, "Couldn't open catch file \"%s\"", catch_name);
+  for (;;) {
+    filecount++;  if (filecount%100 == 0) { printf("%d\r", filecount);  fflush(stdout); }
+    if (read(in_fd, &urllen, sizeof(int)) != sizeof(int) || toobig(urllen) ||
+	read(in_fd, catch_name, urllen) != urllen ||
+	read(in_fd, &conlen, sizeof(int)) != sizeof(int) || toobig(conlen) ||
+	read(in_fd, catch_name, conlen) != conlen) break;
+    if (conlen >= 1 && *catch_name == '@')
+      filekind = filekind_redirected;
+    else {
+      if (conlen >= 4 && strncmp(catch_name, "text", 4) == 0)
+	filekind = filekind_text;
+      else
+	filekind = filekind_other;
+      if (read(in_fd, &filesize, sizeof(int)) != sizeof(int))
+	FatalError(1, "File read failed for size field");
+      if (filesize > buf_size)
+	FatalError(1, "File too large (%d > %d)", filesize, buf_size);
+      if (read(in_fd, buffer, filesize) != filesize)
+	FatalError(1, "Failed to read file data");
+      }
+    if (filekind == filekind_text) do_process(buffer, filesize);
+    }
+  close(in_fd);
+}
+
+static void driver (FILE * Trace, char *file_name)
+{
+  int pass;
+
+  buffer = (char *)Xmalloc (buf_size);
+
+  for (pass = 0; pass < MAX_PASSES; pass++)
+    if (Passes & (1 << pass))
+      {
+	if (PassData[pass].init (file_name) == COMPERROR)
+	  FatalError (1, "Error during init of \"%s\"",PassData[pass].name);
+      }
+
+  if (html_catch == 0) search(dirname, wildname);
+		  else scan_catch(dirname, wildname);
+
+  for (pass = 0; pass < MAX_PASSES; pass++)
+    if (Passes & (1 << pass))
+      {
+	if (PassData[pass].done (file_name) == COMPERROR)
+	  FatalError (1, "Error during done of \"%s\"", PassData[pass].name);
+      }
+
+
+  free (buffer);
+}
+
+void main (int argc, char **argv)
+{
+  int ch;
+  char *filename = NULL;
+  FILE *Trace = NULL;
+
+  msg_prefix = argv[0];
+
+  opterr = 0;
+  while ((ch = getopt (argc, argv, "hC:WHGpSD123f:d:b:T:I:t:m:N:c:n:s:")) != -1)
+    {
+      switch (ch)
+	{
+	case 'H':
+	  html_catch = 1;
+	  break;
+	case 'G':
+	  SkipSGML = 1;
+	  break;
+	case 'p':
+	  by_para = 1;
+	  break;
+	case 'S':
+	  Passes |= SPECIAL;
+	  break;
+	case '1':
+	  InvfLevel = 1;
+	  break;
+	case '2':
+	  InvfLevel = 2;
+	  break;
+	case '3':
+	  InvfLevel = 3;
+	  break;
+	case 'f':
+	  filename = optarg;
+	  break;
+	case 'n':
+	  trace_name = optarg;
+	  break;
+	case 'D':
+	  Dump = 1;
+	  break;
+	case 'W':
+	  MakeWeights = 1;
+	  break;
+	case 'd':
+	  set_basepath (optarg);
+	  break;
+	case 's':
+	  stem_method = atoi (optarg) & STEMMER_MASK;
+	  break;
+	case 'b':
+	  buf_size = atoi (optarg) * 1024;
+	  break;
+	case 'C':
+	  comp_stat_point = atoi (optarg) * 1024;
+	  break;
+	case 'c':
+	  ChunkLimit = atoi (optarg);
+	  break;
+	case 'm':
+	  invf_buffer_size = (int) (atof (optarg) * 1024 * 1024);
+	  break;
+	case 'I':
+	case 'N': /* N kept for compatability */
+	  if (*optarg == '1')
+	    Passes |= IVF_PASS_1;
+	  else if (*optarg == '2')
+	    Passes |= IVF_PASS_2;
+	  else
+	    usage ("Invalid pass number");
+	  break;
+	case 'T':
+	  if (*optarg == '1')
+	    Passes |= TEXT_PASS_1;
+	  else if (*optarg == '2')
+	    Passes |= TEXT_PASS_2;
+	  else
+	    usage ("Invalid pass number");
+	  break;
+	case 't':
+	  trace = (unsigned long) (atof (optarg) * 1024 * 1024);
+	  break;
+	case 'h':
+	case '?':
+	  usage (NULL);
+	}
+    }
+
+  if (!filename || *filename == '\0')
+    FatalError (1, "A document collection name must be specified.");
+
+  if (buf_size < MIN_BUF)
+    FatalError (1, "The buffer size must exceed 1024 bytes.");
+
+  if ((Passes & (IVF_PASS_1 | IVF_PASS_2)) == (IVF_PASS_1 | IVF_PASS_2))
+    FatalError (1, "I1 and I2 cannot be done simultaneously.");
+
+  if ((Passes & (TEXT_PASS_1 | TEXT_PASS_2)) == (TEXT_PASS_1 | TEXT_PASS_2))
+    FatalError (1, "T1 and T2 cannot be done simultaneously.");
+
+  if (!Passes)
+    FatalError (1, "S, T1, T2, I1 or I2 must be specified.");
+
+  if (argc - optind == 1) {
+    strcpy(dirname,"");
+    strcpy(wildname,argv[optind]);
+    }
+  else if (argc - optind == 2) {
+    strcpy(dirname,argv[optind]);
+    strcpy(wildname,argv[optind+1]);
+    }
+  else FatalError(1, "Finder code requires directory and filespec.");
+
+  if (strrchr(wildname,'*') != NULL  ||  strrchr(wildname,'?') != NULL)
+    recurse = 1;
+
+  if (trace)
+    {
+      if (!trace_name)
+	trace_name = make_name (filename, TRACE_SUFFIX, NULL);
+      if (!(Trace = fopen (trace_name, "a")))
+	Message ("Unable to open \"%s\". No tracing will be done.", trace_name);
+      else
+	setbuf (Trace, NULL);
+    }
+  else
+    Trace = NULL;
+
+  if (comp_stat_point)
+    {
+      char *name = make_name (filename, COMPRESSION_STATS_SUFFIX, NULL);
+      if (!(Comp_Stats = fopen (name, "wb")))
+	Message ("Unable to open \"%s\". No comp. stats. will be generated.",
+		 name);
+    }
+
+
+  if (Trace)
+    {
+      int i;
+      fprintf (Trace, "\n\n\t\t-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n");
+      for (i = 0; i < argc; i++)
+	fprintf (Trace, "%s ", argv[i]);
+      fprintf (Trace, "\n\n");
+    }
+
+  driver (Trace, filename);
+
+  if (Trace)
+    fclose (Trace);
+
+  if (Comp_Stats)
+    fclose (Comp_Stats);
+
+  exit (0);
+}
Index: /indexers/branches/3.03a/mg/src/text/Makefile.in
===================================================================
--- /indexers/branches/3.03a/mg/src/text/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/Makefile.in	(revision 14757)
@@ -0,0 +1,387 @@
+###########################################################################
+#
+# Makefile.in -- Makefile for the MG system
+# Copyright (C) 1994  Neil Sharman;  1995 Tim Shimmin
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#       @(#)Makefile.in	1.10 22 Mar 1994
+#
+###########################################################################
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+ 
+SHELL = /bin/sh
+VPATH = @srcdir@
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+bindir = @bindir@
+srcdir = @srcdir@
+subdir = src/text
+top_srcdir = @top_srcdir@
+transform = @program_transform_name@
+
+AR = ar
+CC = @CC@
+CFLAGS = @CFLAGS@ -fpic
+DEFS = @DEFS@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBS = ../../lib/libmglib.a @LIBS@
+TOUCH = echo timestamp >
+AWK = @AWK@
+YACC = @YACC@
+
+##########################################
+# Uncomment for compiling for the nzdl project
+#
+CFLAGS = @CFLAGS@ -fpic -DNZDL -DQUIET -DSHORT_SUFFIX -DPARADOCNUM
+##########################################
+
+datadir = $(prefix)/share
+libexecdir = $(exec_prefix)/libexec
+localedir = $(datadir)/locale
+mandir = $(prefix)/man/man1
+ 
+COMPILE = $(CC) -c $(DEFS) $(TREC_MODE) $(READLINE) $(INCLUDES) $(CFLAGS)
+LINK = $(CC) $(LDFLAGS) -o $@
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+	$(COMPILE) $<
+ 
+
+ANSI2KNR = @ANSI2KNR@
+o = .@U@o
+ 
+.SUFFIXES: ._c ._o
+.c._c:
+	./ansi2knr $< > $*.tmp && mv $*.tmp $@
+._c._o:
+	@echo $(COMPILE) $<
+	@rm -f _$*.c
+	@ln $< _$*.c && $(COMPILE) _$*.c && mv _$*.o $@ && rm _$*.c
+.c._o:
+	./ansi2knr $< > $*.tmp && mv $*.tmp $*._c
+	@echo $(COMPILE) $*._c
+	@rm -f _$*.c
+	@ln $*._c _$*.c && $(COMPILE) _$*.c && mv _$*.o $@ && rm _$*.c
+ 
+INCLUDES = -I../../../.. -I../.. -I../../lib -I.
+
+#############################################################################
+#
+# Uncomment (and possibly edit) the following lines if you wish
+# to use the GNU readline library for the input in mgquery
+# 
+#READLINE = -DGNU_READLINE -I/opt/gnu/include/readline -L/opt/gnu/lib
+#READLINE_LIBS = -lreadline -ltermcap
+#
+#
+#############################################################################
+
+#############################################################################
+#
+# When working with the trec collection this should be uncommented.
+#
+# TREC_MODE = -DTREC_MODE
+#
+#
+#############################################################################
+
+SOURCES = \
+  backend.c               locallib.c              mg_weights_build.c   \
+  bool_optimiser.c        mg.special.c            mgdictlist.c         \
+  bool_parser.c           mg_compression_dict.c   mgquery.c            \
+  bool_query.c            mg_errors.c             mgstat.c             \
+  bool_tester.c           mg_fast_comp_dict.c     mg_decompress_text.c \
+  bool_tree.c             mg_files.c              query.docnums.c      \
+  commands.c              mg_hilite_words.c       query.ranked.c       \
+  comp_dict.c             mg_invf_dict.c          read_line.c          \
+  environment.c           mg_invf_dump.c          stem_search.c        \
+  mg_invf_merge.c         stemmer.c               mg_stem_idx.c        \
+  mg_invf_rebuild.c       term_lists.c            mgstemidxlist.c      \
+  invf_get.c              mg_passes.c             text.pass1.c         \
+  ivf.pass1.c             mg_perf_hash_build.c    text.pass2.c         \
+  ivf.pass2.c             mg_text_estimate.c      text_get.c           \
+  lists.c                 mg_text_merge.c         weights.c            \
+  query_term_list.c       words.c                 mg_passes_4jni.c
+
+HEADERS = \
+  backend.h          conditions.h       locallib.h         term_lists.h \
+  bool_optimiser.h   environment.h      mg.h               text.h       \
+  bool_parser.h      globals.h          mg_errors.h        text_get.h   \
+  bool_query.h       hash.h             mg_files.h         warranty.h   \
+  bool_tree.h        help.mg.h          mg_merge.h         weights.h    \
+  build.h            invf.h             read_line.h        words.h      \
+  commands.h         invf_get.h         stem_search.h                   \
+  comp_dict.h        lists.h            stemmer.h                       \
+  query_term_list.h
+
+
+MISC          = Makefile.in help.mg.src bool_parser.y warranty.src conditions.src
+
+ALLFILES      =	$(SOURCES) $(HEADERS) $(MISC) $(MAN)
+
+DISTFILES     = $(ALLFILES) 
+
+EXEC          = mgquery mg_weights_build mgstat mg_invf_dump mg_invf_dict \
+                mg_invf_rebuild mgdictlist mg_passes mg_perf_hash_build \
+                mg_compression_dict mg_text_estimate mg_fast_comp_dict \
+                mg_hilite_words mg_invf_merge mg_text_merge bool_tester \
+                mg_stem_idx mgstemidxlist mg_decompress_text 
+
+MAN           = mgquery.1 mg_weights_build.1 mgstat.1 mg_invf_dump.1 mg_invf_dict.1 \
+                mg_invf_rebuild.1 mgdictlist.1 mg_passes.1 mg_perf_hash_build.1 \
+                mg_compression_dict.1 mg_text_estimate.1 mg_fast_comp_dict.1 \
+                mg_hilite_words.1 mg_invf_merge.1 mg_text_merge.1 \
+                mg_stem_idx.1 mgstemidxlist.1 mg_decompress_text.1 
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+all:	$(EXEC) libmgtext.a libmgpass.a
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+help.mg.h : help.mg.src
+	sed -e 's/\\/\\\\/g' -e 's/\"/\\\"/g' help.mg.src | $(AWK) '/^#/ { next; };{ if (x == 0) printf("static char *help_str[] = {\n\"%s\\n\"", $$0); else printf(",\n\"%s\\n\"", $$0); x = 1; }; END { printf("};\n"); }' - >help.mg.h
+
+warranty.h : warranty.src
+	sed  -e 's/\\/\\\\/g' -e 's/\"/\\\"/g' warranty.src | $(AWK) '/^#/ { next; };{ if (x == 0) printf("static char *warranty_str[] = {\n\"%s\\n\"", $$0); else printf(",\n\"%s\\n\"", $$0); x = 1; }; END { printf("};\n"); }' - >warranty.h
+
+conditions.h : conditions.src
+	sed -e 's/\\/\\\\/g' -e 's/\"/\\\"/g' conditions.src | $(AWK) '/^#/ { next; };{ if (x == 0) printf("static char *cond_str[] = {\n\"%s\\n\"", $$0); else printf(",\n\"%s\\n\"", $$0); x = 1; }; END { printf("};\n"); }' - >conditions.h
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+HILITE_OBJS = mg_hilite_words$o stemmer$o locallib$o words$o environment$o
+
+mg_hilite_words: $(HILITE_OBJS)
+	$(LINK) $(HILITE_OBJS) $(LIBS)
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+bool_parser.c: bool_parser.y
+	$(YACC) $?
+	mv y.tab.c $@
+
+BOOL_OBJS = bool_tester$o bool_tree$o bool_parser$o bool_optimiser$o  \
+            term_lists$o stemmer$o stem_search$o mg_errors$o query_term_list$o \
+	    words$o environment$o
+
+bool_tester: $(BOOL_OBJS)
+	$(LINK) $(BOOL_OBJS) $(LIBS)
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+QUERY_OBJS = \
+	mgquery$o locallib$o lists$o \
+	query.ranked$o query.docnums$o stem_search$o \
+	environment$o commands$o weights$o text_get$o stemmer$o \
+	read_line$o mg_errors$o backend$o invf_get$o \
+	term_lists$o bool_tree$o bool_parser$o bool_optimiser$o bool_query$o \
+	query_term_list$o words$o
+
+mgquery: $(QUERY_OBJS)	
+	$(LINK) $(READLINE) $(QUERY_OBJS) $(READLINE_LIBS) $(LIBS)
+
+commands$o : help.mg.h warranty.h conditions.h
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+PASSES_OBJS = \
+	mg_passes$o text.pass1$o comp_dict$o stemmer$o \
+	text.pass2$o locallib$o \
+	ivf.pass1$o ivf.pass2$o mg.special$o mg_files$o \
+	words$o environment$o
+
+mg_passes: $(PASSES_OBJS)
+	$(LINK) $(PASSES_OBJS) $(LIBS) 
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+WEIGHTS_BUILD_OBJS = mg_weights_build$o mg_files$o
+
+mg_weights_build: $(WEIGHTS_BUILD_OBJS)
+	$(LINK) $(WEIGHTS_BUILD_OBJS) $(LIBS)
+
+COMP_DICT_OBJS = mg_compression_dict$o mg_files$o locallib$o
+
+mg_compression_dict: $(COMP_DICT_OBJS)
+	$(LINK) $(COMP_DICT_OBJS) $(LIBS)
+
+FAST_COMP_OBJS = mg_fast_comp_dict$o mg_files$o locallib$o
+
+mg_fast_comp_dict: $(FAST_COMP_OBJS)
+	$(LINK) $(FAST_COMP_OBJS) $(LIBS)
+
+TEXT_EST_OBJS = mg_text_estimate$o locallib$o comp_dict$o mg_files$o
+
+mg_text_estimate: $(TEXT_EST_OBJS)
+	$(LINK) $(TEXT_EST_OBJS) $(LIBS)
+
+STAT_OBJS = mgstat$o mg_files$o locallib$o
+
+mgstat:	$(STAT_OBJS)
+	$(LINK) $(STAT_OBJS) $(LIBS)
+
+INVF_DUMP_OBJS = mg_invf_dump$o locallib$o mg_files$o
+
+mg_invf_dump: $(INVF_DUMP_OBJS)
+	$(LINK) $(INVF_DUMP_OBJS) $(LIBS)
+
+INVF_DICT_OBJS = mg_invf_dict$o mg_files$o locallib$o
+
+mg_invf_dict: $(INVF_DICT_OBJS)
+	$(LINK) $(INVF_DICT_OBJS) $(LIBS)
+
+INVF_REB_OBJS = mg_invf_rebuild$o locallib$o
+
+mg_invf_rebuild: $(INVF_REB_OBJS)
+	$(LINK) $(INVF_REB_OBJS) $(LIBS)
+
+DICTLIST_OBJS = mgdictlist$o locallib$o
+
+mgdictlist: $(DICTLIST_OBJS)
+	$(LINK) $(DICTLIST_OBJS) $(LIBS)
+
+PERF_HASH_OBJS = mg_perf_hash_build$o mg_files$o
+
+mg_perf_hash_build: $(PERF_HASH_OBJS)
+	$(LINK) $(PERF_HASH_OBJS) $(LIBS)
+
+STEM_IDX_OBJS = \
+                mg_stem_idx$o mg_files$o stemmer$o locallib$o \
+                mg_errors$o term_lists$o
+
+mg_stem_idx: $(STEM_IDX_OBJS)
+	$(LINK) $(STEM_IDX_OBJS) $(LIBS)
+
+STEM_IDX_LIST_OBJS = mgstemidxlist$o mg_files$o
+
+mgstemidxlist: $(STEM_IDX_LIST_OBJS)
+	$(LINK) $(STEM_IDX_LIST_OBJS) $(LIBS)
+
+DECOMPRESS_TEXT_OBJS = \
+                mg_decompress_text.o query_term_list.o mg_files.o mg_errors.o \
+                text_get.o locallib.o backend.o stem_search.o \
+                term_lists.o stemmer.o weights.o invf_get.o lists.o
+
+mg_decompress_text: $(DECOMPRESS_TEXT_OBJS)
+	$(LINK) $(DECOMPRESS_TEXT_OBJS) $(LIBS)
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+TEXT_MERGE_OBJS = mg_text_merge$o mg_files$o locallib$o
+
+mg_text_merge: $(TEXT_MERGE_OBJS)
+	$(LINK) $(TEXT_MERGE_OBJS) $(LIBS)
+
+INVF_MERGE_OBJS = mg_invf_merge$o mg_files$o locallib$o
+
+mg_invf_merge: $(INVF_MERGE_OBJS)
+	$(LINK) $(INVF_MERGE_OBJS) $(LIBS)
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ansi2knr: ansi2knr.o
+	$(LINK) ansi2knr.o $(LIBS)
+
+install: execinstall #maninstall
+uninstall: execuninstall manuninstall
+
+execinstall: $(EXEC)
+	$(top_srcdir)/mkinstalldirs $(bindir); \
+	for name in $(EXEC); do \
+	  $(INSTALL_PROGRAM) $$name \
+	  $(bindir)/`echo $$name | sed '$(transform)'`; \
+	done
+
+execuninstall:
+	for name in $(EXEC); do \
+	 rm -f $(bindir)/`echo $$name | sed '$(transform)'`; \
+	done
+
+maninstall: $(MAN)
+	$(top_srcdir)/mkinstalldirs $(mandir); \
+	for f in $(MAN); do \
+	  $(INSTALL_DATA) $$f $(mandir)/$$f ;\
+	done
+
+manuninstall: $(MAN)
+	for f in $(MAN); do \
+	  rm -f $(mandir)/$$f ;\
+	done
+
+LIB_OBJS = \
+	query_term_list$o \
+	locallib$o lists$o \
+	query.ranked$o query.docnums$o stem_search$o \
+	environment$o commands$o weights$o text_get$o stemmer$o \
+	read_line$o mg_errors$o backend$o invf_get$o \
+	term_lists$o bool_tree$o bool_parser$o bool_optimiser$o \
+	bool_query$o words$o
+
+libmgtext.a: $(LIB_OBJS)
+	rm -f libmgtext.a
+	$(AR) cru libmgtext.a $(LIB_OBJS)
+	$(RANLIB) libmgtext.a
+
+JNI_LIB_OBJS = \
+	mg_passes_4jni$o text.pass1$o comp_dict$o stemmer$o \
+	text.pass2$o locallib$o  words$o environment$o\
+	ivf.pass1$o ivf.pass2$o mg.special$o mg_files$o 
+
+libmgpass.a: $(JNI_LIB_OBJS)
+	rm -f libmgpass.a
+	$(AR) cru libmgpass.a $(JNI_LIB_OBJS)
+	$(RANLIB) libmgpass.a
+
+mostlyclean:
+	rm -f *$o _*.c _*.o *._c *._o core core.*
+ 
+clean: mostlyclean
+	rm -f $(EXEC) libmgtext.a libmgpass.a
+ 
+distclean: clean
+	rm -f ansi2knr
+	rm -f Makefile
+ 
+maintainer-clean: distclean
+	@echo "This command is intended only for maintainers to use;"
+	@echo "rebuilding the deleted files may require special tools."
+ 
+dist: $(DISTFILES)
+	for file in $(DISTFILES); do \
+	  ln $(srcdir)/$$file $(distdir) 2> /dev/null \
+	  || cp -p $(srcdir)/$$file $(distdir); \
+	done
+  
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exc
+
+
+
+
+
+
Index: /indexers/branches/3.03a/mg/src/text/backend.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/backend.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/backend.c	(revision 14757)
@@ -0,0 +1,838 @@
+/**************************************************************************
+ *
+ * backend.c -- Underlying routines for mgquery
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "messages.h"
+#include "timing.h"
+#include "filestats.h"
+#include "sptree.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+
+#include "mg_files.h"
+#include "mg.h"
+#include "invf.h"
+#include "text.h"
+#include "lists.h"
+#include "backend.h"
+#include "stem_search.h"
+#include "invf_get.h"
+#include "text_get.h"
+#include "weights.h"
+#include "locallib.h"
+#include "mg_errors.h"
+
+
+static File *
+OpenFile (char *base, char *suffix, unsigned long magic, int *ok)
+{
+  char FileName[512];
+  File *F;
+  sprintf (FileName, "%s%s", base, suffix);
+  if (!(F = Fopen (FileName, "rb", 0)))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      mg_errno = MG_NOFILE;
+      MgErrorData (FileName);
+      if (ok)
+	*ok = 0;
+      return (NULL);
+    }
+  if (magic)
+    {
+      unsigned long m;
+      if (fread ((char *) &m, sizeof (m), 1, F->f) == 0)
+	{
+	  mg_errno = MG_READERR;
+	  MgErrorData (FileName);
+	  if (ok)
+	    *ok = 0;
+	  Fclose (F);
+	  return (NULL);
+	}
+      NTOHUL(m);  /* [RPAP - Jan 97: Endian Ordering] */
+      if (m != magic)
+	{
+	  mg_errno = MG_BADMAGIC;
+	  MgErrorData (FileName);
+	  if (ok)
+	    *ok = 0;
+	  Fclose (F);
+	  return (NULL);
+	}
+    }
+  return (F);
+}
+
+
+static int 
+open_all_files (query_data * qd)
+{
+  int ok = 1;
+
+  qd->File_text = OpenFile (qd->textpathname, TEXT_SUFFIX, /* [RJM 06/97: text filename] */
+			    MAGIC_TEXT, &ok);
+  qd->File_fast_comp_dict = OpenFile (qd->textpathname, /* [RJM 06/97: text filename] */
+				      TEXT_DICT_FAST_SUFFIX, MAGIC_FAST_DICT, NULL);
+  if (!qd->File_fast_comp_dict)
+    {
+      qd->File_comp_dict = OpenFile (qd->textpathname, /* [RJM 06/97: text filename] */
+				     TEXT_DICT_SUFFIX, MAGIC_DICT, &ok);
+      qd->File_aux_dict = OpenFile (qd->textpathname, /* [RJM 06/97: text filename] */
+				    TEXT_DICT_AUX_SUFFIX, MAGIC_AUX_DICT, NULL);
+    }
+  else
+    qd->File_comp_dict = qd->File_aux_dict = NULL;
+
+  qd->File_stem = OpenFile (qd->pathname, INVF_DICT_BLOCKED_SUFFIX,
+			    MAGIC_STEM, &ok);
+
+  /* [RPAP - Jan 97: Stem Index Change]
+     These will fail if collection not built with stem indexes */
+  qd->File_stem1 = OpenFile (qd->pathname, INVF_DICT_BLOCKED_1_SUFFIX,
+			     MAGIC_STEM_1, NULL);
+  qd->File_stem2 = OpenFile (qd->pathname, INVF_DICT_BLOCKED_2_SUFFIX,
+			     MAGIC_STEM_2, NULL);
+  qd->File_stem3 = OpenFile (qd->pathname, INVF_DICT_BLOCKED_3_SUFFIX,
+			     MAGIC_STEM_3, NULL);
+
+  qd->File_invf = OpenFile (qd->pathname, INVF_SUFFIX,
+			    MAGIC_INVF, &ok);
+
+  /* These will fail if a level 1 inverted file was created because there 
+     will be no document weights */
+  qd->File_text_idx_wgt = OpenFile (qd->pathname, TEXT_IDX_WGT_SUFFIX,
+				    MAGIC_TEXI_WGT, NULL);
+  qd->File_weight_approx = OpenFile (qd->pathname, APPROX_WEIGHTS_SUFFIX,
+				     MAGIC_WGHT_APPROX, NULL);
+  if (qd->File_text_idx_wgt == NULL && qd->File_weight_approx == NULL)
+    qd->File_text_idx = OpenFile (qd->textpathname, /* [RJM 06/97: text filename] */
+				  TEXT_IDX_SUFFIX, MAGIC_TEXI, NULL);
+  else
+    qd->File_text_idx = NULL;
+
+
+  if (!ok)
+    {
+      Fclose (qd->File_text);
+      if (qd->File_fast_comp_dict)
+	Fclose (qd->File_fast_comp_dict);
+      if (qd->File_comp_dict)
+	Fclose (qd->File_comp_dict);
+      Fclose (qd->File_stem);
+
+      /* [RPAP - Jan 97: Stem Index Change] */
+      if (qd->File_stem1)
+	Fclose (qd->File_stem1);
+      if (qd->File_stem2)
+	Fclose (qd->File_stem2);
+      if (qd->File_stem3)
+	Fclose (qd->File_stem3);
+
+      Fclose (qd->File_invf);
+      if (qd->File_text_idx_wgt)
+	Fclose (qd->File_text_idx_wgt);
+      if (qd->File_weight_approx)
+	Fclose (qd->File_weight_approx);
+      if (qd->File_text_idx)
+	Fclose (qd->File_text_idx);
+      return (-1);
+    }
+  return (0);
+
+}
+
+static void 
+close_all_files (query_data * qd)
+{
+  Fclose (qd->File_text);
+  if (qd->File_fast_comp_dict)
+    Fclose (qd->File_fast_comp_dict);
+  if (qd->File_aux_dict)
+    Fclose (qd->File_aux_dict);
+  if (qd->File_comp_dict)
+    Fclose (qd->File_comp_dict);
+  Fclose (qd->File_stem);
+
+  /* [RPAP - Jan 97: Stem Index Change] */
+  if (qd->File_stem1)
+    Fclose (qd->File_stem1);
+  if (qd->File_stem2)
+    Fclose (qd->File_stem2);
+  if (qd->File_stem3)
+    Fclose (qd->File_stem3);
+
+  Fclose (qd->File_invf);
+  if (qd->File_text_idx_wgt)
+    Fclose (qd->File_text_idx_wgt);
+  if (qd->File_weight_approx)
+    Fclose (qd->File_weight_approx);
+  if (qd->File_text_idx)
+    Fclose (qd->File_text_idx);
+}
+
+/* If textname is equal to null then name will be used instead */
+/* [RJM 06/97: text filename] */
+query_data *
+InitQuerySystem (char *dir, char *name, char *textname, InitQueryTimes * iqt)
+{
+  query_data *qd;
+  char *s;
+
+  if (textname == NULL) textname = name; /* [RJM 06/97: text filename] */
+
+  if (!(qd = Xmalloc (sizeof (query_data))))
+    {
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  bzero ((char *) qd, sizeof (*qd));
+
+  qd->mem_in_use = qd->max_mem_in_use = 0;
+
+  qd->doc_pos = qd->buf_in_use = 0;
+  qd->TextBufferLen = 0;
+  qd->DL = NULL;
+
+  /* [RPAP - Feb 97: Term Frequency] */
+  qd->TL = NULL;
+  qd->QTL = NULL;
+
+  qd->TextBuffer = NULL;
+
+  qd->tot_hops_taken = 0;
+  qd->tot_num_of_ptrs = 0;
+  qd->tot_num_of_accum = 0;
+  qd->tot_num_of_terms = 0;
+  qd->tot_num_of_ans = 0;
+  qd->tot_text_idx_lookups = 0;
+
+  qd->hops_taken = 0;
+  qd->num_of_ptrs = 0;
+  qd->num_of_accum = 0;
+  qd->num_of_terms = 0;
+  qd->num_of_ans = 0;
+  qd->text_idx_lookups = 0;
+
+  qd->pathname = NULL; /* RJM 06/97: text filename] */
+  qd->textpathname = NULL; /* RJM 06/97: text filename] */
+
+  s = strrchr (dir, '/');
+  if (s && *(s + 1) == '\0')
+    {
+      /* [RJM 06/97: text filename] */
+      if (!(qd->pathname = Xmalloc (strlen (dir) + strlen (name) + 1)) ||
+	  !(qd->textpathname = Xmalloc (strlen (dir) + strlen (textname) + 1)))
+	{
+	  mg_errno = MG_NOMEM;
+	  if (qd->pathname) Xfree (qd->pathname); /* [RJM 06/97: text filename] */
+	  Xfree (qd);
+	  return (NULL);
+	}
+      sprintf (qd->pathname, "%s%s", dir, name);
+      sprintf (qd->textpathname, "%s%s", dir, textname); /* [RJM 06/97: text filename] */
+    }
+
+  else
+    {
+      /* [RJM 06/97: text filename] */
+      if (!(qd->pathname = Xmalloc (strlen (dir) + strlen (name) + 2)) ||
+	  !(qd->textpathname = Xmalloc (strlen (dir) + strlen (textname) + 2)))
+	{
+	  mg_errno = MG_NOMEM;
+	  if (qd->pathname) Xfree (qd->pathname); /* [RJM 06/97: text filename] */
+	  Xfree (qd);
+	  return (NULL);
+	}
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+      if (dir == NULL || dir[0] == '\0') {
+	sprintf (qd->pathname, "%s", name);
+	sprintf (qd->textpathname, "%s", textname); /* [RJM 06/97: text filename] */
+      } else {
+	sprintf (qd->pathname, "%s%s", dir, name);
+	sprintf (qd->textpathname, "%s%s", dir, textname); /* [RJM 06/97: text filename] */
+      }
+#else
+      sprintf (qd->pathname, "%s/%s", dir, name);
+      sprintf (qd->textpathname, "%s/%s", dir, textname); /* [RJM 06/97: text filename] */
+#endif
+    }
+
+  if (open_all_files (qd) == -1)
+    {
+      Xfree (qd->pathname);
+      Xfree (qd->textpathname); /* [RJM 06/97: text filename] */
+      Xfree (qd);
+      return (NULL);
+    }
+
+  if (iqt)
+    GetTime (&iqt->Start);
+
+  /* Initialise the stemmed dictionary system */
+  if (!(qd->sd = ReadStemDictBlk (qd->File_stem)))
+    {
+      close_all_files (qd);
+      Xfree (qd->pathname);
+      Xfree (qd->textpathname); /* [RJM 06/97: text filename] */
+      Xfree (qd);
+      return (NULL);
+    }
+
+  /* [RPAP - Jan 97: Stem Index Change] */
+  if ((qd->sd->sdh.indexed & 7) && qd->File_stem1 && qd->File_stem2 && qd->File_stem3)
+    {
+      if (!(qd->sd->stem1 = ReadStemIdxBlk (qd->File_stem1)))
+	{
+	  FreeStemDict (qd->sd);
+	  close_all_files (qd);
+	  Xfree (qd->pathname);
+	  Xfree (qd->textpathname); /* [RJM 06/97: text filename] */
+	  Xfree (qd);
+	  return (NULL);
+	}
+      if (!(qd->sd->stem2 = ReadStemIdxBlk (qd->File_stem2)))
+	{
+	  FreeStemDict (qd->sd);
+	  close_all_files (qd);
+	  Xfree (qd->pathname);
+	  Xfree (qd->textpathname); /* [RJM 06/97: text filename] */
+	  Xfree (qd);
+	  return (NULL);
+	}
+      if (!(qd->sd->stem3 = ReadStemIdxBlk (qd->File_stem3)))
+	{
+	  FreeStemDict (qd->sd);
+	  close_all_files (qd);
+	  Xfree (qd->pathname);
+	  Xfree (qd->textpathname); /* [RJM 06/97: text filename] */
+	  Xfree (qd);
+	  return (NULL);
+	}
+      }
+  else if (qd->sd->sdh.indexed != 0)
+    {
+      FreeStemDict (qd->sd);
+      close_all_files (qd);
+      Xfree (qd->pathname);
+      Xfree (qd->textpathname); /* [RJM 06/97: text filename] */
+      Xfree (qd);
+      return (NULL);
+    }
+  else
+    {
+      if (qd->File_stem1)
+	Fclose (qd->File_stem1);
+      if (qd->File_stem2)
+	Fclose (qd->File_stem2);
+      if (qd->File_stem3)
+	Fclose (qd->File_stem3);
+      qd->File_stem1 = NULL;
+      qd->File_stem2 = NULL;
+      qd->File_stem3 = NULL;
+      qd->sd->stem1 = NULL;
+      qd->sd->stem2 = NULL;
+      qd->sd->stem3 = NULL;
+    }
+
+  if (iqt)
+    GetTime (&iqt->StemDict);
+  if (qd->File_weight_approx)
+    {
+      if (!(qd->awd = LoadDocWeights (qd->File_weight_approx,
+				      qd->sd->sdh.num_of_docs)))
+	{
+	  FreeStemDict (qd->sd);
+	  close_all_files (qd);
+	  Xfree (qd->pathname);
+	  Xfree (qd->textpathname); /* [RJM 06/97: text filename] */
+	  Xfree (qd);
+	  return (NULL);
+	}
+    }
+  else
+    qd->awd = NULL;
+
+
+  if (iqt)
+    GetTime (&iqt->ApproxWeights);
+
+  if (!(qd->cd = LoadCompDict (qd->File_comp_dict, qd->File_aux_dict,
+			       qd->File_fast_comp_dict)))
+    {
+      if (qd->awd)
+	FreeWeights (qd->awd);
+      FreeStemDict (qd->sd);
+      close_all_files (qd);
+      Xfree (qd->pathname);
+      Xfree (qd->textpathname); /* [RJM 06/97: text filename] */
+      Xfree (qd);
+      return (NULL);
+    }
+
+  if (iqt)
+    GetTime (&iqt->CompDict);
+
+  if (!(qd->id = InitInvfFile (qd->File_invf, qd->sd)))
+    {
+      FreeCompDict (qd->cd);
+      if (qd->awd)
+	FreeWeights (qd->awd);
+      FreeStemDict (qd->sd);
+      close_all_files (qd);
+      Xfree (qd->pathname);
+      Xfree (qd->textpathname); /* [RJM 06/97: text filename] */
+      Xfree (qd);
+      return (NULL);
+    }
+  if ((qd->File_text_idx_wgt == NULL || qd->File_weight_approx == NULL) &&
+      qd->id->ifh.InvfLevel >= 2)
+    {
+      FreeInvfData (qd->id);
+      FreeCompDict (qd->cd);
+      if (qd->awd)
+	FreeWeights (qd->awd);
+      FreeStemDict (qd->sd);
+      close_all_files (qd);
+      Xfree (qd->pathname);
+      Xfree (qd->textpathname); /* [RJM 06/97: text filename] */
+      Xfree (qd);
+      mg_errno = MG_INVERSION;
+      return (NULL);
+    }
+  if (iqt)
+    GetTime (&iqt->Invf);
+
+  if (!(qd->td = LoadTextData (qd->File_text, qd->File_text_idx_wgt,
+			       qd->File_text_idx)))
+    {
+      FreeInvfData (qd->id);
+      FreeCompDict (qd->cd);
+      if (qd->awd)
+	FreeWeights (qd->awd);
+      FreeStemDict (qd->sd);
+      close_all_files (qd);
+      Xfree (qd->pathname);
+      Xfree (qd->textpathname); /* [RJM 06/97: text filename] */
+      Xfree (qd);
+      return (NULL);
+    }
+
+/* [RPAP - Feb 97: NZDL Additions] */
+#if defined(PARADOCNUM) || defined(NZDL)
+
+/*
+
+This code is based on the TREC_MODE code below to read the .paragraph
+file to determine what document numbers correspond to what paragraphs.
+This code is more space efficient, reading in the .paragraph file
+into memory as an accumulate docnum array.  Eg.  the .paragraph may contain
+
+	[5 3 6 4 7 9 4]
+
+indicating the first document has 5 paragraphs, the next 3, etc.
+This will be stored in memory as
+
+	[0 5 8 14 18 25 34 38]
+
+so a binary search can be performed.  The first 0 is for convenience;
+it prevents testing boundary conditions.
+
+
+The TREC_MODE code does this differently; it stores the array
+
+	[1 1 1 1 1 2 2 2 3 3 3 3 3 3 ....]
+
+allowing directy paragraph to docnum conversion, at the expense
+of memory.
+
+*/ 
+  qd->paragraph = NULL;
+
+  if (qd->id->ifh.InvfLevel == 3)
+    {
+      unsigned long magic;
+      FILE *paragraph;
+      int i;
+      char paraFile[512];
+
+      sprintf(paraFile, "%s%s", qd->pathname, INVF_PARAGRAPH_SUFFIX);
+      paragraph = fopen(paraFile, "rb");
+      if (!paragraph)
+	FatalError(1, "Unable to open 'paraFile'.", paraFile);
+
+      fread((void *)&magic, sizeof(magic), 1, paragraph);
+      qd->paragraph = Xmalloc((qd->td->cth.num_of_docs+1)*sizeof(int));
+      qd->paragraph[0] = 0;
+      for (i = 1; i <= qd->td->cth.num_of_docs; i++)
+	{
+	  int count;
+
+	  if (fread((void *)&count, sizeof(count), 1, paragraph) != 1)
+	    FatalError(1, "Unexpected EOF while reading '%s'.", paraFile);
+	  NTOHSI(count);  /* [RPAP - Jan 97: Endian Ordering] */
+	  qd->paragraph[i] = qd->paragraph[i-1]+count;
+	}
+
+      fclose (paragraph); /* [RJM 07/98: Memory Leak] */
+    }
+  
+  
+#endif
+
+#ifdef TREC_MODE
+  {
+    extern char *trec_ids;
+    extern long *trec_paras;
+    int size;
+    char FileName[512];
+    FILE *f;
+    if (!strstr (qd->pathname, "trec"))
+      goto error;
+    sprintf (FileName, "%s%s", qd->pathname, ".DOCIDS");
+    if (!(f = fopen (FileName, "rb")))  /* [RPAP - Feb 97: WIN32 Port] */
+      {
+	Message ("Unable to open \"%s\"", FileName);
+	goto error;
+      }
+    fseek (f, 0, 2);
+    size = ftell (f);
+    fseek (f, 0, 0);
+    trec_ids = Xmalloc (size);
+    if (!trec_ids)
+      {
+	fclose (f);
+	goto error;
+      }
+    fread (trec_ids, 1, size, f);
+    fclose (f);
+    if (qd->id->ifh.InvfLevel == 3)
+      {
+	int i, d;
+	unsigned long magic;
+	trec_paras = Xmalloc (qd->sd->sdh.num_of_docs * sizeof (long));
+	if (!trec_paras)
+	  {
+	    Xfree (trec_ids);
+	    trec_ids = NULL;
+	    goto error;
+	  }
+	sprintf (FileName, "%s%s", qd->pathname, INVF_PARAGRAPH_SUFFIX);
+	if (!(f = fopen (FileName, "rb")))  /* [RPAP - Feb 97: WIN32 Port] */
+	  {
+	    Message ("Unable to open \"%s\"", FileName);
+	    goto error;
+	  }
+	if (fread ((char *) &magic, sizeof (magic), 1, f) != 1 ||
+	    NTOHUL(magic) != MAGIC_PARAGRAPH)  /* [RPAP - Jan 97: Endian Ordering] */
+	  {
+	    fclose (f);
+	    Message ("Bad magic number in \"%s\"", FileName);
+	    goto error;
+	  }
+
+	for (d = i = 0; i < qd->td->cth.num_of_docs; i++)
+	  {
+	    int count;
+	    if (fread ((char *) &count, sizeof (count), 1, f) != 1)
+	      {
+		fclose (f);
+		goto error;
+	      }
+	    NTOHSI(count);  /* [RPAP - Jan 97: Endian Ordering] */
+	    while (count--)
+	      trec_paras[d++] = i;
+	  }
+	fclose (f);
+      }
+    goto ok;
+  error:
+    if (trec_ids)
+      Xfree (trec_ids);
+    if (trec_paras)
+      Xfree (trec_paras);
+    trec_ids = NULL;
+    trec_paras = NULL;
+  ok:
+    ;
+  }
+#endif
+
+  if (iqt)
+    GetTime (&iqt->Text);
+
+  return (qd);
+}
+
+
+
+
+
+
+/*
+ * Change the amount of memory currently in use
+ *
+ */
+void 
+ChangeMemInUse (query_data * qd, long delta)
+{
+  qd->mem_in_use += delta;
+  if (qd->mem_in_use > qd->max_mem_in_use)
+    qd->max_mem_in_use = qd->mem_in_use;
+}
+
+
+void 
+FinishQuerySystem (query_data * qd)
+{
+/* [RJM 07/98: Memory Leak] */
+#if defined(PARADOCNUM) || defined(NZDL)
+  if (qd->paragraph != NULL) {
+    Xfree (qd->paragraph);
+    qd->paragraph = NULL;
+  }
+#endif
+
+  FreeTextData (qd->td);
+  FreeInvfData (qd->id);
+  FreeCompDict (qd->cd);
+  if (qd->awd)
+    FreeWeights (qd->awd);
+  FreeStemDict (qd->sd);
+  close_all_files (qd);
+  Xfree (qd->textpathname); /* [RJM 06/97: text filename] */
+  Xfree (qd->pathname);
+  FreeQueryDocs (qd);
+  if (qd->TL != NULL) FreeTermList(&qd->TL);         /* [RJM 07/98: Memory Leak] */
+  if (qd->QTL != NULL) FreeQueryTermList(&qd->QTL);  /* [RJM 07/98: Memory Leak] */
+  Xfree (qd);
+
+  /* other global stuff hanging around */
+  MgErrorDeinit ();
+}
+
+
+void 
+ResetFileStats (query_data * qd)
+{
+  ZeroFileStats (qd->File_text);
+  if (qd->File_comp_dict)
+    ZeroFileStats (qd->File_comp_dict);
+  if (qd->File_fast_comp_dict)
+    ZeroFileStats (qd->File_fast_comp_dict);
+  ZeroFileStats (qd->File_stem);
+
+  /* [RPAP - Jan 97: Stem Index Change] */
+  if (qd->File_stem1)
+    ZeroFileStats (qd->File_stem1);
+  if (qd->File_stem2)
+    ZeroFileStats (qd->File_stem2);
+  if (qd->File_stem3)
+    ZeroFileStats (qd->File_stem3);
+
+  ZeroFileStats (qd->File_invf);
+  if (qd->File_text_idx_wgt)
+    ZeroFileStats (qd->File_text_idx_wgt);
+  if (qd->File_weight_approx)
+    ZeroFileStats (qd->File_weight_approx);
+  if (qd->File_text_idx)
+    ZeroFileStats (qd->File_text_idx);
+}
+
+
+void 
+TransFileStats (query_data * qd)
+{
+  qd->File_text->Current = qd->File_text->Cumulative;
+  if (qd->File_comp_dict)
+    qd->File_comp_dict->Current = qd->File_comp_dict->Cumulative;
+  if (qd->File_fast_comp_dict)
+    qd->File_fast_comp_dict->Current = qd->File_fast_comp_dict->Cumulative;
+  qd->File_stem->Current = qd->File_stem->Cumulative;
+
+  /* [RPAP - Jan 97: Stem Index Change] */
+  if (qd->File_stem1)
+    qd->File_stem1->Current = qd->File_stem1->Cumulative;
+  if (qd->File_stem2)
+    qd->File_stem2->Current = qd->File_stem2->Cumulative;
+  if (qd->File_stem3)
+    qd->File_stem3->Current = qd->File_stem3->Cumulative;
+
+  qd->File_invf->Current = qd->File_invf->Cumulative;
+  if (qd->File_text_idx_wgt)
+    qd->File_text_idx_wgt->Current = qd->File_text_idx_wgt->Cumulative;
+  if (qd->File_weight_approx)
+    qd->File_weight_approx->Current = qd->File_weight_approx->Cumulative;
+  if (qd->File_text_idx)
+    qd->File_text_idx->Current = qd->File_text_idx->Cumulative;
+}
+
+
+void 
+FreeTextBuffer (query_data * qd)
+{
+  if (qd->TextBuffer)
+    {
+      Xfree (qd->TextBuffer);
+      ChangeMemInUse (qd, -qd->TextBufferLen);
+    }
+  qd->TextBuffer = NULL;
+  qd->TextBufferLen = 0;
+}
+
+void 
+FreeQueryDocs (query_data * qd)
+{
+  qd->doc_pos = 0;
+  qd->buf_in_use = 0;
+  if (qd->DL)
+    {
+      int i;
+      for (i = 0; i < qd->DL->num; i++)
+	if (qd->DL->DE[i].CompTextBuffer)
+	  {
+	    Xfree (qd->DL->DE[i].CompTextBuffer);
+	    qd->DL->DE[i].CompTextBuffer = NULL;
+	    ChangeMemInUse (qd, -qd->DL->DE[i].Len);
+	  }
+      Xfree (qd->DL);
+    }
+  qd->DL = NULL;
+  FreeTextBuffer (qd);
+}
+
+int 
+LoadCompressedText (query_data * qd, int max_mem)
+{
+  DocEntry *DE;
+  if (qd->DL == NULL || qd->doc_pos >= qd->DL->num)
+    return -1;
+
+  DE = &qd->DL->DE[qd->doc_pos];
+  if (!DE->CompTextBuffer)
+    {
+      int i;
+      DocEntry *de;
+      for (i = 0, de = qd->DL->DE; i < qd->DL->num; i++, de++)
+	if (de->CompTextBuffer)
+	  {
+	    Xfree (de->CompTextBuffer);
+	    de->CompTextBuffer = NULL;
+	    ChangeMemInUse (qd, -de->Len);
+	  }
+      if (LoadBuffers (qd, &qd->DL->DE[qd->doc_pos], max_mem,
+		       qd->DL->num - qd->doc_pos) == -1)
+	return -1;
+    }
+  return 0;
+}
+
+int 
+GetDocNum (query_data * qd)
+{
+  if (qd->DL == NULL || qd->doc_pos >= qd->DL->num)
+    return -1;
+  return qd->DL->DE[qd->doc_pos].DocNum;
+}
+
+DocEntry *
+GetDocChain (query_data * qd)
+{
+  if (qd->DL == NULL || qd->doc_pos >= qd->DL->num)
+    return NULL;
+  return &(qd->DL->DE[qd->doc_pos]);
+}
+
+float 
+GetDocWeight (query_data * qd)
+{
+  if (qd->DL == NULL || qd->doc_pos >= qd->DL->num)
+    return -1;
+  return qd->DL->DE[qd->doc_pos].Weight;
+}
+
+long 
+GetDocCompLength (query_data * qd)
+{
+  if (qd->DL == NULL || qd->doc_pos >= qd->DL->num)
+    return -1;
+  return qd->DL->DE[qd->doc_pos].Len;
+}
+
+
+u_char *
+GetDocText (query_data * qd, unsigned long *len)
+{
+  DocEntry *DE;
+  int ULen;
+  if (qd->DL == NULL || qd->doc_pos >= qd->DL->num)
+    return NULL;
+
+  DE = &qd->DL->DE[qd->doc_pos];
+
+  if (!DE->CompTextBuffer)
+    {
+      fprintf (stderr, "The compressed text buffer is NULL\n");
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  FreeTextBuffer (qd);
+
+  qd->TextBufferLen = (int) (qd->td->cth.ratio * 1.01 *
+			     DE->Len) + 100;
+  if (!(qd->TextBuffer = Xmalloc (qd->TextBufferLen)))
+    {
+      fprintf (stderr, "No memory for TextBuffer\n");
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  DecodeText (qd->cd, (u_char *) (DE->CompTextBuffer), DE->Len,
+	      (u_char *) (qd->TextBuffer), &ULen);
+  qd->TextBuffer[ULen] = '\0';
+
+  if (ULen >= qd->TextBufferLen)
+    {
+      fprintf (stderr, "%d >= %d\n", ULen, qd->TextBufferLen);
+      mg_errno = MG_BUFTOOSMALL;
+      return (NULL);
+    }
+
+  if (len)
+    *len = ULen;
+
+  return qd->TextBuffer;
+}
+
+int 
+NextDoc (query_data * qd)
+{
+  if (qd->DL == NULL || qd->doc_pos >= qd->DL->num)
+    return 0;
+  qd->doc_pos++;
+  return qd->doc_pos < qd->DL->num;
+}
Index: /indexers/branches/3.03a/mg/src/text/backend.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/backend.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/backend.h	(revision 14757)
@@ -0,0 +1,261 @@
+/**************************************************************************
+ *
+ * backend.h -- Underlying routines and datastructures for mgquery
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#ifndef BACKEND_H
+#define BACKEND_H
+
+#include "sysfuncs.h"
+
+#include "timing.h"
+#include "lists.h"
+#include "term_lists.h"
+#include "query_term_list.h"  /* [RPAP - Feb 97: Term Frequency] */
+#include "mg.h"
+#include "invf.h"
+#include "text.h"
+
+
+typedef struct invf_data
+  {
+    File *InvfFile;
+    unsigned long N;
+    unsigned long Nstatic;	/* N parameter for decoding inverted file entries */
+    struct invf_file_header ifh;
+  }
+invf_data;
+
+typedef struct text_data
+  {
+    File *TextFile;
+    File *TextIdxFile;
+    File *TextIdxWgtFile;
+    long current_pos;
+    struct
+      {
+	unsigned long Start;
+	float Weight;
+      }
+     *idx_data;
+    compressed_text_header cth;
+  }
+text_data;
+
+
+typedef struct auxiliary_dict
+  {
+    aux_frags_header afh[2];
+    u_char *word_data[2];
+    u_char **words[2];
+    int blk_start[2][33], blk_end[2][33];	/* blk_start and blk_end are required
+						   for the hybrid methods */
+  }
+auxiliary_dict;
+
+
+typedef struct compression_dict
+  {
+    compression_dict_header cdh;
+    comp_frags_header *cfh[2];
+    unsigned long MemForCompDict;
+    u_char ***values[2];
+    u_char *escape[2];
+    huff_data *chars_huff[2];
+    u_long **chars_vals[2];
+    huff_data *lens_huff[2];
+    u_long **lens_vals[2];
+    auxiliary_dict *ad;
+    int fast_loaded;
+  }
+compression_dict;
+
+
+typedef struct stemmed_idx   /* [RPAP - Jan 97: Stem Index Change] */
+  {
+    File *stem_idx_file;
+    struct stem_idx_header sih;
+    u_char **index;
+    unsigned long *pos;
+    int active;
+    u_char *buffer;
+    unsigned long MemForStemIdx;
+  }
+stemmed_idx;
+
+
+typedef struct stemmed_dict
+  {
+    File *stem_file;
+    struct stem_dict_header sdh;
+    u_char **index;
+    unsigned long *pos;
+    int active;
+    u_char *buffer;
+    unsigned long MemForStemDict;
+
+    /* [RPAP - Jan 97: Stem Index Change] */
+    stemmed_idx *stem1;
+    stemmed_idx *stem2;
+    stemmed_idx *stem3;
+  }
+stemmed_dict;
+
+
+typedef struct approx_weights_data
+  {
+    double L;
+    double B;
+    unsigned long *DocWeights;
+    char bits;
+    float *table;
+    unsigned long mask;
+    unsigned long MemForWeights;
+    unsigned long num_of_docs;
+  }
+approx_weights_data;
+
+
+typedef struct RankedQueryInfo
+  {
+    int QueryFreqs;
+    int Exact;           /* use exact weights for ranking or not */
+    long MaxDocsToRetrieve;	/* may be -1 for all */
+    long MaxParasToRetrieve;
+    int Sort;        
+    char AccumMethod;		/* 'A' = array,  'S' = splay tree,  'H' = hash_table */
+    long MaxAccums;		/* may be -1 for all */
+    long MaxTerms;		/* may be -1 for all */
+    int StopAtMaxAccum; /* Stop at maximum accumulator or not */
+    long HashTblSize;
+    char *skip_dump;
+  }
+RankedQueryInfo;
+
+
+
+typedef struct BooleanQueryInfo
+  {
+    long MaxDocsToRetrieve;
+  }
+BooleanQueryInfo;
+
+
+/* [TS:24/Aug/94] - maximum number of characters in term string */
+#define MAXTERMSTRLEN 1023
+
+typedef struct query_data
+  {
+    stemmed_dict *sd;
+    compression_dict *cd;
+    approx_weights_data *awd;
+    invf_data *id;
+    text_data *td;
+#if defined(PARADOCNUM) || defined(NZDL)
+    int *paragraph;
+#endif
+    char *pathname;
+    char *textpathname; /* [RJM 06/97: text filename] */
+    File *File_text;
+    File *File_comp_dict;
+    File *File_aux_dict;
+    File *File_fast_comp_dict;
+    File *File_text_idx_wgt;
+    File *File_text_idx;
+    File *File_stem;
+
+    /* [RPAP - Jan 97: Stem Index Change] */
+    File *File_stem1;
+    File *File_stem2;
+    File *File_stem3;
+
+    File *File_invf;
+    File *File_weight_approx;
+    unsigned long mem_in_use, max_mem_in_use;
+    unsigned long num_of_ptrs, tot_num_of_ptrs;
+    unsigned long num_of_terms, tot_num_of_terms;
+    unsigned long num_of_accum, tot_num_of_accum;
+    unsigned long num_of_ans, tot_num_of_ans;
+    unsigned long hops_taken, tot_hops_taken;
+    unsigned long text_idx_lookups, tot_text_idx_lookups;
+    unsigned long max_buffers;
+    unsigned doc_pos;
+    unsigned buf_in_use;
+    DocList *DL;
+    TermList *TL;		/* [TS:Oct/94] - so term list for query can easily be accessed */
+    u_char *TextBuffer;
+    int TextBufferLen;
+    QueryTermList *QTL;    /* [RPAP - Feb 97: Term Frequency] */
+  }
+query_data;
+
+
+
+typedef struct InitQueryTimes
+  {
+    ProgTime Start;
+    ProgTime StemDict;
+    ProgTime ApproxWeights;
+    ProgTime CompDict;
+    ProgTime Invf;
+    ProgTime Text;
+  }
+InitQueryTimes;
+
+
+/* [RJM 06/97: text filename] */
+query_data *InitQuerySystem (char *dir, char *name, char *textname, InitQueryTimes * iqt);
+
+void ChangeMemInUse (query_data * qd, long delta);
+
+void FinishQuerySystem (query_data * qd);
+
+void ResetFileStats (query_data * qd);
+
+void TransFileStats (query_data * qd);
+
+void RankedQuery (query_data * qd, char *Query, RankedQueryInfo * rqi);
+
+void BooleanQuery (query_data * qd, char *Query, BooleanQueryInfo * bqi,
+		   int stem_method);
+
+void DocnumsQuery (query_data * qd, char *QueryLine);
+
+void FreeTextBuffer (query_data * qd);
+
+void FreeQueryDocs (query_data * qd);
+
+int LoadCompressedText (query_data * qd, int max_mem);
+
+int GetDocNum (query_data * qd);
+
+float GetDocWeight (query_data * qd);
+
+long GetDocCompLength (query_data * qd);
+
+u_char *GetDocText (query_data * qd, unsigned long *len);
+
+DocEntry *GetDocChain (query_data * qd);
+
+int NextDoc (query_data * qd);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/bool_optimiser.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/bool_optimiser.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/bool_optimiser.c	(revision 14757)
@@ -0,0 +1,1111 @@
+/**************************************************************************
+ *
+ * bool_optimiser -- optimise boolean parse tree
+ * Copyright (C) 1994,95  Tim Shimmin
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:23  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:17:42  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:34:20  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.4  1995/07/27  04:54:55  tes
+   * Committing optimiser before I add the code
+   * to find diff-nodes in any kind of tree.
+   *
+   * Revision 1.3  1994/10/20  00:02:55  tes
+   * Fixed bug with bool_optimiser:
+   *   - it couldn't handle "false | false"
+   *   - it couldn't handle "true & true"
+   * These would collapse into an empty list and cause an error.
+   *
+   * Revision 1.2  1994/10/18  06:11:02  tes
+   * The boolean optimiser seems to be modifying the parse tree
+   * like it is supposed to.
+   * Paragraph ranking now works without any text files if required to.
+   *
+   * Revision 1.1  1994/10/12  01:15:28  tes
+   * Found bugs in the existing boolean query optimiser.
+   * So decided to rewrite it.
+   * I accidentally deleted query.bool.y, but I have replaced it
+   * with bool_parser.y (which I have forgotten to add here ! ;-(
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "bool_tree.h"
+#include "term_lists.h"
+#include "messages.h"
+
+typedef int (*CompFunc) (const void *, const void *);
+typedef void (*TreeFunc) (bool_tree_node *);
+
+/* --- routines --- */
+static void PermeateNots (bool_tree_node * tree);
+static void DoubleNeg (bool_tree_node * not_tree);
+static void AndDeMorgan (bool_tree_node * not_tree);
+static void OrDeMorgan (bool_tree_node * not_tree);
+static int AndDistribute (bool_tree_node * tree);
+static void DNF_Distribute (bool_tree_node * tree);
+static void ReplaceWithChildren (bool_tree_node * tree);
+static void CollapseTree (bool_tree_node * tree);
+static void AndTrueFalse (bool_tree_node * and_tree);
+static void OrTrueFalse (bool_tree_node * or_tree);
+static void TF_Idempotent (bool_tree_node * tree);
+static void AndNotToDiff (bool_tree_node * and_tree, TreeFunc recurs_func);
+static void DiffDNF (bool_tree_node * or_node);
+static void DiffTree (bool_tree_node * tree);
+static void AndSort (bool_tree_node * and_tree, TermList * tl, CompFunc comp);
+static void AndOrSort (bool_tree_node * tree, TermList * tl);
+static void AndSortDNF (bool_tree_node * or_node, TermList * tl);
+static void MarkOrTerms (bool_tree_node * tree, TermList * tl);
+static int calc_sum_ft (bool_tree_node * term_tree, TermList * tl);
+static int AndOrSort_comp (const void *A, const void *B);
+static int AndSort_comp (const void *A, const void *B);
+
+/* =========================================================================
+ * Function: OptimiseBoolTree
+ * Description: 
+ *      For case 2:
+ *        Do three major steps:
+ *        (i) put into standard form
+ *            -> put into DNF (disjunctive normal form - or of ands)
+ *            Use DeMorgan's, Double-negative, Distributive rules
+ *        (ii) simplify
+ *             apply idempotency rules
+ *        (iii) ameliorate
+ *              convert &! to diff nodes, order terms by frequency,...
+ *     Could also do the matching idempotency laws i.e. ...
+ *     (A | A), (A | !A), (A & !A), (A & A), (A & (A | B)), (A | (A & B)) 
+ *     Job for future.... ;-) 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+void
+OptimiseBoolTree (bool_tree_node * parse_tree, TermList * tl, int type)
+{
+  switch (type)
+    {
+    case 1:
+      /* --- sorts for and of or-terms --- */
+      PermeateNots (parse_tree);
+      TF_Idempotent (parse_tree);
+      CollapseTree (parse_tree);
+      DiffTree (parse_tree);
+      MarkOrTerms (parse_tree, tl);
+      AndOrSort (parse_tree, tl);
+      break;
+    case 2:
+      /* --- put into DNF --- */
+      PermeateNots (parse_tree);
+      TF_Idempotent (parse_tree);
+      DNF_Distribute (parse_tree);
+      CollapseTree (parse_tree);
+      AndSortDNF (parse_tree, tl);
+      DiffDNF (parse_tree);
+      break;
+    default:
+      /* --- do nothing --- */
+      break;
+    }				/*switch */
+}				/*OptimiseBoolTree */
+
+/* =========================================================================
+ * Function: DoubleNeg
+ * Description: 
+ *      !(!(a) = a
+ *      Assumes binary tree.
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+static void
+DoubleNeg (bool_tree_node * not_tree)
+{
+  bool_tree_node *child = BOOL_CHILD (not_tree);
+  bool_tree_node *a = BOOL_CHILD (child);
+  bool_tree_node *sibling = BOOL_SIBLING (not_tree);
+
+  /* copy a into not tree */
+  bcopy (a, not_tree, sizeof (bool_tree_node));
+
+  BOOL_SIBLING (not_tree) = sibling;
+
+  Xfree (child);
+  Xfree (a);
+
+}
+
+/* =========================================================================
+ * Function: AndDeMorgan
+ * Description: 
+ *      DeMorgan's rule for 'not' of an 'and'  i.e. !(a & b) <=> (!a) | (!b)
+ *      Assumes Binary Tree
+ * Input: 
+ *      not of and tree
+ * Output: 
+ *      or of not trees
+ * ========================================================================= */
+
+static void
+AndDeMorgan (bool_tree_node * not_tree)
+{
+  bool_tree_node *child = BOOL_CHILD (not_tree);
+  bool_tree_node *a = BOOL_CHILD (child);
+  bool_tree_node *b = BOOL_SIBLING (a);
+  bool_tree_node *new_not = NULL;
+
+  /* change 'not' to 'or' */
+  BOOL_TAG (not_tree) = N_or;
+
+  /* change 'and' to 'not' */
+  BOOL_TAG (child) = N_not;
+
+  /* 'a' no longer has a sibling */
+  BOOL_SIBLING (a) = NULL;
+
+  /* 'a's old sibling is now a child of a new not */
+  new_not = CreateBoolTreeNode (N_not, b, NULL);
+  BOOL_SIBLING (child) = new_not;
+}
+
+/* =========================================================================
+ * Function: OrDeMorgan
+ * Description: 
+ *      DeMorgan's rule for 'not' of an 'or' i.e. !(a | b) <=> (!a) & (!b)
+ *      Assumes Binary Tree
+ * Input: 
+ *      not of and tree
+ * Output: 
+ *      or of not trees
+ * ========================================================================= */
+
+static void
+OrDeMorgan (bool_tree_node * not_tree)
+{
+  bool_tree_node *child = BOOL_CHILD (not_tree);
+  bool_tree_node *a = BOOL_CHILD (child);
+  bool_tree_node *b = BOOL_SIBLING (a);
+  bool_tree_node *new_not = NULL;
+
+  /* change 'not' to 'and' */
+  BOOL_TAG (not_tree) = N_and;
+
+  /* change 'or' to 'not' */
+  BOOL_TAG (child) = N_not;
+
+  /* 'a' no longer has a sibling */
+  BOOL_SIBLING (a) = NULL;
+
+  /* 'a's old sibling is now a child of a new not */
+  new_not = CreateBoolTreeNode (N_not, b, NULL);
+  BOOL_SIBLING (child) = new_not;
+}
+
+/* =========================================================================
+ * Function: PermeateNots
+ * Description: 
+ *      Use DeMorgan's and Double-negative
+ *      Assumes tree in binary form (i.e. No ands/ors collapsed)
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+PermeateNots (bool_tree_node * tree)
+{
+  if (!tree)
+    return;
+
+  if (BOOL_TAG (tree) == N_not)
+    {
+      switch (BOOL_TAG (BOOL_CHILD (tree)))
+	{
+	case N_not:
+	  DoubleNeg (tree);
+/** NOTE: I do not go on to do the children **/
+	  /* I permeate the nots on the tree here & leave it at that */
+	  /* In this case I do not know what type 'tree' will end up */
+	  PermeateNots (tree);
+	  return;
+	case N_and:
+	  AndDeMorgan (tree);
+	  break;
+	case N_or:
+	  OrDeMorgan (tree);
+	  break;
+	default:
+	  /* leave alone */
+	  break;
+	}
+    }
+
+  /* Permeate Nots for children */
+  if (BOOL_HAS_CHILD (tree))
+    {
+      PermeateNots (BOOL_CHILD (tree));
+      PermeateNots (BOOL_SIBLING (BOOL_CHILD (tree)));
+    }
+
+}
+
+/* =========================================================================
+ * Function: DNF_Distribute
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+
+#define ITER_LIMIT 500		/* if reach limit then probably in trouble */
+
+static void
+DNF_Distribute (bool_tree_node * tree)
+{
+  int i = 0;
+
+  /* multiple passes until no change */
+  /* not very smart :-( */
+  while (1)
+    {
+      if (AndDistribute (tree) == 0)
+	return;
+      if (i == ITER_LIMIT)
+	FatalError (1, "DNF infinite loop");
+      i++;
+    }				/*while */
+
+}
+
+/* =========================================================================
+ * Function: AndDistribute
+ * Description: 
+ *      (a | b) & A <=> (a & A) | (b & A)
+ * Input: 
+ *      binary tree of "AND" , "OR"s.
+ * Output: 
+ *      return 1 if changed the tree
+ *      return 0 if there was NO change (no distributive rule to apply)
+ * ========================================================================= */
+
+static int
+AndDistribute (bool_tree_node * tree)
+{
+  if (!tree)
+    return 0;
+
+  if (BOOL_TAG (tree) != N_and)
+    {
+      /* try the children if got some */
+      if (BOOL_TAG (tree) == N_or)
+	{
+	  bool_tree_node *left_child = BOOL_CHILD (tree);
+	  int left = AndDistribute (left_child);
+	  int right = AndDistribute (BOOL_SIBLING (left_child));
+	  return (left || right);
+	}
+
+      /* no children, then no change */
+      return 0;
+    }
+
+  /* AND case */
+  {
+    /* we have to check the children to see if can distribute */
+    bool_tree_node *left_child = BOOL_CHILD (tree);
+    bool_tree_node *right_child = BOOL_SIBLING (left_child);
+    int swap = 0;
+
+    /* If "or" on the right side then do a swap */
+    /* This is done for code simplicity */
+    if (BOOL_TAG (right_child) == N_or)
+      {
+	/* do a swap */
+	bool_tree_node *temp;
+	temp = right_child;
+	right_child = left_child;
+	left_child = temp;
+
+	BOOL_SIBLING (left_child) = right_child;
+	BOOL_SIBLING (right_child) = NULL;
+	BOOL_CHILD (tree) = left_child;
+
+	swap = 1;
+      }
+
+    /* do the actual distribution */
+    if (swap || BOOL_TAG (left_child) == N_or)
+      {
+	bool_tree_node *A = right_child;
+	bool_tree_node *A_copy = CopyBoolTree (A);
+	bool_tree_node *a = BOOL_CHILD (left_child);
+	bool_tree_node *b = BOOL_SIBLING (a);
+
+	/* then can distribute away ... */
+	BOOL_TAG (tree) = N_or;
+	BOOL_TAG (left_child) = N_and;
+	BOOL_SIBLING (left_child) = CreateBoolTreeNode (N_and, b, A);
+	BOOL_SIBLING (a) = A_copy;
+
+	AndDistribute (tree);
+	return 1;
+      }
+
+    /* if "and" of something other than "or" s then try the children */
+    {
+      int left = AndDistribute (left_child);
+      int right = AndDistribute (right_child);
+      return (left || right);
+    }
+  }				/* AND case */
+
+}				/*AndDistribute */
+
+/* =========================================================================
+ * Function: CollapseTree
+ * Description: 
+ *      Collapse "and" and "or"s.
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+CollapseTree (bool_tree_node * tree)
+{
+  if (!tree)
+    return;
+
+  if ((BOOL_TAG (tree) == N_and) || (BOOL_TAG (tree) == N_or))
+    {
+      bool_tree_node *child = BOOL_CHILD (tree);
+      while (child)
+	{
+	  while (BOOL_TAG (child) == BOOL_TAG (tree))
+	    {
+	      ReplaceWithChildren (child);
+	    }
+	  CollapseTree (child);
+	  child = BOOL_SIBLING (child);
+	}
+    }
+
+  /* assume "not"s permeated */
+  return;
+}
+
+/* =========================================================================
+ * Function: ReplaceWithChildren
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+ReplaceWithChildren (bool_tree_node * tree)
+{
+  bool_tree_node *next = BOOL_SIBLING (tree);
+  bool_tree_node *child = BOOL_CHILD (tree);
+  bool_tree_node *last = LastBoolSibling (child);
+
+  bcopy ((char *) child, (char *) tree, sizeof (bool_tree_node));
+  Xfree (child);
+  BOOL_SIBLING (last) = next;
+
+}
+
+/* =========================================================================
+ * Function: TF_Idempotent
+ * Description: 
+ *      Applies Idempotency laws which refer to True or False (hence "TF")
+ *      uses the true or false idempotent rules
+ * Input: 
+ *      operates on n-ary trees (not restricted to binary)
+ * Output: 
+ * ========================================================================= */
+
+static void
+TF_Idempotent (bool_tree_node * tree)
+{
+  bool_tree_node *child = NULL;
+
+  while (tree)
+    {
+      if (BOOL_HAS_CHILD (tree))
+	{
+	  child = BOOL_CHILD (tree);
+	  TF_Idempotent (child);
+	}
+
+      /* --- process node --- */
+      switch (BOOL_TAG (tree))
+	{
+	case N_not:
+	  child = BOOL_CHILD (tree);
+
+	  /* if true then falsify */
+	  if (BOOL_TAG (child) == N_all)
+	    {
+	      BOOL_TAG (tree) = N_none;
+	      BOOL_CHILD (tree) = NULL;
+	      Xfree (child);
+	      break;
+	    }
+
+	  /* if false then trueify */
+	  if (BOOL_TAG (child) == N_none)
+	    {
+	      BOOL_TAG (tree) = N_all;
+	      BOOL_CHILD (tree) = NULL;
+	      Xfree (child);
+	      break;
+	    }
+
+	  break;
+	case N_and:
+	  AndTrueFalse (tree);
+	  break;
+	case N_or:
+	  OrTrueFalse (tree);
+	  break;
+
+	default:
+	  /* do nothing */
+	  break;
+	}			/*switch */
+
+      tree = BOOL_SIBLING (tree);
+    }				/*while */
+}				/*TF_Idempotent */
+
+/* =========================================================================
+ * Function: AndTrueFalse
+ * Description: 
+ *      If any "false" then falsify whole tree 
+ *      If any "true" then delete them
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+AndTrueFalse (bool_tree_node * and_tree)
+{
+  bool_tree_node *child = BOOL_CHILD (and_tree);
+
+  bool_tree_node *prev = NULL;
+
+  while (child)
+    {
+      if (BOOL_TAG (child) == N_none)
+	{
+	  FreeBoolTree (&(BOOL_CHILD (and_tree)));
+	  BOOL_TAG (and_tree) = N_none;
+	  return;
+	}
+
+      if (BOOL_TAG (child) == N_all)
+	{
+	  bool_tree_node *sibling = BOOL_SIBLING (child);
+
+	  /* --- link over child --- */
+	  if (!prev)
+	    {
+	      BOOL_CHILD (and_tree) = sibling;
+	    }
+	  else
+	    {
+	      BOOL_SIBLING (prev) = sibling;
+	    }
+
+	  Xfree (child);
+	  child = sibling;
+	}
+      else
+	{
+	  prev = child;
+	  child = BOOL_SIBLING (child);
+	}
+    }				/*while */
+
+  child = BOOL_CHILD (and_tree);
+
+  /* if no children ... */
+  /* => all have been true */
+  if (!child)
+    {
+      BOOL_TAG (and_tree) = N_all;
+      return;
+    }
+
+  /* If only one child ... */
+  if (!BOOL_SIBLING (child))
+    {
+      /* replace the parent with child - move it up */
+      bool_tree_node *save_sibling = BOOL_SIBLING (and_tree);
+      bcopy ((char *) child, (char *) and_tree, sizeof (bool_tree_node));
+      BOOL_SIBLING (and_tree) = save_sibling;
+      Xfree (child);
+    }
+
+}				/*AndTrueFalse */
+
+/* =========================================================================
+ * Function: OrTrueFalse
+ * Description: 
+ *      If any "true" then trueify whole tree 
+ *      If any "false" then delete them 
+ *      ***** NOTE: This is a reflection of AndTrueFalse *****
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+OrTrueFalse (bool_tree_node * or_tree)
+{
+  bool_tree_node *child = BOOL_CHILD (or_tree);
+
+  bool_tree_node *prev = NULL;
+
+  while (child)
+    {
+      if (BOOL_TAG (child) == N_all)
+	{
+	  FreeBoolTree (&(BOOL_CHILD (or_tree)));
+	  BOOL_TAG (or_tree) = N_all;
+	  return;
+	}
+
+      if (BOOL_TAG (child) == N_none)
+	{
+	  bool_tree_node *sibling = BOOL_SIBLING (child);
+	  if (!prev)
+	    {
+	      BOOL_CHILD (or_tree) = sibling;
+	    }
+	  else
+	    {
+	      BOOL_SIBLING (prev) = sibling;
+	    }
+	  Xfree (child);
+	  child = sibling;
+
+	}
+      else
+	{
+	  prev = child;
+	  child = BOOL_SIBLING (child);
+	}
+    }				/*while */
+
+  child = BOOL_CHILD (or_tree);
+
+  /* if no children ... */
+  /* => all have been false */
+  if (!child)
+    {
+      BOOL_TAG (or_tree) = N_none;
+      return;
+    }
+
+  /* If only one child ... */
+  if (!BOOL_SIBLING (child))
+    {
+      /* replace the parent with child - move it up */
+      bool_tree_node *save_sibling = BOOL_SIBLING (or_tree);
+      bcopy ((char *) child, (char *) or_tree, sizeof (bool_tree_node));
+      BOOL_SIBLING (or_tree) = save_sibling;
+      Xfree (child);
+    }
+
+}				/*AndTrueFalse */
+
+/* =========================================================================
+ * Function: AndNotToDiff
+ * Description: 
+ *      Convert an "And" tree with possibly some negated terms into
+ *      a "And - neg-terms". 
+ * Input: 
+ *      Expects "And" of only literals - as tree should be in DNF form.
+ *      This means that no recursion is necessary.
+ * Output: 
+ * ========================================================================= */
+
+static void
+AndNotToDiff (bool_tree_node * and_tree, TreeFunc recurs_func)
+{
+
+  /* -------------------------------------------------- */
+  /* --- Divide the children up into positive and negative literals --- */
+  /* Preserves ordering of children */
+  bool_tree_node *pos = NULL;
+  bool_tree_node *neg = NULL;
+  bool_tree_node *last_pos = NULL;
+  bool_tree_node *last_neg = NULL;
+
+  bool_tree_node *child = BOOL_CHILD (and_tree);
+  while (child)
+    {
+      bool_tree_node *next = BOOL_SIBLING (child);
+      if (BOOL_TAG (child) == N_not)
+	{
+	  /* add to end of neg list */
+	  if (!neg)
+	    neg = child;
+	  else
+	    BOOL_SIBLING (last_neg) = child;
+	  last_neg = child;
+	}
+      else
+	{
+	  /* add to end of pos list */
+	  if (!pos)
+	    pos = child;
+	  else
+	    BOOL_SIBLING (last_pos) = child;
+	  last_pos = child;
+	}
+      child = next;
+    }				/*while */
+  if (last_pos)
+    BOOL_SIBLING (last_pos) = NULL;
+  if (last_neg)
+    BOOL_SIBLING (last_neg) = NULL;
+  /* -------------------------------------------------- */
+
+  if (!neg)			/* no negtives => no subtraction */
+    {
+      /* fix up parent's child link */
+      BOOL_CHILD (and_tree) = pos;
+      return;
+    }
+
+  if (!pos)			/* no positives = all negatives */
+    {
+      /* Choose one of the negs for the left-hand-side of the subtraction */
+      /* In particular, choose the first */
+      pos = neg;
+      neg = BOOL_SIBLING (neg);
+      BOOL_SIBLING (pos) = NULL;
+    }
+
+  /* Get rid of all '!' from not nodes */
+  /* Make a list out of the children */
+  {
+    bool_tree_node *n = neg;
+    bool_tree_node *next = NULL;
+
+    neg = BOOL_CHILD (neg);
+    while (n)
+      {
+	bool_tree_node *c = BOOL_CHILD (n);
+	next = BOOL_SIBLING (n);
+	Xfree (n);
+	if (next)
+	  BOOL_SIBLING (c) = BOOL_CHILD (next);
+	n = next;
+      }
+  }
+
+  /* --- restructure the tree with "and" and "diff" --- */
+  BOOL_TAG (and_tree) = N_diff;
+  if (!BOOL_SIBLING (pos))	/* i.e. only one pos */
+    {
+      /* (A & !B & !C & !D & ...) ==> A - (B,C,D,...) */
+
+      BOOL_CHILD (and_tree) = pos;
+      BOOL_SIBLING (pos) = neg;
+    }
+  else
+    {
+      /* (A & !C & B & !D & ...) ==> (A & B & ....) - (C, D, ...) */
+
+      bool_tree_node *n = CreateBoolNode (N_and);
+      BOOL_CHILD (and_tree) = n;
+      BOOL_CHILD (n) = pos;
+      BOOL_SIBLING (n) = neg;
+    }				/*if */
+
+  if (recurs_func)
+    {
+      recurs_func (BOOL_CHILD (and_tree));
+    }
+
+}				/*AndNotToDiff */
+
+/* =========================================================================
+ * Function: DiffTree
+ * Description: 
+ *      Applies "AndNotToNeg" to each conjunct.
+ *      Unlike DiffDNF, this routine will search throughout the tree for
+ *      "and"-nodes. It will call AndNotToNeg with this as its recursive 
+ *      routine.
+ * Date: 27/July/95
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+DiffTree (bool_tree_node * tree)
+{
+  bool_tree_node *t = tree;
+
+  while (t)
+    {
+      if (BOOL_TAG (t) == N_and)
+	{
+	  AndNotToDiff (t, DiffTree);
+	}
+      t = BOOL_SIBLING (t);
+    }				/*while */
+
+}				/*DiffTree */
+
+/* =========================================================================
+ * Function: DiffDNF
+ * Description: 
+ *      Applies "AndNotToNeg" to each conjunct.
+ * Input: 
+ *      A DNF tree
+ * Output: 
+ *      A tree possibly with some diffs in it.
+ * ========================================================================= */
+
+static void
+DiffDNF (bool_tree_node * DNF_tree)
+{
+
+  if (BOOL_TAG (DNF_tree) == N_or)
+    {
+      bool_tree_node *child = BOOL_CHILD (DNF_tree);
+
+      while (child)
+	{
+	  if (BOOL_TAG (child) == N_and)
+	    {
+	      AndNotToDiff (child, NULL);
+	    }
+	  child = BOOL_SIBLING (child);
+	}
+    }
+  else if (BOOL_TAG (DNF_tree) == N_and)
+    {
+      AndNotToDiff (DNF_tree, NULL);
+    }
+}
+
+/* =========================================================================
+ * Function: AndSort_comp 
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+/* Module variable, "term_list",  used as parameter for comparison function */
+/* The comparison function only allows certain fixed parameters */
+static TermList *term_list;
+
+static int
+AndSort_comp (const void *A, const void *B)
+{
+  const bool_tree_node *const *a = A;
+  const bool_tree_node *const *b = B;
+
+  if (BOOL_TAG (*a) == N_term && BOOL_TAG (*b) == N_term)
+    {
+      /* look up in term list */
+      int a_doc_count = GetNthWE (term_list, BOOL_TERM (*a))->doc_count;
+      int b_doc_count = GetNthWE (term_list, BOOL_TERM (*b))->doc_count;
+
+      return a_doc_count - b_doc_count;
+    }
+
+  if (BOOL_TAG (*a) == N_term && BOOL_TAG (*b) != N_term)
+    return -1;
+
+  if (BOOL_TAG (*a) != N_term && BOOL_TAG (*b) == N_term)
+    return 1;
+
+  return 0;
+}				/*AndSort_comp */
+
+/* =========================================================================
+ * Function: AndSort
+ * Description: 
+ *      Sort the list of nodes by increasing doc_count 
+ *      Using some Neil Sharman code - pretty straight forward.
+ *      Note: not-terms are sent to the end of the list
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+AndSort (bool_tree_node * and_tree, TermList * tl, CompFunc comp)
+{
+  bool_tree_node **list = NULL;
+  bool_tree_node *child = NULL;
+  int count = 0;
+  int i = 0;
+
+  if (BOOL_TAG (and_tree) != N_and)
+    return;
+
+  /* --- Convert linked list into an array for sorting --- */
+  child = BOOL_CHILD (and_tree);
+  count = 0;
+  while (child)
+    {
+      count++;
+      child = BOOL_SIBLING (child);
+    }
+
+  if (!(list = Xmalloc (sizeof (bool_tree_node *) * count)))
+    return;
+
+  child = BOOL_CHILD (and_tree);
+  for (i = 0; i < count; i++)
+    {
+      list[i] = child;
+      child = BOOL_SIBLING (child);
+    }
+  /* ----------------------------------------------------- */
+
+  term_list = tl;
+  qsort (list, count, sizeof (bool_tree_node *), comp);
+
+  /* --- Convert array back into linked list --- */
+  for (i = 0; i < count - 1; i++)
+    BOOL_SIBLING (list[i]) = list[i + 1];
+  BOOL_SIBLING (list[count - 1]) = NULL;
+  BOOL_CHILD (and_tree) = list[0];
+  Xfree (list);
+  /* ----------------------------------------------------- */
+
+}				/*AndSort */
+
+/* =========================================================================
+ * Function: AndSortDNF
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+
+static void
+AndSortDNF (bool_tree_node * DNF_tree, TermList * tl)
+{
+
+  if (BOOL_TAG (DNF_tree) == N_or)
+    {
+      bool_tree_node *child = BOOL_CHILD (DNF_tree);
+
+      while (child)
+	{
+	  if (BOOL_TAG (child) == N_and)
+	    {
+	      AndSort (child, tl, AndSort_comp);
+	    }
+	  child = BOOL_SIBLING (child);
+	}
+    }
+  else if (BOOL_TAG (DNF_tree) == N_and)
+    {
+      AndSort (DNF_tree, tl, AndSort_comp);
+    }
+}
+
+/* =========================================================================
+ * Function: MarkOrTerms
+ * Description: 
+ *      Mark or-nodes whose children are all terms.
+ *      Also store the sum of the ft's of these nodes.
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+MarkOrTerms (bool_tree_node * tree, TermList * tl)
+{
+  if (BOOL_TAG (tree) == N_or)
+    {
+      int found_non_term = 0;
+      bool_tree_node *child = BOOL_CHILD (tree);
+
+      /* --- check to see if got all terms --- */
+      while (child)
+	{
+	  if (BOOL_TAG (child) != N_term)
+	    {
+	      found_non_term = 1;
+	    }
+	  if (BOOL_HAS_CHILD (tree))
+	    {
+	      MarkOrTerms (child, tl);
+	    }
+	  child = BOOL_SIBLING (child);
+	}			/*while */
+
+      if (!found_non_term)
+	{
+	  /* Must have all terms for the OR node */
+	  /* So change its tag and calculate its sum */
+	  BOOL_TAG (tree) = N_or_terms;
+	  BOOL_SUM_FT (tree) = calc_sum_ft (tree, tl);
+	}			/*if */
+      /* ------------------------------------- */
+
+    }				/*if OR node */
+
+  else if (BOOL_HAS_CHILD (tree))
+    {
+      bool_tree_node *child = BOOL_CHILD (tree);
+      while (child)
+	{
+	  MarkOrTerms (child, tl);
+	  child = BOOL_SIBLING (child);
+	}
+    }
+
+}				/*MarkOrTerms */
+
+/* =========================================================================
+ * Function: calc_sum_ft
+ * Description: 
+ *      Sums up the ft's of all the terms 
+ * Input: 
+ *      Assumes that the tree only contains terms in it 
+ * Output: 
+ *      the ft sum
+ * ========================================================================= */
+static int
+calc_sum_ft (bool_tree_node * term_tree, TermList * tl)
+{
+  int sum_ft = 0;
+  bool_tree_node *child = BOOL_CHILD (term_tree);
+  while (child)
+    {
+      sum_ft += GetNthWE (tl, BOOL_TERM (child))->doc_count;
+      child = BOOL_SIBLING (child);
+    }
+  return sum_ft;
+}
+
+/* =========================================================================
+ * Function: AndOrSort
+ * Description: 
+ *      This is like an AndSort of just terms. 
+ *      The difference is that we are now also 
+ *      considering sorting with <or of terms> by using the sum of f_t's.
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+static void
+AndOrSort (bool_tree_node * tree, TermList * tl)
+{
+  if (BOOL_HAS_CHILD (tree))
+    {
+
+      if (BOOL_TAG (tree) == N_and)
+	{
+	  AndSort (tree, tl, AndOrSort_comp);
+	}
+
+      /* Check out any children down the tree */
+      /* Probably a waste of time */
+      {
+	bool_tree_node *child = BOOL_CHILD (tree);
+	while (child)
+	  {
+	    AndOrSort (child, tl);
+	    child = BOOL_SIBLING (child);
+	  }
+      }				/*do the tree */
+
+    }				/*if has children */
+}				/*AndOrSort */
+
+/* =========================================================================
+ * Function: AndOrSort_comp
+ * Description: 
+ *      Comparison function used to order "term"s and "or_terms"s.
+ *      It's purpose is to be used by a sort routine.
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+static int
+AndOrSort_comp (const void *A, const void *B)
+{
+  const bool_tree_node *const *a = A;
+  const bool_tree_node *const *b = B;
+
+  if (BOOL_TAG (*a) == N_term && BOOL_TAG (*b) == N_term)
+    {
+      /* look up in term list */
+      int a_doc_count = GetNthWE (term_list, BOOL_TERM (*a))->doc_count;
+      int b_doc_count = GetNthWE (term_list, BOOL_TERM (*b))->doc_count;
+
+      return a_doc_count - b_doc_count;
+    }
+
+  if (BOOL_TAG (*a) == N_term && BOOL_TAG (*b) == N_or_terms)
+    {
+      /* look up in term list */
+      int a_doc_count = GetNthWE (term_list, BOOL_TERM (*a))->doc_count;
+      int b_doc_count = BOOL_SUM_FT (*b);
+
+      return a_doc_count - b_doc_count;
+    }
+
+  if (BOOL_TAG (*a) == N_or_terms && BOOL_TAG (*b) == N_term)
+    {
+      /* look up in term list */
+      int a_doc_count = BOOL_SUM_FT (*a);
+      int b_doc_count = GetNthWE (term_list, BOOL_TERM (*b))->doc_count;
+
+      return a_doc_count - b_doc_count;
+    }
+
+  if (BOOL_TAG (*a) == N_or_terms && BOOL_TAG (*b) == N_or_terms)
+    {
+      /* look up in term list */
+      int a_doc_count = BOOL_SUM_FT (*a);
+      int b_doc_count = BOOL_SUM_FT (*b);
+
+      return a_doc_count - b_doc_count;
+    }
+
+  if ((BOOL_TAG (*a) == N_term || BOOL_TAG (*a) == N_or_terms) &&
+      (BOOL_TAG (*b) != N_term && BOOL_TAG (*b) != N_or_terms))
+    return -1;
+
+  if ((BOOL_TAG (*a) != N_term && BOOL_TAG (*a) != N_or_terms) &&
+      (BOOL_TAG (*b) == N_term || BOOL_TAG (*b) == N_or_terms))
+    return 1;
+
+  return 0;
+}				/*AndOrSort_comp */
Index: /indexers/branches/3.03a/mg/src/text/bool_optimiser.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/bool_optimiser.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/bool_optimiser.h	(revision 14757)
@@ -0,0 +1,65 @@
+/**************************************************************************
+ *
+ * bool_optimiser -- optimise boolean parse tree
+ * Copyright (C) 1994  Tim Shimmin
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:23  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:17:42  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:34:23  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.2  1995/03/14  05:15:21  tes
+   * Updated the boolean query optimiser to do different types of optimisation.
+   * A query environment variable "optimise_type" specifies which one is to be
+   * used. Type 1 is the new one which is faster than 2.
+   *
+   * Revision 1.1  1994/10/20  03:56:32  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/10/18  06:11:03  tes
+   * The boolean optimiser seems to be modifying the parse tree
+   * like it is supposed to.
+   * Paragraph ranking now works without any text files if required to.
+   *
+   * Revision 1.1  1994/10/12  01:15:29  tes
+   * Found bugs in the existing boolean query optimiser.
+   * So decided to rewrite it.
+   * I accidentally deleted query.bool.y, but I have replaced it
+   * with bool_parser.y (which I have forgotten to add here ! ;-(
+   *
+ */
+
+#ifndef BOOL_OPTIMISER_H
+#define BOOL_OPTIMISER_H
+
+#include "bool_tree.h"
+#include "term_lists.h"
+
+void OptimiseBoolTree (bool_tree_node * parse_tree, TermList * term_list, int type);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/bool_parser.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/bool_parser.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/bool_parser.c	(revision 14757)
@@ -0,0 +1,1196 @@
+
+/*  A Bison parser, made from bool_parser.y
+ by  GNU Bison version 1.27
+  */
+
+#define YYBISON 1  /* Identify Bison output.  */
+
+#define	TERM	257
+
+#line 24 "bool_parser.y"
+
+ 
+#include "sysfuncs.h"
+
+#include "messages.h"
+ 
+#include "memlib.h"
+#include "words.h"
+#include "stemmer.h"
+#include "term_lists.h"
+#include "bool_tree.h"
+/* [RPAP - Jan 97: Stem Index Change] */
+#include "backend.h"     /* for stemmed_dict def */
+#include "stem_search.h"
+
+#include "query_term_list.h"  /* [RPAP - Feb 97: Term Frequency] */
+
+/* --- routines --- */
+static int query_lex();
+static int yyerror(char *);
+#define yylex() query_lex(&ch_buf, end_buf)
+ 
+/* --- module variables --- */
+static char *ch_buf; /* ptr to the character query line buffer */
+static char *end_buf; /* ptr to the last character of the line buffer */
+static bool_tree_node *tree_base = NULL;
+static TermList **term_list;
+static int stemmer_num;
+static int stem_method;
+/* [RPAP - Jan 97: Stem Index Change] */
+stemmed_dict *p__sd;
+static int indexed;
+/* [RPAP - Feb 97: Term Frequency] */
+static QueryTermList **query_term_list;
+static int word_num;
+static u_long count;
+static u_long doc_count;
+static u_long invf_ptr;
+static u_long invf_len;
+
+#line 66 "bool_parser.y"
+typedef union {
+  char *text;
+  bool_tree_node *node;
+} YYSTYPE;
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define	YYFINAL		20
+#define	YYFLAG		-32768
+#define	YYNTBASE	11
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 257 ? yytranslate[x] : 16)
+
+static const char yytranslate[] = {     0,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     8,     2,     2,     2,     2,     9,     2,     4,
+     5,     6,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     7,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,    10,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     1,     3
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = {     0,
+     0,     2,     4,     8,    10,    12,    14,    17,    21,    24,
+    26,    30
+};
+
+static const short yyrhs[] = {    15,
+     0,     3,     0,     4,    15,     5,     0,     6,     0,     7,
+     0,    12,     0,     8,    13,     0,    14,     9,    13,     0,
+    14,    13,     0,    13,     0,    15,    10,    14,     0,    14,
+     0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+    76,    80,    81,    82,    83,    86,    87,    90,    91,    92,
+    95,    96
+};
+#endif
+
+
+#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
+
+static const char * const yytname[] = {   "$","error","$undefined.","TERM","'('",
+"')'","'*'","'_'","'!'","'&'","'|'","query","term","not","and","or", NULL
+};
+#endif
+
+static const short yyr1[] = {     0,
+    11,    12,    12,    12,    12,    13,    13,    14,    14,    14,
+    15,    15
+};
+
+static const short yyr2[] = {     0,
+     1,     1,     3,     1,     1,     1,     2,     3,     2,     1,
+     3,     1
+};
+
+static const short yydefact[] = {     0,
+     2,     0,     4,     5,     0,     6,    10,    12,     1,     0,
+     7,     0,     9,     0,     3,     8,    11,     0,     0,     0
+};
+
+static const short yydefgoto[] = {    18,
+     6,     7,     8,     9
+};
+
+static const short yypact[] = {    10,
+-32768,    10,-32768,-32768,    10,-32768,-32768,     2,    -9,    14,
+-32768,    10,-32768,    10,-32768,-32768,     2,     4,    15,-32768
+};
+
+static const short yypgoto[] = {-32768,
+-32768,    -5,   -12,    18
+};
+
+
+#define	YYLAST		24
+
+
+static const short yytable[] = {    11,
+    14,    17,    13,    19,     1,     2,    16,     3,     4,     5,
+    12,    13,     1,     2,    20,     3,     4,     5,    15,    10,
+     0,     0,     0,    14
+};
+
+static const short yycheck[] = {     5,
+    10,    14,     8,     0,     3,     4,    12,     6,     7,     8,
+     9,    17,     3,     4,     0,     6,     7,     8,     5,     2,
+    -1,    -1,    -1,    10
+};
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "/usr/lib/bison.simple"
+/* This file comes from bison-1.27.  */
+
+/* Skeleton output parser for bison,
+   Copyright (C) 1984, 1989, 1990 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 program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* This is the parser code that is written into each bison parser
+  when the %semantic_parser declaration is not specified in the grammar.
+  It was written by Richard Stallman by simplifying the hairy parser
+  used when %semantic_parser is specified.  */
+
+#ifndef YYSTACK_USE_ALLOCA
+#ifdef alloca
+#define YYSTACK_USE_ALLOCA
+#else /* alloca not defined */
+#ifdef __GNUC__
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#else /* not GNU C.  */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+#define YYSTACK_USE_ALLOCA
+#include <alloca.h>
+#else /* not sparc */
+/* We think this test detects Watcom and Microsoft C.  */
+/* This used to test MSDOS, but that is a bad idea
+   since that symbol is in the user namespace.  */
+#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+#if 0 /* No need for malloc.h, which pollutes the namespace;
+	 instead, just don't use alloca.  */
+#include <malloc.h>
+#endif
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+/* I don't know what this was needed for, but it pollutes the namespace.
+   So I turned it off.   rms, 2 May 1997.  */
+/* #include <malloc.h>  */
+ #pragma alloca
+#define YYSTACK_USE_ALLOCA
+#else /* not MSDOS, or __TURBOC__, or _AIX */
+#if 0
+#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+		 and on HPUX 10.  Eventually we can turn this on.  */
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#endif /* __hpux */
+#endif
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc */
+#endif /* not GNU C */
+#endif /* alloca not defined */
+#endif /* YYSTACK_USE_ALLOCA not defined */
+
+#ifdef YYSTACK_USE_ALLOCA
+#define YYSTACK_ALLOC alloca
+#else
+#define YYSTACK_ALLOC malloc
+#endif
+
+/* Note: there must be only one dollar sign in this file.
+   It is replaced by the list of actions, each action
+   as one case of the switch.  */
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		-2
+#define YYEOF		0
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT 	goto yyabortlab
+#define YYERROR		goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+   This remains here temporarily to ease the
+   transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYFAIL		goto yyerrlab
+#define YYRECOVERING()  (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    { yychar = (token), yylval = (value);			\
+      yychar1 = YYTRANSLATE (yychar);				\
+      YYPOPSTACK;						\
+      goto yybackup;						\
+    }								\
+  else								\
+    { yyerror ("syntax error: cannot back up"); YYERROR; }	\
+while (0)
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+#ifndef YYPURE
+#define YYLEX		yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX		yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX		yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX		yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX		yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int	yychar;			/*  the lookahead symbol		*/
+YYSTYPE	yylval;			/*  the semantic value of the		*/
+				/*  lookahead symbol			*/
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc;			/*  location data for the lookahead	*/
+				/*  symbol				*/
+#endif
+
+int yynerrs;			/*  number of parse errors so far       */
+#endif  /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug;			/*  nonzero means print parse trace	*/
+/* Since this is uninitialized, it does not stop multiple parsers
+   from coexisting.  */
+#endif
+
+/*  YYINITDEPTH indicates the initial size of the parser's stacks	*/
+
+#ifndef	YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/*  YYMAXDEPTH is the maximum size the stacks can grow to
+    (effective only if the built-in stack extension method is used).  */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+
+/* Define __yy_memcpy.  Note that the size argument
+   should be passed with type unsigned int, because that is what the non-GCC
+   definitions require.  With GCC, __builtin_memcpy takes an arg
+   of type size_t, but it can handle unsigned int.  */
+
+#if __GNUC__ > 1		/* GNU C and GNU C++ define this.  */
+#define __yy_memcpy(TO,FROM,COUNT)	__builtin_memcpy(TO,FROM,COUNT)
+#else				/* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+__yy_memcpy (to, from, count)
+     char *to;
+     char *from;
+     unsigned int count;
+{
+  register char *f = from;
+  register char *t = to;
+  register int i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+__yy_memcpy (char *to, char *from, unsigned int count)
+{
+  register char *t = to;
+  register char *f = from;
+  register int i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#endif
+#endif
+
+
+#line 216 "/usr/lib/bison.simple"
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+#ifdef __cplusplus
+#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#else /* not __cplusplus */
+#define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#endif /* not __cplusplus */
+#else /* not YYPARSE_PARAM */
+#define YYPARSE_PARAM_ARG
+#define YYPARSE_PARAM_DECL
+#endif /* not YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+#ifdef YYPARSE_PARAM
+int yyparse (void *);
+#else
+int yyparse (void);
+#endif
+#endif
+
+int
+yyparse(YYPARSE_PARAM_ARG)
+     YYPARSE_PARAM_DECL
+{
+  register int yystate;
+  register int yyn;
+  register short *yyssp;
+  register YYSTYPE *yyvsp;
+  int yyerrstatus;	/*  number of tokens to shift before error messages enabled */
+  int yychar1 = 0;		/*  lookahead token as an internal (translated) token number */
+
+  short	yyssa[YYINITDEPTH];	/*  the state stack			*/
+  YYSTYPE yyvsa[YYINITDEPTH];	/*  the semantic value stack		*/
+
+  short *yyss = yyssa;		/*  refer to the stacks thru separate pointers */
+  YYSTYPE *yyvs = yyvsa;	/*  to allow yyoverflow to reallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+  YYLTYPE yylsa[YYINITDEPTH];	/*  the location stack			*/
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+
+#define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK   (yyvsp--, yyssp--)
+#endif
+
+  int yystacksize = YYINITDEPTH;
+  int yyfree_stacks = 0;
+
+#ifdef YYPURE
+  int yychar;
+  YYSTYPE yylval;
+  int yynerrs;
+#ifdef YYLSP_NEEDED
+  YYLTYPE yylloc;
+#endif
+#endif
+
+  YYSTYPE yyval;		/*  the variable used to return		*/
+				/*  semantic values from the action	*/
+				/*  routines				*/
+
+  int yylen;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Starting parse\n");
+#endif
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss - 1;
+  yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+  yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in  yystate  .  */
+/* In all cases, when you get here, the value and location stacks
+   have just been pushed. so pushing a state here evens the stacks.  */
+yynewstate:
+
+  *++yyssp = yystate;
+
+  if (yyssp >= yyss + yystacksize - 1)
+    {
+      /* Give user a chance to reallocate the stack */
+      /* Use copies of these so that the &'s don't force the real ones into memory. */
+      YYSTYPE *yyvs1 = yyvs;
+      short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+      YYLTYPE *yyls1 = yyls;
+#endif
+
+      /* Get the current used size of the three stacks, in elements.  */
+      int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      /* Each stack pointer address is followed by the size of
+	 the data in use in that stack, in bytes.  */
+#ifdef YYLSP_NEEDED
+      /* This used to be a conditional around just the two extra args,
+	 but that might be undefined if yyoverflow is a macro.  */
+      yyoverflow("parser stack overflow",
+		 &yyss1, size * sizeof (*yyssp),
+		 &yyvs1, size * sizeof (*yyvsp),
+		 &yyls1, size * sizeof (*yylsp),
+		 &yystacksize);
+#else
+      yyoverflow("parser stack overflow",
+		 &yyss1, size * sizeof (*yyssp),
+		 &yyvs1, size * sizeof (*yyvsp),
+		 &yystacksize);
+#endif
+
+      yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+      yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+	{
+	  yyerror("parser stack overflow");
+	  if (yyfree_stacks)
+	    {
+	      free (yyss);
+	      free (yyvs);
+#ifdef YYLSP_NEEDED
+	      free (yyls);
+#endif
+	    }
+	  return 2;
+	}
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+	yystacksize = YYMAXDEPTH;
+#ifndef YYSTACK_USE_ALLOCA
+      yyfree_stacks = 1;
+#endif
+      yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+      __yy_memcpy ((char *)yyss, (char *)yyss1,
+		   size * (unsigned int) sizeof (*yyssp));
+      yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+      __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+		   size * (unsigned int) sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+      yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+      __yy_memcpy ((char *)yyls, (char *)yyls1,
+		   size * (unsigned int) sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + size - 1;
+      yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+      yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+      if (yyssp >= yyss + yystacksize - 1)
+	YYABORT;
+    }
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+  goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Reading a token: ");
+#endif
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)		/* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;		/* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Now at end of input.\n");
+#endif
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+      if (yydebug)
+	{
+	  fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+	  /* Give the individual parser a way to print the precise meaning
+	     of a token, for further debugging info.  */
+#ifdef YYPRINT
+	  YYPRINT (stderr, yychar, yylval);
+#endif
+	  fprintf (stderr, ")\n");
+	}
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* count tokens shifted since error; after three, turn off error status.  */
+  if (yyerrstatus) yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+/* Do the default action for the current state.  */
+yydefault:
+
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+
+/* Do a reduction.  yyn is the number of a rule to reduce with.  */
+yyreduce:
+  yylen = yyr2[yyn];
+  if (yylen > 0)
+    yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      int i;
+
+      fprintf (stderr, "Reducing via rule %d (line %d), ",
+	       yyn, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+	fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+      fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+
+
+  switch (yyn) {
+
+case 1:
+#line 76 "bool_parser.y"
+{ tree_base = yyvsp[0].node;;
+    break;}
+case 2:
+#line 80 "bool_parser.y"
+{ yyval.node = CreateBoolTermNode(term_list, yyvsp[0].text, 1, word_num, count, doc_count, invf_ptr, invf_len, stemmer_num); ;
+    break;}
+case 3:
+#line 81 "bool_parser.y"
+{ yyval.node = yyvsp[-1].node; ;
+    break;}
+case 4:
+#line 82 "bool_parser.y"
+{ yyval.node = CreateBoolTreeNode(N_all, NULL, NULL); ;
+    break;}
+case 5:
+#line 83 "bool_parser.y"
+{ yyval.node = CreateBoolTreeNode(N_none, NULL, NULL); ;
+    break;}
+case 7:
+#line 87 "bool_parser.y"
+{ yyval.node = CreateBoolTreeNode(N_not, yyvsp[0].node, NULL); ;
+    break;}
+case 8:
+#line 90 "bool_parser.y"
+{ yyval.node = CreateBoolTreeNode(N_and, yyvsp[-2].node, yyvsp[0].node); ;
+    break;}
+case 9:
+#line 91 "bool_parser.y"
+{ yyval.node = CreateBoolTreeNode(N_and, yyvsp[-1].node, yyvsp[0].node); ;
+    break;}
+case 11:
+#line 95 "bool_parser.y"
+{ yyval.node = CreateBoolTreeNode(N_or, yyvsp[-2].node, yyvsp[0].node); ;
+    break;}
+}
+   /* the action file gets copied in in place of this dollarsign */
+#line 542 "/usr/lib/bison.simple"
+
+
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "state stack now");
+      while (ssp1 != yyssp)
+	fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+  yylsp++;
+  if (yylen == 0)
+    {
+      yylsp->first_line = yylloc.first_line;
+      yylsp->first_column = yylloc.first_column;
+      yylsp->last_line = (yylsp-1)->last_line;
+      yylsp->last_column = (yylsp-1)->last_column;
+      yylsp->text = 0;
+    }
+  else
+    {
+      yylsp->last_line = (yylsp+yylen-1)->last_line;
+      yylsp->last_column = (yylsp+yylen-1)->last_column;
+    }
+#endif
+
+  /* Now "shift" the result of the reduction.
+     Determine what state that goes to,
+     based on the state we popped back to
+     and the rule number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+yyerrlab:   /* here on detecting error */
+
+  if (! yyerrstatus)
+    /* If not already recovering from an error, report this error.  */
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (yyn > YYFLAG && yyn < YYLAST)
+	{
+	  int size = 0;
+	  char *msg;
+	  int x, count;
+
+	  count = 0;
+	  /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */
+	  for (x = (yyn < 0 ? -yyn : 0);
+	       x < (sizeof(yytname) / sizeof(char *)); x++)
+	    if (yycheck[x + yyn] == x)
+	      size += strlen(yytname[x]) + 15, count++;
+	  msg = (char *) malloc(size + 15);
+	  if (msg != 0)
+	    {
+	      strcpy(msg, "parse error");
+
+	      if (count < 5)
+		{
+		  count = 0;
+		  for (x = (yyn < 0 ? -yyn : 0);
+		       x < (sizeof(yytname) / sizeof(char *)); x++)
+		    if (yycheck[x + yyn] == x)
+		      {
+			strcat(msg, count == 0 ? ", expecting `" : " or `");
+			strcat(msg, yytname[x]);
+			strcat(msg, "'");
+			count++;
+		      }
+		}
+	      yyerror(msg);
+	      free(msg);
+	    }
+	  else
+	    yyerror ("parse error; also virtual memory exceeded");
+	}
+      else
+#endif /* YYERROR_VERBOSE */
+	yyerror("parse error");
+    }
+
+  goto yyerrlab1;
+yyerrlab1:   /* here on error raised explicitly by an action */
+
+  if (yyerrstatus == 3)
+    {
+      /* if just tried and failed to reuse lookahead token after an error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+	YYABORT;
+
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token
+     after shifting the error token.  */
+
+  yyerrstatus = 3;		/* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+yyerrdefault:  /* current state does not do anything special for the error token. */
+
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+  yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
+  if (yyn) goto yydefault;
+#endif
+
+yyerrpop:   /* pop the current state because it cannot handle the error token */
+
+  if (yyssp == yyss) YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "Error: state stack now");
+      while (ssp1 != yyssp)
+	fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+yyerrhandle:
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting error token, ");
+#endif
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+
+ yyacceptlab:
+  /* YYACCEPT comes here.  */
+  if (yyfree_stacks)
+    {
+      free (yyss);
+      free (yyvs);
+#ifdef YYLSP_NEEDED
+      free (yyls);
+#endif
+    }
+  return 0;
+
+ yyabortlab:
+  /* YYABORT comes here.  */
+  if (yyfree_stacks)
+    {
+      free (yyss);
+      free (yyvs);
+#ifdef YYLSP_NEEDED
+      free (yyls);
+#endif
+    }
+  return 1;
+}
+#line 99 "bool_parser.y"
+
+ 
+/* Bison on one mips machine defined "const" to be nothing but
+   then did not undef it */
+#ifdef const
+#undef const
+#endif
+
+/**************************************************************************/ 
+
+
+/* =========================================================================
+ * Function: query_lex
+ * Description:
+ *      Hand written lexical analyser for the parser.
+ * Input:
+ *      ptr = ptr to a ptr into character query-line buffer
+ *      end = ptr to last char in buffer
+ * Output:
+ *      yylval.text = the token's text
+ * Notes:
+ *      does NOT produce WILD tokens at the moment
+ * ========================================================================= */
+ 
+/* [RPAP - Jan 97: Stem Index Change]
+   state mode:
+      0 = Read next token
+      1 = Output word
+      2 = Output '|' or ')'
+ */
+static int query_lex(char **ptr, const char *end)
+{
+  char *buf_ptr = *ptr;
+  static int mode = 0;
+  static int termnum = 0;
+  static TermList *Terms = NULL;
+
+  if (mode == 0)
+    {
+      /* jump over whitespace */
+      buf_ptr = skipspace(buf_ptr, end);
+ 
+      if (inaword(buf_ptr, end))
+	{
+	  static char word[MAXSTEMLEN + 1]; /* [RJM 07/98: Memory Leak] */
+	  char *sWord = Xmalloc(MAXSTEMLEN + 1);
+	  int stem_to_apply, method_using = -1;
+
+	  PARSE_STEM_WORD(word, buf_ptr, end);
+
+	  /* Extract any parameters */
+	  stem_to_apply = stem_method;
+	  while (buf_ptr <= end)
+	    {
+	      int stem_param, param_type;
+	      char param[MAXPARAMLEN + 1];
+
+	      param_type = 0;
+	      PARSE_OPT_TERM_PARAM (param, param_type, buf_ptr, end);
+	      if (!param_type)
+		break;
+
+	      if (param_type == STEMPARAM)
+		{
+		  stem_param = atoi (param);
+		  if (errno != ERANGE && indexed && stem_param >= 0 && stem_param <= 3)
+		    method_using = stem_to_apply = stem_param;
+		}
+	    }
+
+	  bcopy ((char *) word, (char *) sWord, *word + 1);
+	  stemmer (stem_to_apply, stemmer_num, sWord);
+
+	  if (stem_to_apply == 0 || !indexed || p__sd == NULL)
+	    {
+	      /* [RPAP - Feb 97: Term Frequency] */
+	      word_num = FindWord (p__sd, sWord, &count, &doc_count, &invf_ptr, &invf_len);
+	      if (word_num == -1)
+		count = doc_count = invf_ptr = invf_len = 0;
+	      AddQueryTerm (query_term_list, (u_char *) word, count, method_using);
+
+	      yylval.text = word;
+	      *ptr = buf_ptr; /* fix up ptr */
+	      Xfree (sWord);
+	      return TERM;
+	    }
+	  else
+	    {
+	      *ptr = buf_ptr; /* fix up ptr */
+	      termnum = 0;
+	      ResetTermList (&Terms);
+	      if (FindWords (p__sd, (u_char *) sWord, stem_to_apply, &Terms) > 0)
+		{
+		  /* [RPAP - Feb 97: Term Frequency] */ 
+		  int i, freq = 0;
+		  for (i = 0; i < Terms->num; i++)
+		    freq += Terms->TE[i].WE.count;
+		  AddQueryTerm (query_term_list, word, freq, method_using);
+
+		  Xfree (sWord);
+		  mode = 1;
+		  return '(';
+		}
+	      else
+		{
+		  /* Word does not exists - include in tree anyway */
+		  Xfree (sWord);
+
+		  /* [RPAP - Feb 97: Term Frequency] */
+		  word_num = -1;
+		  count = doc_count = invf_ptr = invf_len = 0;
+		  AddQueryTerm (query_term_list, (u_char *) word, count, method_using);
+
+		  yylval.text = word;
+		  return TERM;
+		}
+	    }
+	}
+      else /* NON-WORD */
+	{
+	  if (*buf_ptr == '\0')
+	    {
+	      /* return null-char if it is one */
+	      *ptr = buf_ptr; /* fix up ptr */
+	      return 0;
+	    }
+	  else
+	    {
+	      /* return 1st char, and delete from buffer */
+	      char c = *buf_ptr++;
+	      *ptr = buf_ptr; /* fix up ptr */
+	      return c;
+	    }
+	}
+    }
+  else if (mode == 1)
+    {
+      yylval.text = Terms->TE[termnum].Word;
+      
+      /* [RPAP - Feb 97: Term Frequency] */
+      word_num = Terms->TE[termnum].WE.word_num;
+      count = Terms->TE[termnum].WE.count;
+      doc_count = Terms->TE[termnum].WE.doc_count;
+      invf_ptr = Terms->TE[termnum].WE.invf_ptr;
+      invf_len = Terms->TE[termnum].WE.invf_len;
+
+      termnum++;
+      mode = 2;
+      return TERM;
+    }
+  else  /* mode == 2 */
+    {
+      if (termnum >= Terms->num)
+	{
+	  mode = 0;
+	  return ')';
+	}
+      else
+	{
+	  mode = 1;
+	  return '|';
+	}
+    }
+}/*query_lex*/
+
+/* =========================================================================
+ * Function: yyerror
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */ 
+static int yyerror(char *s)
+{
+  Message("%s", s);
+  return(1);
+}
+
+ 
+/* =========================================================================
+ * Function: ParseBool
+ * Description:
+ *      Parse a boolean query string into a term-list and a boolean parse tree
+ * Input:
+ *      query_line = query line string
+ *      query_len = query line length
+ *      the_stem_method = stem method id used for stemming
+ * Output:
+ *      the_term_list = the list of terms
+ *      res = parser result code
+ * ========================================================================= */
+ 
+bool_tree_node *
+ParseBool(char *query_line, int query_len,
+          TermList **the_term_list, int the_stemmer_num, int the_stem_method, int *res,
+	  stemmed_dict * the_sd, int is_indexed,   /* [RPAP - Jan 97: Stem Index Change] */
+	  QueryTermList **the_query_term_list)  /* [RPAP - Feb 97: Term Frequency] */
+{
+  /* global variables to be accessed by bison/yacc created parser */
+  term_list = the_term_list;
+  stemmer_num = the_stemmer_num;
+  stem_method = the_stem_method;
+  ch_buf = query_line;
+  end_buf = query_line + query_len;
+  p__sd = the_sd;   /* [RPAP - Jan 97: Stem Index Change] */
+  indexed = is_indexed;  /* [RPAP - Jan 97: Stem Index Change] */
+  query_term_list = the_query_term_list; /* [RPAP - Feb 97: Term Frequency] */
+
+  FreeBoolTree(&(tree_base));
+ 
+  ResetTermList(term_list);
+  ResetQueryTermList(query_term_list);  /* [RPAP - Feb 97: Term Frequency] */
+
+  *res = yyparse();
+ 
+  return tree_base;
+}
+ 
+
Index: /indexers/branches/3.03a/mg/src/text/bool_parser.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/bool_parser.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/bool_parser.h	(revision 14757)
@@ -0,0 +1,70 @@
+/**************************************************************************
+ *
+ * filename -- description
+ * Copyright (C) 1994  Authors
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:23  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:17:43  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:40  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:34:26  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.1  1994/10/20  03:56:33  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.1  1994/10/12  01:15:31  tes
+   * Found bugs in the existing boolean query optimiser.
+   * So decided to rewrite it.
+   * I accidentally deleted query.bool.y, but I have replaced it
+   * with bool_parser.y (which I have forgotten to add here ! ;-(
+   *
+ */
+
+#ifndef BOOL_PARSER_H
+#define BOOL_PARSER_H
+
+#include "backend.h"
+#include "term_lists.h"
+#include "invf.h"
+
+bool_tree_node *ParseBool (char *query_line, int query_len,
+			   TermList ** the_term_list, int the_stemmer_num, 
+			   int the_stem_method, int *res,
+			   stemmed_dict * the_sd, int is_indexed,  /* [RPAP - Jan 97: Stem Index Change] */
+			   QueryTermList ** the_query_term_list);  /* [RPAP - Feb 97: Term Frequency] */
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/bool_parser.y
===================================================================
--- /indexers/branches/3.03a/mg/src/text/bool_parser.y	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/bool_parser.y	(revision 14757)
@@ -0,0 +1,316 @@
+/**************************************************************************
+ *
+ * bool_parser - boolean query parser
+ * Copyright (C) 1994  Neil Sharman & Tim Shimmin
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************/
+ 
+/**************************************************************************/
+%{
+ 
+#include "sysfuncs.h"
+
+#include "messages.h"
+ 
+#include "memlib.h"
+#include "words.h"
+#include "stemmer.h"
+#include "term_lists.h"
+#include "bool_tree.h"
+/* [RPAP - Jan 97: Stem Index Change] */
+#include "backend.h"     /* for stemmed_dict def */
+#include "stem_search.h"
+
+#include "query_term_list.h"  /* [RPAP - Feb 97: Term Frequency] */
+
+/* --- routines --- */
+static int query_lex();
+static int yyerror(char *);
+#define yylex() query_lex(&ch_buf, end_buf)
+ 
+/* --- module variables --- */
+static char *ch_buf; /* ptr to the character query line buffer */
+static char *end_buf; /* ptr to the last character of the line buffer */
+static bool_tree_node *tree_base = NULL;
+static TermList **term_list;
+static int stemmer_num;
+static int stem_method;
+/* [RPAP - Jan 97: Stem Index Change] */
+stemmed_dict *p__sd;
+static int indexed;
+/* [RPAP - Feb 97: Term Frequency] */
+static QueryTermList **query_term_list;
+static int word_num;
+static u_long count;
+static u_long doc_count;
+static u_long invf_ptr;
+static u_long invf_len;
+%}
+ 
+ 
+%union {
+  char *text;
+  bool_tree_node *node;
+}
+ 
+%token <text> TERM
+%type <node> query term not and or
+ 
+%%
+ 
+query: or  { tree_base = $1;}
+;
+ 
+ 
+term:     TERM  { $$ = CreateBoolTermNode(term_list, $1, 1, word_num, count, doc_count, invf_ptr, invf_len, stemmer_num); }
+        | '(' or ')' { $$ = $2; }
+        | '*' { $$ = CreateBoolTreeNode(N_all, NULL, NULL); }
+        | '_' { $$ = CreateBoolTreeNode(N_none, NULL, NULL); }
+;
+ 
+not:      term
+        | '!' not { $$ = CreateBoolTreeNode(N_not, $2, NULL); }
+;
+ 
+and:      and '&' not { $$ = CreateBoolTreeNode(N_and, $1, $3); }
+        | and not { $$ = CreateBoolTreeNode(N_and, $1, $2); }
+        | not
+;
+ 
+or:       or '|' and { $$ = CreateBoolTreeNode(N_or, $1, $3); }
+        | and
+;
+ 
+%%
+ 
+/* Bison on one mips machine defined "const" to be nothing but
+   then did not undef it */
+#ifdef const
+#undef const
+#endif
+
+/**************************************************************************/ 
+
+
+/* =========================================================================
+ * Function: query_lex
+ * Description:
+ *      Hand written lexical analyser for the parser.
+ * Input:
+ *      ptr = ptr to a ptr into character query-line buffer
+ *      end = ptr to last char in buffer
+ * Output:
+ *      yylval.text = the token's text
+ * Notes:
+ *      does NOT produce WILD tokens at the moment
+ * ========================================================================= */
+ 
+/* [RPAP - Jan 97: Stem Index Change]
+   state mode:
+      0 = Read next token
+      1 = Output word
+      2 = Output '|' or ')'
+ */
+static int query_lex(char **ptr, const char *end)
+{
+  char *buf_ptr = *ptr;
+  static int mode = 0;
+  static int termnum = 0;
+  static TermList *Terms = NULL;
+
+  if (mode == 0)
+    {
+      /* jump over whitespace */
+      buf_ptr = skipspace(buf_ptr, end);
+
+      if (inaword(buf_ptr, end))
+	{
+	  static char word[MAXSTEMLEN + 1]; /* [RJM 07/98: Memory Leak] */
+	  char *sWord = Xmalloc(MAXSTEMLEN + 1);
+	  int stem_to_apply, method_using = -1;
+
+	  PARSE_STEM_WORD(word, buf_ptr, end);
+
+	  /* Extract any parameters */
+	  stem_to_apply = stem_method;
+	  while (buf_ptr <= end)
+	    {
+	      int stem_param, param_type;
+	      char param[MAXPARAMLEN + 1];
+
+	      param_type = 0;
+	      PARSE_OPT_TERM_PARAM (param, param_type, buf_ptr, end);
+	      if (!param_type)
+		break;
+
+	      if (param_type == STEMPARAM)
+		{
+		  stem_param = atoi (param);
+		  if (errno != ERANGE && indexed && stem_param >= 0 && stem_param <= 3)
+		    method_using = stem_to_apply = stem_param;
+		}
+	    }
+
+	  bcopy ((char *) word, (char *) sWord, *word + 1);
+	  stemmer (stem_to_apply, stemmer_num, sWord);
+
+	  if (stem_to_apply == 0 || !indexed || p__sd == NULL)
+	    {
+	      /* [RPAP - Feb 97: Term Frequency] */
+	      word_num = FindWord (p__sd, sWord, &count, &doc_count, &invf_ptr, &invf_len);
+	      if (word_num == -1)
+		count = doc_count = invf_ptr = invf_len = 0;
+	      AddQueryTerm (query_term_list, (u_char *) word, count, method_using);
+
+	      yylval.text = word;
+	      *ptr = buf_ptr; /* fix up ptr */
+	      Xfree (sWord);
+	      return TERM;
+	    }
+	  else
+	    {
+	      *ptr = buf_ptr; /* fix up ptr */
+	      termnum = 0;
+	      ResetTermList (&Terms);
+	      if (FindWords (p__sd, (u_char *) sWord, stem_to_apply, &Terms) > 0)
+		{
+		  /* [RPAP - Feb 97: Term Frequency] */ 
+		  int i, freq = 0;
+		  for (i = 0; i < Terms->num; i++)
+		    freq += Terms->TE[i].WE.count;
+		  AddQueryTerm (query_term_list, word, freq, method_using);
+
+		  Xfree (sWord);
+		  mode = 1;
+		  return '(';
+		}
+	      else
+		{
+		  /* Word does not exists - include in tree anyway */
+		  Xfree (sWord);
+
+		  /* [RPAP - Feb 97: Term Frequency] */
+		  word_num = -1;
+		  count = doc_count = invf_ptr = invf_len = 0;
+		  AddQueryTerm (query_term_list, (u_char *) word, count, method_using);
+
+		  yylval.text = word;
+		  return TERM;
+		}
+	    }
+	}
+      else /* NON-WORD */
+	{
+	  if (*buf_ptr == '\0')
+	    {
+	      /* return null-char if it is one */
+	      *ptr = buf_ptr; /* fix up ptr */
+	      return 0;
+	    }
+	  else
+	    {
+	      /* return 1st char, and delete from buffer */
+	      char c = *buf_ptr++;
+	      *ptr = buf_ptr; /* fix up ptr */
+	      return c;
+	    }
+	}
+    }
+  else if (mode == 1)
+    {
+      yylval.text = Terms->TE[termnum].Word;
+      
+      /* [RPAP - Feb 97: Term Frequency] */
+      word_num = Terms->TE[termnum].WE.word_num;
+      count = Terms->TE[termnum].WE.count;
+      doc_count = Terms->TE[termnum].WE.doc_count;
+      invf_ptr = Terms->TE[termnum].WE.invf_ptr;
+      invf_len = Terms->TE[termnum].WE.invf_len;
+
+      termnum++;
+      mode = 2;
+      return TERM;
+    }
+  else  /* mode == 2 */
+    {
+      if (termnum >= Terms->num)
+	{
+	  mode = 0;
+	  return ')';
+	}
+      else
+	{
+	  mode = 1;
+	  return '|';
+	}
+    }
+}/*query_lex*/
+
+/* =========================================================================
+ * Function: yyerror
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */ 
+static int yyerror(char *s)
+{
+  Message("%s", s);
+  return(1);
+}
+
+ 
+/* =========================================================================
+ * Function: ParseBool
+ * Description:
+ *      Parse a boolean query string into a term-list and a boolean parse tree
+ * Input:
+ *      query_line = query line string
+ *      query_len = query line length
+ *      the_stem_method = stem method id used for stemming
+ * Output:
+ *      the_term_list = the list of terms
+ *      res = parser result code
+ * ========================================================================= */
+ 
+bool_tree_node *
+ParseBool(char *query_line, int query_len,
+          TermList **the_term_list, int the_stemmer_num, int the_stem_method, int *res,
+	  stemmed_dict * the_sd, int is_indexed,   /* [RPAP - Jan 97: Stem Index Change] */
+	  QueryTermList **the_query_term_list)  /* [RPAP - Feb 97: Term Frequency] */
+{
+  /* global variables to be accessed by bison/yacc created parser */
+  term_list = the_term_list;
+  stemmer_num = the_stemmer_num;
+  stem_method = the_stem_method;
+  ch_buf = query_line;
+  end_buf = query_line + query_len;
+  p__sd = the_sd;   /* [RPAP - Jan 97: Stem Index Change] */
+  indexed = is_indexed;  /* [RPAP - Jan 97: Stem Index Change] */
+  query_term_list = the_query_term_list; /* [RPAP - Feb 97: Term Frequency] */
+
+  FreeBoolTree(&(tree_base));
+ 
+  ResetTermList(term_list);
+  ResetQueryTermList(query_term_list);  /* [RPAP - Feb 97: Term Frequency] */
+
+  *res = yyparse();
+ 
+  return tree_base;
+}
+ 
+
Index: /indexers/branches/3.03a/mg/src/text/bool_query.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/bool_query.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/bool_query.c	(revision 14757)
@@ -0,0 +1,353 @@
+/**************************************************************************
+ *
+ * bool_query.c -- Boolean query evaluation
+ * Copyright (C) 1994  Neil Sharman & Tim Shimmin
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "messages.h"
+#include "filestats.h"
+#include "timing.h"
+#include "sptree.h"
+
+
+#include "mg.h"
+#include "text.h"
+#include "invf.h"
+#include "lists.h"
+#include "term_lists.h"
+#include "backend.h"
+#include "words.h"
+#include "stemmer.h"
+#include "stem_search.h"
+#include "invf_get.h"
+#include "text_get.h"
+#include "read_line.h"
+#include "bool_tree.h"
+#include "bool_parser.h"
+#include "bool_optimiser.h"
+#include "environment.h"
+
+
+/**********************
+  [RPAP - Feb 97: Term Frequency]
+
+  Shifted to bool_parser.y
+
+  *********************/
+
+/* =========================================================================
+ * Function: ReadInTermInfo
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+/**************************
+static void 
+ReadInTermInfo (query_data * qd)
+{
+  int i;
+  TermList *tl = qd->TL;
+
+  for (i = 0; i < tl->num; i++)
+    {
+      TermEntry *te = &(tl->TE[i]);
+      WordEntry *we = &(te->WE);
+
+       we->word_num = FindWord (qd->sd, te->Word,
+			       &we->count, &we->doc_count,
+			       &we->invf_ptr, &we->invf_len);
+      if (we->word_num == -1)
+	we->count = we->doc_count = 0;
+    }
+}
+
+***********************/
+
+
+
+/* =========================================================================
+ * Function: FindNoneTerms 
+ * Description: 
+ *      Set any terms which are not in dictionary to N_none (i.e. false)
+ *      Assumes a prior call to ReadInTermInfo
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void 
+FindNoneTerms (query_data * qd, bool_tree_node * tree)
+{
+  if (BOOL_HAS_CHILD (tree))
+    {
+      bool_tree_node *child = BOOL_CHILD (tree);
+      while (child)
+	{
+	  FindNoneTerms (qd, child);
+	  child = BOOL_SIBLING (child);
+	}
+    }
+  else if (BOOL_TAG (tree) == N_term)
+    {
+      int doc_count = qd->TL->TE[BOOL_TERM (tree)].WE.doc_count;
+      if (!doc_count)
+	BOOL_TAG (tree) = N_none;
+    }
+
+}				/*FindNoneTerms */
+
+/* =========================================================================
+ * Function: ReduceList
+ * Description: 
+ *      Go thru doc-set and get rid of all docs which are unmarked
+ *      The motivation for this routine is in the case of CNF queries.
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+void
+ReduceList (DocList * cset)
+{
+  DocEntry *src;
+  DocEntry *dest;
+
+  src = dest = cset->DE;
+  for (src = dest = cset->DE; src < cset->DE + cset->num; src++)
+    {
+      if (src->or_included)
+	{
+	  src->or_included = 0;
+	  *dest++ = *src;
+	}
+    }
+  cset->num = dest - cset->DE;
+
+}				/*ReduceList */
+
+/* =========================================================================
+ * Function: BooleanGet
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+static DocList *
+BooleanGet (query_data * qd, bool_tree_node * n,
+	    BooleanQueryInfo * bqi)
+{
+  if (n)
+    {
+      DocList *res = NULL;
+      switch (BOOL_TAG (n))
+	{
+	case N_all:
+	  Message ("Unexpected \"all\" node in the parse tree.");
+	  res = MakeDocList (0);
+	  break;
+	case N_not:
+	  Message ("Unexpected \"not\" node in the parse tree.");
+	  res = MakeDocList (0);
+	  break;
+	case N_none:
+	  {
+	    res = MakeDocList (0);
+	    break;
+	  }
+	case N_diff:
+	  {
+	    res = BooleanGet (qd, BOOL_CHILD (n), bqi);
+	    n = BOOL_SIBLING (BOOL_CHILD (n));
+	    while (n)
+	      {
+		bool_tree_node *next = BOOL_SIBLING (n);
+		if (BOOL_TAG (n) == N_term)
+		  {
+		    WordEntry *we = GetNthWE (qd->TL, BOOL_TERM (n));
+		    res = GetDocsOp (qd, we, op_diff_terms, res);
+		  }
+		else
+		  res = DiffLists (res, BooleanGet (qd, n, bqi));
+		n = next;
+	      }
+	    break;
+	  }
+	case N_and:
+	  {
+	    res = BooleanGet (qd, BOOL_CHILD (n), bqi);		/* initial fill of c-set */
+	    n = BOOL_SIBLING (BOOL_CHILD (n));
+	    while (n)
+	      {
+		bool_tree_node *next = BOOL_SIBLING (n);
+		switch (BOOL_TAG (n))
+		  {
+		  case N_term:
+		    {
+		      WordEntry *we = GetNthWE (qd->TL, BOOL_TERM (n));
+		      res = GetDocsOp (qd, we, op_and_terms, res);
+		    }
+		    break;
+		  case N_or_terms:
+		    {
+		      bool_tree_node *child = BOOL_CHILD (n);
+		      /* note: all children are terms - predetermined */
+		      while (child)
+			{
+			  WordEntry *we = GetNthWE (qd->TL, BOOL_TERM (child));
+			  res = GetDocsOp (qd, we, op_and_or_terms, res);
+			  child = BOOL_SIBLING (child);
+			}
+		      ReduceList (res);
+		    }
+		    break;
+		  default:
+		    res = IntersectLists (res, BooleanGet (qd, n, bqi));
+		  }		/*switch */
+		n = next;
+	      }
+	    break;
+	  }
+	case N_or:
+	case N_or_terms:
+	  {
+	    res = BooleanGet (qd, BOOL_CHILD (n), bqi);
+	    n = BOOL_SIBLING (BOOL_CHILD (n));
+	    while (n)
+	      {
+		bool_tree_node *next = BOOL_SIBLING (n);
+		res = MergeLists (res, BooleanGet (qd, n, bqi));
+		n = next;
+	      }
+	    break;
+	  }
+	case N_term:
+	  {
+	    res = GetDocsOp (qd, GetNthWE (qd->TL, BOOL_TERM (n)), op_term, NULL);
+	    break;
+	  }
+	}
+      return (res ? res : MakeDocList (0));
+    }
+  else
+    return MakeDocList (0);
+}
+
+/* =========================================================================
+ * Function: AdjustParaDocs
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+static int 
+DE_comp (void *a, void *b)
+{
+  return ((DocEntry *) a)->SeekPos - ((DocEntry *) b)->SeekPos;
+}
+
+static void
+AdjustParaDocs (query_data * qd, DocList * Docs)
+{
+  DocEntry *DE = Docs->DE;
+  int s, d;
+  Splay_Tree *SP;
+
+
+  /* Make the doc-list contain only references to unique
+   * real documents. So can get rid of cases where there
+   * are multiple paragraphs for a real document.
+   */
+
+  /* Note: [TS: 29/Sep/94] */
+  /* reads in seek-pos for docnums so can compare docs */
+  /* seek-pos used as real doc identifier */
+  /* whereas doc-num entries refer to paragraphs -- I think */
+  for (s = 0; s < Docs->num; s++)
+    FetchDocStart (qd, DE[s].DocNum, &DE[s].SeekPos, &DE[s].Len);
+
+  Message ("Original Number = %d\n", Docs->num);
+  SP = SP_createset (DE_comp);
+  d = 0;
+  for (s = 0; s < Docs->num; s++)
+    if (!SP_member (&DE[s], SP))
+      {
+	DE[d] = DE[s];
+	SP_insert (&DE[d], SP);
+	d++;
+      }
+  SP_freeset (SP);
+  Docs->num = d;
+  Message ("Final Number = %d\n", Docs->num);
+}
+
+/* =========================================================================
+ * Function: BooleanQuery 
+ * Description: 
+ *      The main control function for the boolean query.
+ * Input: 
+ * Output: 
+ *      qd->DL
+ * ========================================================================= */
+
+void 
+BooleanQuery (query_data * qd, char *Query, BooleanQueryInfo * bqi,
+	      int stem_method)
+{
+  bool_tree_node *tree;
+  DocList *Docs;
+  int res = 0;
+
+  tree = ParseBool (Query, MAXLINEBUFFERLEN, &(qd->TL), 
+		    qd->sd->sdh.stemmer_num, stem_method, &res,
+		    qd->sd, qd->sd->sdh.indexed,         /* [RPAP - Jan 97: Stem Index Change] */
+		    &(qd->QTL));                         /* [RPAP - Feb 97: Term Frequency] */
+
+  /* [TS:Aug/94] no longer tries to continue after parse failure */
+  if (res != 0)			/* failed the parse */
+    {
+      qd->DL = NULL;		/* have empty doc-list */
+      return;
+    }
+
+  /* [RPAP - Feb 97: Term Frequency] */
+  /*  ReadInTermInfo (qd); */
+
+  FindNoneTerms (qd, tree);
+
+  OptimiseBoolTree (tree, qd->TL, atoi (GetEnv ("optimise_type")));
+
+  qd->hops_taken = qd->num_of_ptrs = 0;
+  qd->num_of_terms = 0;
+
+  Docs = BooleanGet (qd, tree, bqi);
+
+/* [RPAP - Feb 97: NZDL Specifics] */
+#if !defined(PARABOOLEANMATCHES) && !defined(NZDL)
+  if (qd->id->ifh.InvfLevel == 3)
+    {
+      AdjustParaDocs (qd, Docs);
+    }
+#endif
+
+  if (bqi->MaxDocsToRetrieve != -1 && Docs->num > bqi->MaxDocsToRetrieve)
+    Docs->num = bqi->MaxDocsToRetrieve;
+
+  FreeQueryDocs (qd);
+
+  qd->DL = Docs;
+}
Index: /indexers/branches/3.03a/mg/src/text/bool_query.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/bool_query.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/bool_query.h	(revision 14757)
@@ -0,0 +1,55 @@
+/**************************************************************************
+ *
+ * bool_query.h -- boolean query processing
+ * Copyright (C) 1994  Authors
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:23  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:17:45  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:34:28  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.1  1994/10/20  03:56:36  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.1  1994/10/12  01:15:33  tes
+   * Found bugs in the existing boolean query optimiser.
+   * So decided to rewrite it.
+   * I accidentally deleted query.bool.y, but I have replaced it
+   * with bool_parser.y (which I have forgotten to add here ! ;-(
+   *
+ */
+
+#ifndef BOOL_QUERY_H
+#define BOOL_QUERY_H
+
+#include "backend.h"
+
+void BooleanQuery (query_data * qd, char *Query, BooleanQueryInfo * bqi,
+		   int stem_method);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/bool_tester.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/bool_tester.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/bool_tester.c	(revision 14757)
@@ -0,0 +1,185 @@
+/**************************************************************************
+ *
+ * bool_tester -- used to test bool_tree, bool_parser, bool_optimiser
+ * Copyright (C) 1994  Authors
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:23  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.2  2000/03/05 22:58:24  sjboddie
+   compiler complained about using stdin and stdout to do global
+   initialization - variables were never changed so they were
+   replaced with #defines
+
+   Revision 1.1  1999/08/10 21:17:45  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:41  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:34:29  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.2  1995/03/14  05:15:23  tes
+   * Updated the boolean query optimiser to do different types of optimisation.
+   * A query environment variable "optimise_type" specifies which one is to be
+   * used. Type 1 is the new one which is faster than 2.
+   *
+   * Revision 1.2  1994/10/18  06:11:05  tes
+   * The boolean optimiser seems to be modifying the parse tree
+   * like it is supposed to.
+   * Paragraph ranking now works without any text files if required to.
+   *
+   * Revision 1.1  1994/10/12  01:15:33  tes
+   * Found bugs in the existing boolean query optimiser.
+   * So decided to rewrite it.
+   * I accidentally deleted query.bool.y, but I have replaced it
+   * with bool_parser.y (which I have forgotten to add here ! ;-(
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+#include "sysfuncs.h"
+
+#include "local_strings.h"
+#include "term_lists.h"
+#include "bool_tree.h"
+#include "bool_parser.h"
+#include "bool_optimiser.h"
+#include "query_term_list.h"  /* [RPAP - Feb 97: Term Frequency] */
+
+#define MAX_LINE_LEN  255
+#define STEMMER_NUM 0 /* Lovin's stemmer */
+#define STEM_METHOD 3
+
+/* Newer compilers complain when you use stdin and stdout to do global 
+initialization. Since they're static we'll just use #defines instead
+static FILE *file_in = stdin;
+static FILE *file_out = stdout;
+*/
+#define FILE_IN stdin
+#define FILE_OUT stdout
+
+static char line[MAX_LINE_LEN + 1];
+
+/* --- prototypes --- */
+static char *prompt (char *str);
+
+
+/* =========================================================================
+ * Function: main
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+int main (int argc, char *argv[])
+{
+  bool_tree_node *tree = NULL;
+  TermList *term_list = NULL;
+  QueryTermList *query_term_list = NULL;  /* [RPAP - Feb 97: Term Frequency] */
+  int opt_type = 0;
+
+  while (1)
+    {
+      int res = 0;
+      int len = 0;
+
+      /* get a line */
+      if (!prompt ("Please enter boolean expression..."))
+	break;
+
+      len = strlen (line) - 1;	/* -1 => ignore the \n */
+
+      tree = ParseBool (line, len, &term_list, STEMMER_NUM, STEM_METHOD, &res,
+			NULL, 0,             /* [RPAP - Jan 97: Stem Index Change] */
+			&query_term_list);   /* [RPAP - Feb 97: Term Frequency] */
+
+      {
+	int done = 0;
+	while (!done)
+	  {
+	    if (!prompt ("Which type of optimisation 1 or 2 ?"))
+	      break;
+	    opt_type = atoi (line);
+	    done = (opt_type == 1 || opt_type == 2);
+	  }
+      }
+
+      if (!prompt ("Do you want to assign doc_counts to terms ?"))
+	break;
+
+      if (toupper (line[0]) == 'Y')
+	{
+	  /* cycle thru terms asking for doc_counts */
+	  int i;
+	  for (i = 0; i < term_list->num; i++)
+	    {
+	      char str[80];
+	      TermEntry *te = &(term_list->TE[i]);
+
+	      sprintf (str, "Please enter doc count for term '%s'",
+		       str255_to_string (te->Word, NULL));
+	      prompt (str);
+	      te->WE.doc_count = atoi (line);
+	      printf ("doc_count = %ld\n", te->WE.doc_count);
+	    }			/*for */
+	}			/*if */
+
+
+      if (res == 0)
+	{
+	  fprintf (FILE_OUT, "\n***Parsed Expression***\n");
+	  PrintBoolTree (tree, FILE_OUT);
+	  fputc ('\n', FILE_OUT);
+	  OptimiseBoolTree (tree, term_list, opt_type);
+	  fprintf (FILE_OUT, "\n***Optimised Expression ***\n");
+	  PrintBoolTree (tree, FILE_OUT);
+	  fputc ('\n', FILE_OUT);
+	}
+
+    }
+  return 0;
+}
+
+/* =========================================================================
+ * Function: 
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static char *
+prompt (char *str)
+{
+  fprintf (FILE_OUT, "\n%s\n", str);
+  return fgets (line, MAX_LINE_LEN, FILE_IN);
+}
Index: /indexers/branches/3.03a/mg/src/text/bool_tree.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/bool_tree.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/bool_tree.c	(revision 14757)
@@ -0,0 +1,292 @@
+/**************************************************************************
+ *
+ * bool_tree.c -- Boolean parse tree ADT
+ * Copyright (C) 1994  Tim Shimmin
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *       @(#)query.bool.y	1.9 16 Mar 1994
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "messages.h"
+#include "bool_tree.h"
+
+static char *RCSID = "$Id$";
+
+
+/* =========================================================================
+ * Function: CreateBoolNode
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+bool_tree_node *
+CreateBoolNode (N_Tag tag)
+{
+  bool_tree_node *n;
+  if (!(n = Xmalloc (sizeof (bool_tree_node))))
+    FatalError (1, "Can not create bool_tree_node for boolean query");
+  n->tag = tag;
+  BOOL_SIBLING (n) = NULL;
+  return n;
+}
+
+/* =========================================================================
+ * Function: 
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+bool_tree_node *
+CreateBoolTermNode (TermList ** tl, char *text, int Count, int word_num,
+		    u_long count, u_long doc_count, u_long invf_ptr, u_long invf_len,  /* [RPAP - Feb 97: Term Frequency] */
+		    int stemmer_num) 
+{
+  bool_tree_node *n = NULL;
+
+  /* allocate bool_tree_node */
+  n = CreateBoolNode (N_term);
+
+  BOOL_TERM (n) = AddTerm (tl, (u_char *) text, Count, word_num, count, doc_count, 
+			   invf_ptr, invf_len, stemmer_num);  /* [RPAP - Feb 97: Term Frequency] */
+
+  return n;
+}
+
+
+/* =========================================================================
+ * Function: CreateTreeNode
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+bool_tree_node *
+CreateBoolTreeNode (N_Tag tag, bool_tree_node * left, bool_tree_node * right)
+{
+  bool_tree_node *n = CreateBoolNode (tag);
+
+  BOOL_CHILD (n) = left;
+  if (left)
+    BOOL_SIBLING (left) = right;
+  if (right)
+    BOOL_SIBLING (right) = NULL;
+
+  return (n);
+}
+
+/* =========================================================================
+ * Function: 
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+int
+EqualBoolNodes (bool_tree_node * a, bool_tree_node * b)
+{
+  if (BOOL_TAG (a) == N_term && BOOL_TAG (a) == N_term)
+    return BOOL_TERM (a) == BOOL_TERM (b);
+  return 0;
+}
+
+/* =========================================================================
+ * Function: FreeBoolTree
+ * Description: 
+ *      Notes: does not fix up any parent or sibling links around given tree
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void 
+FreeTree (bool_tree_node * tree)
+{
+  bool_tree_node *sibling;
+
+  while (tree)
+    {
+      if (BOOL_HAS_CHILD (tree))
+	FreeTree (BOOL_CHILD (tree));
+      sibling = BOOL_SIBLING (tree);
+      Xfree (tree);
+      tree = sibling;
+    }
+}
+
+void 
+FreeBoolTree (bool_tree_node ** the_tree)
+{
+  bool_tree_node *tree = *the_tree;
+
+  if (!tree)
+    return;
+
+  FreeTree (tree);
+  *the_tree = NULL;
+/*********************************/
+  /* THIS IS POTENTIALLY DANGEROUS */
+  /* FIX UP LATER */
+  /* Need to correct the links for parent/siblings */
+/*********************************/
+
+}
+
+/* =========================================================================
+ * Function: PrintBoolTree
+ * Description: 
+ *      Print out a text version of the tree to the file
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+PrintBinaryOp (bool_tree_node * tree, FILE * file, char op)
+{
+  bool_tree_node *child = NULL;
+  assert (BOOL_HAS_CHILD (tree));
+
+  child = BOOL_CHILD (tree);
+  while (child)
+    {
+      PrintBoolTree (child, file);
+      child = BOOL_SIBLING (child);
+      if (child)
+	fprintf (file, " %c ", op);
+    }
+}
+
+static void
+PrintUnaryOp (bool_tree_node * tree, FILE * file, char op)
+{
+  bool_tree_node *child = NULL;
+
+  fprintf (file, " %c ", op);
+  assert (BOOL_HAS_CHILD (tree));
+  child = BOOL_CHILD (tree);
+  PrintBoolTree (child, file);
+}
+
+void
+PrintBoolTree (bool_tree_node * tree, FILE * file)
+{
+  if (!tree)
+    return;
+
+  fprintf (file, "(");
+  switch (BOOL_TAG (tree))
+    {
+    case N_term:
+      fprintf (file, "term %d", BOOL_TERM (tree));
+      break;
+    case N_and:
+      PrintBinaryOp (tree, file, '&');
+      break;
+    case N_or:
+      PrintBinaryOp (tree, file, '|');
+      break;
+    case N_or_terms:
+      PrintBinaryOp (tree, file, '+');
+      break;
+    case N_diff:
+      PrintBinaryOp (tree, file, '-');
+      break;
+    case N_not:
+      PrintUnaryOp (tree, file, '!');
+      break;
+    case N_all:
+      fprintf (file, " TRUE ");
+      break;
+    case N_none:
+      fprintf (file, " FALSE ");
+      break;
+    default:
+      break;
+    }
+
+  fprintf (file, ")");
+}
+
+
+/* =========================================================================
+ * Function: CopyBoolTree
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+bool_tree_node *
+CopyBoolTree (bool_tree_node * tree)
+{
+  bool_tree_node *sibling = NULL;
+  bool_tree_node *tree_copy = NULL;
+  bool_tree_node *prev = NULL;
+
+  if (!tree)
+    return NULL;
+
+  sibling = tree;
+  prev = NULL;
+  while (sibling)
+    {
+      /* copy sibling */
+      bool_tree_node *sibling_copy = (bool_tree_node *) malloc (sizeof (bool_tree_node));
+      if (!sibling_copy)
+	FatalError (1, "No memory for bool tree copy");
+      bcopy ((char *) sibling, (char *) sibling_copy, sizeof (bool_tree_node));
+
+      if (BOOL_HAS_CHILD (sibling))
+	{
+	  BOOL_CHILD (sibling_copy) = CopyBoolTree (BOOL_CHILD (sibling));
+	}
+
+      /* do the link up of copies */
+      if (prev)
+	BOOL_SIBLING (prev) = sibling_copy;
+      else
+	tree_copy = sibling_copy;
+      prev = sibling_copy;
+
+      sibling = BOOL_SIBLING (sibling);
+    }
+  return tree_copy;
+}
+
+
+/* =========================================================================
+ * Function: LastBoolSibling
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+bool_tree_node *
+LastBoolSibling (bool_tree_node * tree)
+{
+
+  if (!tree)
+    return NULL;
+
+  do
+    {
+      tree = BOOL_SIBLING (tree);
+    }
+  while (BOOL_SIBLING (tree));
+
+  return tree;
+}
Index: /indexers/branches/3.03a/mg/src/text/bool_tree.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/bool_tree.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/bool_tree.h	(revision 14757)
@@ -0,0 +1,113 @@
+/**************************************************************************
+ *
+ * bool_tree.h -- description
+ * Copyright (C) 1994  Authors
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:23  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:17:46  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:42  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:34:31  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.2  1995/03/14  05:15:25  tes
+   * Updated the boolean query optimiser to do different types of optimisation.
+   * A query environment variable "optimise_type" specifies which one is to be
+   * used. Type 1 is the new one which is faster than 2.
+   *
+   * Revision 1.2  1994/10/18  06:11:07  tes
+   * The boolean optimiser seems to be modifying the parse tree
+   * like it is supposed to.
+   * Paragraph ranking now works without any text files if required to.
+   *
+   * Revision 1.1  1994/10/12  01:15:35  tes
+   * Found bugs in the existing boolean query optimiser.
+   * So decided to rewrite it.
+   * I accidentally deleted query.bool.y, but I have replaced it
+   * with bool_parser.y (which I have forgotten to add here ! ;-(
+   *
+ */
+
+#ifndef BOOL_TREE_H
+#define BOOL_TREE_H
+
+#include "sysfuncs.h"
+#include "term_lists.h"
+
+typedef enum
+  {
+    N_term, N_and, N_or, N_diff, N_none, N_all,
+    N_not, N_or_terms
+  }
+N_Tag;
+
+typedef struct bool_tree_node
+  {
+    N_Tag tag;
+    struct bool_tree_node *sibling;
+    union
+      {
+	struct bool_tree_node *child;
+	int term_id;
+      }
+    fields;
+    int sum_ft;			/* for or_terms nodes */
+  }
+bool_tree_node;
+
+
+#define BOOL_HAS_CHILD(n) (\
+			(n)->tag==N_and || \
+			(n)->tag==N_or || (n)->tag==N_or_terms || \
+			(n)->tag==N_not || (n)->tag==N_diff)
+#define BOOL_TAG(n) ((n)->tag)
+#define BOOL_SIBLING(n) ((n)->sibling)
+#define BOOL_TERM(n) ((n)->fields.term_id)
+#define BOOL_CHILD(n) ((n)->fields.child)
+#define BOOL_SUM_FT(n) ((n)->sum_ft)
+
+bool_tree_node *CreateBoolNode (N_Tag tag);
+bool_tree_node *CopyBoolTree (bool_tree_node * tree);
+bool_tree_node *CreateBoolTermNode (TermList ** tl, char *text, int Count, int word_num,
+				    u_long count, u_long doc_count, u_long invf_ptr, 
+				    u_long invf_len, int stemmer_num);
+bool_tree_node *CreateBoolTreeNode (N_Tag tag,
+			     bool_tree_node * left, bool_tree_node * right);
+void FreeBoolTree (bool_tree_node ** tree);
+void PrintBoolTree (bool_tree_node * tree, FILE * file);
+bool_tree_node *LastBoolSibling (bool_tree_node * tree);
+
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/build.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/build.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/build.h	(revision 14757)
@@ -0,0 +1,171 @@
+/**************************************************************************
+ *
+ * build.h -- Global information for the passes of mg_passes
+ * Copyright (C) 1994  Neil Sharman, Alistair Moffat and Lachlan Andrew
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#ifndef H_BUILD
+#define H_BUILD
+
+#include "longlong.h"
+
+#define	TERMPARAGRAPH	'\003'
+
+
+int init_special (char *file_name);
+int init_text_1 (char *file_name);
+int init_text_2 (char *file_name);
+int init_invf_1 (char *file_name);
+int init_invf_2 (char *file_name);
+int init_ivf_1 (char *file_name);
+int init_ivf_2 (char *file_name);
+/*
+ * file_name  IN      The name of the dictionary file
+ * 
+ * returns      COMPALLOK for all ok,
+ *              COMPERROR for any error.  e.g. cannot read file
+ */
+
+
+
+
+
+int process_special (u_char * s_in, int l_in);
+int process_text_1 (u_char * s_in, int l_in);
+int process_text_2 (u_char * s_in, int l_in);
+int process_invf_1 (u_char * s_in, int l_in);
+int process_invf_2 (u_char * s_in, int l_in);
+int process_ivf_1 (u_char * s_in, int l_in);
+int process_ivf_2 (u_char * s_in, int l_in);
+/*
+ * s_in               IN      The binary string to be compressed
+ * l_in         IN      The number of characters in s_in
+ *
+ * returns      COMPALLOK for all ok,
+ *              COMPERROR for any error.  e.g. cannot read file
+ *
+ * The calling routine is responsible for ensuring that s_out is long 
+ * enough.
+ */
+
+
+
+
+
+int done_special (char *filename);
+int done_text_1 (char *filename);
+int done_text_2 (char *filename);
+int done_invf_1 (char *filename);
+int done_invf_2 (char *filename);
+int done_ivf_1 (char *filename);
+int done_ivf_2 (char *filename);
+/*
+ * returns    COMPALLOK for all ok,
+ *              COMPERROR for any error.  e.g. cannot write file
+ */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern char InvfLevel;
+/*
+ * This will determine the level of the inverted file it can take on the
+ * values 1, 2, or 3.
+ *
+ * Level 1: The inverted file contains only document numbers making it possible
+ *          to do only boolean queries.
+ * 
+ * Level 2: The inverted file also contains word counts per document making it
+ *          possible to do cosine ranked queries.
+ *
+ * Level 3: The inverted file contains word positions.
+ */
+
+
+extern unsigned long buf_size;
+/*
+ * The size of the document input buffer.
+ */
+
+extern unsigned long ChunkLimit;
+/*
+ * The maximum number of chunks that can be written to disk.
+ */
+
+extern unsigned long invf_buffer_size;
+/*
+ * The amount of memory to allocate to the invertion buffer.
+ */
+
+extern char SkipSGML;
+/*
+ * 1 if SGML tags are to be considered non-words when building the 
+ * inverted file.
+ */
+
+extern char MakeWeights;
+/*
+ * 1 if the weights file should be generated.
+ */
+
+extern FILE *Comp_Stats;
+/*
+ * Contains a file pointer to the file where compression stats should be sent
+ */
+
+extern int comp_stat_point;
+/*
+ * Generate a compression stat entry every comp_stat_point bytes 
+ */
+
+extern mg_ullong bytes_processed;
+/*
+ * The number of bytes processed. NOTE: This excludes document separators.
+ */
+
+extern mg_ullong bytes_received;
+/*
+ * The number of bytes processed. NOTE: This includes document separators.
+ */
+
+
+extern int stemmer_num;
+/*
+ * The stemmer to use for stemming words for the inverted file.
+ * see stemmer.h
+ */
+
+extern int stem_method;
+/*
+ * The method to use for stemming words for the inverted file.
+ * see stemmer.h
+ */
+#endif
Index: /indexers/branches/3.03a/mg/src/text/commands.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/commands.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/commands.c	(revision 14757)
@@ -0,0 +1,585 @@
+/**************************************************************************
+ *
+ * commands.c -- mgquery command processing functions
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:23  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:17:47  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:34:32  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.2  1994/09/20  04:41:22  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "messages.h"
+
+#include "environment.h"
+#include "mg.h"
+#include "locallib.h"
+#include "backend.h"		/* for qd */
+#include "term_lists.h"		/* for MAXTERMSTRLEN */
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+# define OPENPIPE        _popen
+# define CLOSEPIPE       _pclose
+#else
+# define OPENPIPE        popen
+# define CLOSEPIPE       pclose
+#endif
+
+extern char *PathName;
+extern FILE *OutFile, *InFile;
+extern int OutPipe, InPipe;
+extern int Quitting;
+
+char *CommandsErrorStr = NULL;
+
+/* [TS: June/95] */
+/* current qd for use by any commands */
+static query_data *the_qd = NULL;
+
+
+#include "help.mg.h"
+#include "warranty.h"
+#include "conditions.h"
+
+static void 
+CmdQuit (void)
+{
+  Quitting = 1;
+}
+
+static void 
+CmdPush (void)
+{
+  PushEnv ();
+}
+
+
+static void 
+CmdPop (void)
+{
+  PopEnv ();
+  if (EnvStackHeight () == 1)
+    PushEnv ();
+}
+
+static void 
+CmdHelp (void)
+{
+  FILE *more;
+  int i;
+
+  if (!(more = OPENPIPE (GetDefEnv ("pager", "more"), "w")))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      fprintf (stderr, "ERROR : Unable to run more\n");
+      return;
+    }
+  for (i = 0; i < sizeof (help_str) / sizeof (help_str[0]); i++)
+    fputs (help_str[i], more);
+
+  CLOSEPIPE (more);  /* [RPAP - Feb 97: WIN32 Port] */
+}
+
+
+static void 
+CmdWarranty (void)
+{
+  FILE *more;
+  int i;
+
+  if (!(more = OPENPIPE (GetDefEnv ("pager", "more"), "w")))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      fprintf (stderr, "ERROR : Unable to run more\n");
+      return;
+    }
+  for (i = 0; i < sizeof (warranty_str) / sizeof (warranty_str[0]); i++)
+    fputs (warranty_str[i], more);
+
+  CLOSEPIPE (more);  /* [RPAP - Feb 97: WIN32 Port] */
+}
+
+
+static void 
+CmdConditions (void)
+{
+  FILE *more;
+  int i;
+
+  if (!(more = OPENPIPE (GetDefEnv ("pager", "more"), "w")))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      fprintf (stderr, "ERROR : Unable to run more\n");
+      return;
+    }
+  for (i = 0; i < sizeof (cond_str) / sizeof (cond_str[0]); i++)
+    fputs (cond_str[i], more);
+
+  CLOSEPIPE (more);
+}
+
+static void 
+CmdReset (void)
+{
+  while (EnvStackHeight () > 1)
+    PopEnv ();
+  PushEnv ();
+}
+
+static void 
+CmdDisplay (void)
+{
+  int i;
+  size_t l = 0;
+  char *name;
+  for (i = 0; (name = GetEnvName (i)) != NULL; i++)
+    if (strlen (name) > l)
+      l = strlen (name);
+
+  for (i = 0; (name = GetEnvName (i)) != NULL; i++)
+    printf ("%-*s = \"%s\"\n", (int) l, name, GetEnv (name));
+}
+
+static void 
+CmdQueryTerms (void)
+{
+  static char terms_str[MAXTERMSTRLEN + 1];
+
+  if (the_qd && the_qd->TL)
+    {
+      ConvertTermsToString (the_qd->TL, terms_str);
+      printf ("%s\n", terms_str);
+      fflush (stdout);
+    }
+
+}
+
+
+static void 
+CmdSet (char *name, char *value)
+{
+  if (!*name)
+    {
+      CommandsErrorStr = "Blank names are not permitted";
+      return;
+    }
+  switch (SetEnv (name, value, NULL))
+    {
+    case -1:
+      CommandsErrorStr = "Out of memory\n";
+      break;
+    case -2:
+      CommandsErrorStr = ConstraintErrorStr;
+      break;
+    }
+}
+
+static void 
+CmdUnset (char *name)
+{
+  if (!*name)
+    {
+      CommandsErrorStr = "Blank names are not permitted";
+      return;
+    }
+  if (UnsetEnv (name, 0) == -1)
+    CommandsErrorStr = "Specified name does not exist";
+}
+
+
+
+
+
+
+/*
+ * Do the .input command 
+ */
+static void 
+CmdInput (char *param1, char *param2)
+{
+  enum
+  {
+    READ, APPEND, PIPEFROM
+  }
+  mode;
+  FILE *NewInput;
+  char *buf, *s;
+
+  /* join the two parameters together */
+  buf = Xmalloc (strlen (param1) + strlen (param2) + 1);
+  strcpy (buf, param1);
+  strcat (buf, param2);
+  s = buf;
+
+
+  while (*s == ' ' || *s == '\t')
+    s++;
+
+  if (*s == '<')
+    {
+      s++;
+      mode = READ;
+    }
+  else if (*s == '|')
+    {
+      mode = PIPEFROM;
+      s++;
+    }
+  else
+    {
+      if (InPipe)
+	CLOSEPIPE (InFile);  /* [RPAP - Feb 97: WIN32 Port] */
+      else if (InFile != stdin)
+	fclose (InFile);
+      InPipe = 0;
+      InFile = stdin;
+      Xfree (buf);
+      return;
+    }
+
+  while (*s == ' ' || *s == '\t')
+    s++;
+
+  if (*s)
+    {
+      if (mode == READ)
+	NewInput = fopen (s, "r");
+      else
+	NewInput = OPENPIPE (s, "r");  /* [RPAP - Feb 97: WIN32 Port] */
+
+      if (NewInput)
+	{
+	  if (InPipe)
+	    CLOSEPIPE (InFile);  /* [RPAP - Feb 97: WIN32 Port] */
+	  else if (InFile != stdin)
+	    fclose (InFile);
+	  InPipe = (mode == PIPEFROM);
+	  InFile = NewInput;
+	}
+      else
+	CommandsErrorStr = "Bad input file/pipe";
+    }
+  else
+    {
+      if (InPipe)
+	CLOSEPIPE (InFile);  /* [RPAP - Feb 97: WIN32 Port] */
+      else if (InFile != stdin)
+	fclose (InFile);
+      InPipe = 0;
+      InFile = stdin;
+    }
+  Xfree (buf);
+}
+
+
+
+static void 
+CmdOutput (char *param1, char *param2)
+{
+  enum
+  {
+    WRITE, APPEND, PIPETO
+  }
+  mode;
+  char *buf, *s;
+  FILE *NewOutput;
+
+  /* join the two parameters together */
+  buf = Xmalloc (strlen (param1) + strlen (param2) + 1);
+  strcpy (buf, param1);
+  strcat (buf, param2);
+  s = buf;
+
+  while (*s == ' ' || *s == '\t')
+    s++;
+
+  if (*s == '>')
+    {
+      s++;
+      mode = APPEND;
+      if (*s == '>')
+	s++;
+      else
+	mode = WRITE;
+    }
+  else if (*s == '|')
+    {
+      mode = PIPETO;
+      s++;
+    }
+  else
+    {
+      if (OutPipe)
+	CLOSEPIPE (OutFile);  /* [RPAP - Feb 97: WIN32 Port] */
+      else if (OutFile != stdout)
+	fclose (OutFile);
+      OutPipe = 0;
+      OutFile = stdout;
+      Xfree (buf);
+      return;
+    }
+
+  while (*s == ' ' || *s == '\t')
+    s++;
+
+  if (*s)
+    {
+      if (mode == PIPETO)
+	NewOutput = OPENPIPE (s, "w");  /* [RPAP - Feb 97: WIN32 Port] */
+      else
+	NewOutput = fopen (s, mode == WRITE ? "w" : "a");
+      if (NewOutput)
+	{
+	  if (OutPipe)
+	    CLOSEPIPE (OutFile);  /* [RPAP - Feb 97: WIN32 Port] */
+	  else if (OutFile != stdout)
+	    fclose (OutFile);
+	  OutPipe = (mode == PIPETO);
+	  OutFile = NewOutput;
+	}
+      else
+	CommandsErrorStr = "Bad output file/pipe";
+    }
+  else
+    {
+      if (OutPipe)
+	CLOSEPIPE (OutFile);  /* [RPAP - Feb 97: WIN32 Port] */
+      else if (OutFile != stdout)
+	fclose (OutFile);
+      OutPipe = 0;
+      OutFile = stdout;
+    }
+  Xfree (buf);
+}
+
+
+
+static char *
+ParseArg (char *line, char *buffer)
+{
+  if (*line == '\"')
+    {
+      line++;
+      while (*line != '\"' && *line != '\0')
+	{
+	  if (*line == '\\')
+	    *buffer++ = *line++;
+	  if (*line != '\0')
+	    *buffer++ = *line++;
+	}
+      if (*line == '\"')
+	line++;
+    }
+  else
+    while (*line != ' ' && *line != '\t' && *line != '\0')
+      {
+	if (*line == '\\')
+	  line++;
+	if (*line != '\0')
+	  *buffer++ = *line++;
+      }
+  *buffer = '\0';
+  while (*line == ' ' || *line == '\t')
+    line++;
+  return (line);
+}
+
+
+
+char *
+ProcessCommands (char *line, query_data * qd)
+{
+  struct
+  {
+    char *Command;
+    void (*action) (void);
+    void (*action1) (char *);
+    void (*action2) (char *, char *);
+  }
+   *dc, dot_command[] =
+  {
+    {
+      "set", NULL, NULL, CmdSet
+    }
+    ,
+    {
+      "input", NULL, NULL, CmdInput
+    }
+    ,
+    {
+      "output", NULL, NULL, CmdOutput
+    }
+    ,
+    {
+      "unset", NULL, CmdUnset, NULL
+    }
+    ,
+    {
+      "help", CmdHelp, NULL, NULL
+    }
+    ,
+    {
+      "reset", CmdReset, NULL, NULL
+    }
+    ,
+    {
+      "display", CmdDisplay, NULL, NULL
+    }
+    ,
+    {
+      "push", CmdPush, NULL, NULL
+    }
+    ,
+    {
+      "quit", CmdQuit, NULL, NULL
+    }
+    ,
+    {
+      "pop", CmdPop, NULL, NULL
+    }
+    ,
+    {
+      "warranty", CmdWarranty, NULL, NULL
+    }
+    ,
+    {
+      "conditions", CmdConditions, NULL, NULL
+    }
+    ,
+    {
+      "queryterms", CmdQueryTerms, NULL, NULL
+    }
+  };
+
+
+  char command[512];
+  char param1[512], param2[512];
+  CommandsErrorStr = NULL;
+  the_qd = qd;			/* set globally to be accessed by command functions if needed */
+  while (*line == ' ' || *line == '\t')
+    line++;
+  while (*line == '.')
+    {
+      int i;
+      line++;
+      for (i = 0; isalpha (*line) && i < 512; i++, line++)
+	command[i] = tolower (*line);
+      while (*line == ' ' || *line == '\t')
+	line++;
+      if (i != 512)
+	{
+	  command[i] = '\0';
+	  for (i = 0, dc = dot_command; i < NUMOF (dot_command); i++, dc++)
+	    if (!strcmp (dc->Command, command))
+	      {
+		if (dc->action)
+		  dc->action ();
+		else if (dc->action1)
+		  {
+		    line = ParseArg (line, param1);
+		    dc->action1 (param1);
+		    break;
+		  }
+		else if (dc->action2)
+		  {
+		    line = ParseArg (line, param1);
+		    line = ParseArg (line, param2);
+		    dc->action2 (param1, param2);
+		    break;
+		  }
+		if (CommandsErrorStr)
+		  *line = '\0';
+		break;
+	      }
+	  if (i == NUMOF (dot_command))
+	    i = 100;
+	}
+      if (i == 100)
+	{
+	  CommandsErrorStr = "Illegal command";
+	  *line = '\0';
+	}
+      while (*line == ' ' || *line == '\t')
+	line++;
+    }
+  return (line);
+}
+
+
+
+
+
+void 
+read_mgrc_file (void)
+{
+  char line[1000];
+  char FileName[256];
+  int LineNum = 0;
+  FILE *mgrc;
+
+  strcpy (FileName, ".mgrc");
+  mgrc = fopen (FileName, "r");
+
+  if (!mgrc)
+    {
+      char *home_path = getenv ("HOME");
+      if (home_path)
+	{
+	  sprintf (FileName, "%s/.mgrc", home_path);
+	  mgrc = fopen (FileName, "r");
+	}
+    }
+
+  if (!mgrc)
+    return;
+
+  while (fgets (line, sizeof (line), mgrc))
+    {
+      char *s, linebuf[1000];
+      LineNum++;
+      if ((s = strchr (line, '\n')) != NULL)
+	*s = '\0';
+      strcpy (linebuf, line);
+      if ((s = strchr (line, '#')) != NULL)
+	*s = '\0';
+      if (!*line)
+	continue;
+      ProcessCommands (line, NULL);
+      if (CommandsErrorStr)
+	Message ("%s\n%s : ERROR in line %d of %s\n%s : %s\n",
+		 linebuf,
+		 msg_prefix, LineNum, FileName,
+		 msg_prefix, CommandsErrorStr);
+    }
+  fclose (mgrc);
+}
Index: /indexers/branches/3.03a/mg/src/text/commands.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/commands.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/commands.h	(revision 14757)
@@ -0,0 +1,33 @@
+/**************************************************************************
+ *
+ * commands.h -- mgquery command processing functions
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef COMMANDS_H
+#define COMMANDS_H
+
+#include "backend.h"
+
+extern char *CommandsErrorStr;
+char *ProcessCommands (char *line, query_data * qd);
+void read_mgrc_file (void);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/comp_dict.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/comp_dict.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/comp_dict.c	(revision 14757)
@@ -0,0 +1,258 @@
+/**************************************************************************
+ *
+ * comp_dict.c -- Functions for loading the compression dictionary
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "huffman.h"
+#include "local_strings.h"
+#include "memlib.h"
+#include "messages.h"
+
+#include "mg.h"
+#include "hash.h"
+#include "text.h"
+#include "comp_dict.h"
+#include "locallib.h"
+#include "mg_files.h"
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:23  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:17:48  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:34:34  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:56:41  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:24  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+compression_dict_header cdh;
+compressed_text_header cth;
+comp_frags_header cfh[2];
+
+dict_hash_table *ht[2];
+
+huff_data char_huff[2];
+huff_data lens_huff[2];
+u_long *char_codes[2], *lens_codes[2];
+u_long Words_disk = 0;
+u_long Chars_disk = 0;
+
+
+static dict_hash_table *
+ReadInWords (FILE * dict, comp_frags_header * cfh,
+	     int esc)
+{
+  int i;
+  u_char *allwords, *prev = NULL;
+  dict_hash_table *ht;
+  u_char **words;
+  u_long ht_size;
+
+  ht_size = prime (cfh->hd.num_codes * HASH_RATIO);
+  if (!(ht = Xmalloc (sizeof (dict_hash_table) +
+		      (ht_size - 1) * sizeof (ht->table[0]))))
+    {
+      Message ("no memory for hash_table\n");
+      return NULL;
+    }
+
+  ht->size = ht_size;
+  ht->hd = &cfh->hd;
+
+  if (!(ht->codes = Generate_Huffman_Codes (&cfh->hd, NULL)))
+    {
+      Message ("no memory for huffman codes\n");
+      return NULL;
+    }
+
+  if (!(ht->words = Xmalloc (sizeof (u_char *) * cfh->hd.num_codes)))
+    {
+      Message ("no memory for word pointers\n");
+      return NULL;
+    }
+  words = ht->words;
+
+  bzero ((char *) ht->table, ht_size * sizeof (ht->table[0]));
+
+  if (!(allwords = Xmalloc (sizeof (u_char) * cfh->uncompressed_size)))
+    {
+      Message ("no memory for words\n");
+      return NULL;
+    }
+
+  for (i = 0; i < cfh->hd.num_codes; i++, words++)
+    {
+      register int val, copy;
+      val = fgetc (dict);
+      copy = (val >> 4) & 0xf;
+      val &= 0xf;
+
+      *words = allwords;
+
+      memcpy (allwords + 1, prev + 1, copy);
+      fread (allwords + copy + 1, sizeof (u_char), val, dict);
+      *allwords = val + copy;
+
+      Words_disk += val + 1;
+
+      /* insert into the hash table */
+      if (i < cfh->hd.num_codes - esc)
+	{
+	  register u_char **wptr;
+	  register int tsize = ht->size;
+	  register unsigned long hashval, step;
+
+	  HASH (hashval, step, allwords, tsize);
+
+	  wptr = ht->table[hashval];
+	  for (; wptr;)
+	    {
+	      hashval += step;
+	      if (hashval >= tsize)
+		hashval -= tsize;
+	      wptr = ht->table[hashval];
+	    }
+	  ht->table[hashval] = words;
+	}
+      prev = allwords;
+      allwords += *allwords + 1;
+    }
+  return ht;
+}
+
+
+
+int 
+LoadCompressionDictionary (char *dict_file_name)
+{
+  FILE *dict;
+  int which;
+  if (!(dict = open_named_file (dict_file_name, "rb", MAGIC_DICT, MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return COMPERROR;
+
+  Words_disk = sizeof (u_long);
+
+  if (Read_cdh (dict, &cdh, NULL, &Words_disk) == -1)
+    goto error;
+
+  for (which = 0; which < 2; which++)
+    switch (cdh.dict_type)
+      {
+      case MG_COMPLETE_DICTIONARY:
+	{
+	  if (Read_cfh (dict, &cfh[which], NULL, &Words_disk) == -1)
+	    goto error;
+
+	  if (!(ht[which] = ReadInWords (dict, &cfh[which], 0)))
+	    goto error;
+
+	}
+	break;
+      case MG_PARTIAL_DICTIONARY:
+	{
+	  if (cdh.num_words[which])
+	    {
+	      if (Read_cfh (dict, &cfh[which], NULL, &Words_disk) == -1)
+		goto error;
+	      if (!(ht[which] = ReadInWords (dict, &cfh[which], 1)))
+		goto error;
+	    }
+	  else
+	    ht[which] = NULL;
+	  if (Read_Huffman_Data (dict, &char_huff[which], NULL,
+				 &Chars_disk) == -1)
+	    goto error;
+	  if (!(char_codes[which] =
+		Generate_Huffman_Codes (&char_huff[which], NULL)))
+	    goto error;
+	  if (Read_Huffman_Data (dict, &lens_huff[which], NULL,
+				 &Chars_disk) == -1)
+	    goto error;
+	  if (!(lens_codes[which] =
+		Generate_Huffman_Codes (&lens_huff[which], NULL)))
+	    goto error;
+	}
+	break;
+      case MG_SEED_DICTIONARY:
+	{
+	  if (cdh.num_words[which])
+	    {
+	      if (Read_cfh (dict, &cfh[which], NULL, &Words_disk) == -1)
+		goto error;
+	      if (!(ht[which] = ReadInWords (dict, &cfh[which], 1)))
+		goto error;
+	    }
+	  else
+	    ht[which] = NULL;
+	  switch (cdh.novel_method)
+	    {
+	    case MG_NOVEL_HUFFMAN_CHARS:
+	      if (Read_Huffman_Data (dict, &char_huff[which], NULL,
+				     &Chars_disk) == -1)
+		goto error;
+	      if (!(char_codes[which] =
+		    Generate_Huffman_Codes (&char_huff[which], NULL)))
+		goto error;
+	      if (Read_Huffman_Data (dict, &lens_huff[which], NULL,
+				     &Chars_disk) == -1)
+		goto error;
+	      if (!(lens_codes[which] =
+		    Generate_Huffman_Codes (&lens_huff[which], NULL)))
+		goto error;
+	      break;
+	    case MG_NOVEL_BINARY:
+	      break;
+	    case MG_NOVEL_DELTA:
+	      break;
+	    case MG_NOVEL_HYBRID:
+	      break;
+	    case MG_NOVEL_HYBRID_MTF:
+	      break;
+	    default:
+	      FatalError (1, "Bad novel method");
+	    }
+	}
+	break;
+      default:
+	FatalError (1, "Bad dictionary kind\n");
+      }
+
+  return (COMPALLOK);
+
+
+error:
+  fclose (dict);
+  return (COMPERROR);
+}
Index: /indexers/branches/3.03a/mg/src/text/comp_dict.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/comp_dict.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/comp_dict.h	(revision 14757)
@@ -0,0 +1,59 @@
+/**************************************************************************
+ *
+ * comp_dict.h -- Functions for loading the compression dictionary
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+
+
+#define HASH_RATIO 2
+
+
+
+
+typedef struct dict_hash_table
+  {
+    u_long size;
+    huff_data *hd;
+    u_long *codes;
+    u_char **words;
+    u_char **table[1];
+  }
+dict_hash_table;
+
+
+
+
+extern compression_dict_header cdh;
+extern compressed_text_header cth;
+extern comp_frags_header cfh[2];
+
+extern dict_hash_table *ht[2];
+
+extern huff_data char_huff[2];
+extern huff_data lens_huff[2];
+extern u_long *char_codes[2], *lens_codes[2];
+extern u_long Words_disk;
+extern u_long Chars_disk;
+
+
+
+int LoadCompressionDictionary (char *dict_file_name);
Index: /indexers/branches/3.03a/mg/src/text/conditions.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/conditions.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/conditions.h	(revision 14757)
@@ -0,0 +1,226 @@
+static char *cond_str[] = {
+"		    GNU GENERAL PUBLIC LICENSE\n",
+"   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n",
+"\n",
+"  0. This License applies to any program or other work which contains\n",
+"a notice placed by the copyright holder saying it may be distributed\n",
+"under the terms of this General Public License.  The \"Program\", below,\n",
+"refers to any such program or work, and a \"work based on the Program\"\n",
+"means either the Program or any derivative work under copyright law:\n",
+"that is to say, a work containing the Program or a portion of it,\n",
+"either verbatim or with modifications and/or translated into another\n",
+"language.  (Hereinafter, translation is included without limitation in\n",
+"the term \"modification\".)  Each licensee is addressed as \"you\".\n",
+"\n",
+"Activities other than copying, distribution and modification are not\n",
+"covered by this License; they are outside its scope.  The act of\n",
+"running the Program is not restricted, and the output from the Program\n",
+"is covered only if its contents constitute a work based on the\n",
+"Program (independent of having been made by running the Program).\n",
+"Whether that is true depends on what the Program does.\n",
+"\n",
+"  1. You may copy and distribute verbatim copies of the Program's\n",
+"source code as you receive it, in any medium, provided that you\n",
+"conspicuously and appropriately publish on each copy an appropriate\n",
+"copyright notice and disclaimer of warranty; keep intact all the\n",
+"notices that refer to this License and to the absence of any warranty;\n",
+"and give any other recipients of the Program a copy of this License\n",
+"along with the Program.\n",
+"\n",
+"You may charge a fee for the physical act of transferring a copy, and\n",
+"you may at your option offer warranty protection in exchange for a fee.\n",
+"\n",
+"  2. You may modify your copy or copies of the Program or any portion\n",
+"of it, thus forming a work based on the Program, and copy and\n",
+"distribute such modifications or work under the terms of Section 1\n",
+"above, provided that you also meet all of these conditions:\n",
+"\n",
+"    a) You must cause the modified files to carry prominent notices\n",
+"    stating that you changed the files and the date of any change.\n",
+"\n",
+"    b) You must cause any work that you distribute or publish, that in\n",
+"    whole or in part contains or is derived from the Program or any\n",
+"    part thereof, to be licensed as a whole at no charge to all third\n",
+"    parties under the terms of this License.\n",
+"\n",
+"    c) If the modified program normally reads commands interactively\n",
+"    when run, you must cause it, when started running for such\n",
+"    interactive use in the most ordinary way, to print or display an\n",
+"    announcement including an appropriate copyright notice and a\n",
+"    notice that there is no warranty (or else, saying that you provide\n",
+"    a warranty) and that users may redistribute the program under\n",
+"    these conditions, and telling the user how to view a copy of this\n",
+"    License.  (Exception: if the Program itself is interactive but\n",
+"    does not normally print such an announcement, your work based on\n",
+"    the Program is not required to print an announcement.)\n",
+"
+\n",
+"These requirements apply to the modified work as a whole.  If\n",
+"identifiable sections of that work are not derived from the Program,\n",
+"and can be reasonably considered independent and separate works in\n",
+"themselves, then this License, and its terms, do not apply to those\n",
+"sections when you distribute them as separate works.  But when you\n",
+"distribute the same sections as part of a whole which is a work based\n",
+"on the Program, the distribution of the whole must be on the terms of\n",
+"this License, whose permissions for other licensees extend to the\n",
+"entire whole, and thus to each and every part regardless of who wrote it.\n",
+"\n",
+"Thus, it is not the intent of this section to claim rights or contest\n",
+"your rights to work written entirely by you; rather, the intent is to\n",
+"exercise the right to control the distribution of derivative or\n",
+"collective works based on the Program.\n",
+"\n",
+"In addition, mere aggregation of another work not based on the Program\n",
+"with the Program (or with a work based on the Program) on a volume of\n",
+"a storage or distribution medium does not bring the other work under\n",
+"the scope of this License.\n",
+"\n",
+"  3. You may copy and distribute the Program (or a work based on it,\n",
+"under Section 2) in object code or executable form under the terms of\n",
+"Sections 1 and 2 above provided that you also do one of the following:\n",
+"\n",
+"    a) Accompany it with the complete corresponding machine-readable\n",
+"    source code, which must be distributed under the terms of Sections\n",
+"    1 and 2 above on a medium customarily used for software interchange; or,\n",
+"\n",
+"    b) Accompany it with a written offer, valid for at least three\n",
+"    years, to give any third party, for a charge no more than your\n",
+"    cost of physically performing source distribution, a complete\n",
+"    machine-readable copy of the corresponding source code, to be\n",
+"    distributed under the terms of Sections 1 and 2 above on a medium\n",
+"    customarily used for software interchange; or,\n",
+"\n",
+"    c) Accompany it with the information you received as to the offer\n",
+"    to distribute corresponding source code.  (This alternative is\n",
+"    allowed only for noncommercial distribution and only if you\n",
+"    received the program in object code or executable form with such\n",
+"    an offer, in accord with Subsection b above.)\n",
+"\n",
+"The source code for a work means the preferred form of the work for\n",
+"making modifications to it.  For an executable work, complete source\n",
+"code means all the source code for all modules it contains, plus any\n",
+"associated interface definition files, plus the scripts used to\n",
+"control compilation and installation of the executable.  However, as a\n",
+"special exception, the source code distributed need not include\n",
+"anything that is normally distributed (in either source or binary\n",
+"form) with the major components (compiler, kernel, and so on) of the\n",
+"operating system on which the executable runs, unless that component\n",
+"itself accompanies the executable.\n",
+"\n",
+"If distribution of executable or object code is made by offering\n",
+"access to copy from a designated place, then offering equivalent\n",
+"access to copy the source code from the same place counts as\n",
+"distribution of the source code, even though third parties are not\n",
+"compelled to copy the source along with the object code.\n",
+"
+\n",
+"  4. You may not copy, modify, sublicense, or distribute the Program\n",
+"except as expressly provided under this License.  Any attempt\n",
+"otherwise to copy, modify, sublicense or distribute the Program is\n",
+"void, and will automatically terminate your rights under this License.\n",
+"However, parties who have received copies, or rights, from you under\n",
+"this License will not have their licenses terminated so long as such\n",
+"parties remain in full compliance.\n",
+"\n",
+"  5. You are not required to accept this License, since you have not\n",
+"signed it.  However, nothing else grants you permission to modify or\n",
+"distribute the Program or its derivative works.  These actions are\n",
+"prohibited by law if you do not accept this License.  Therefore, by\n",
+"modifying or distributing the Program (or any work based on the\n",
+"Program), you indicate your acceptance of this License to do so, and\n",
+"all its terms and conditions for copying, distributing or modifying\n",
+"the Program or works based on it.\n",
+"\n",
+"  6. Each time you redistribute the Program (or any work based on the\n",
+"Program), the recipient automatically receives a license from the\n",
+"original licensor to copy, distribute or modify the Program subject to\n",
+"these terms and conditions.  You may not impose any further\n",
+"restrictions on the recipients' exercise of the rights granted herein.\n",
+"You are not responsible for enforcing compliance by third parties to\n",
+"this License.\n",
+"\n",
+"  7. If, as a consequence of a court judgment or allegation of patent\n",
+"infringement or for any other reason (not limited to patent issues),\n",
+"conditions are imposed on you (whether by court order, agreement or\n",
+"otherwise) that contradict the conditions of this License, they do not\n",
+"excuse you from the conditions of this License.  If you cannot\n",
+"distribute so as to satisfy simultaneously your obligations under this\n",
+"License and any other pertinent obligations, then as a consequence you\n",
+"may not distribute the Program at all.  For example, if a patent\n",
+"license would not permit royalty-free redistribution of the Program by\n",
+"all those who receive copies directly or indirectly through you, then\n",
+"the only way you could satisfy both it and this License would be to\n",
+"refrain entirely from distribution of the Program.\n",
+"\n",
+"If any portion of this section is held invalid or unenforceable under\n",
+"any particular circumstance, the balance of the section is intended to\n",
+"apply and the section as a whole is intended to apply in other\n",
+"circumstances.\n",
+"\n",
+"It is not the purpose of this section to induce you to infringe any\n",
+"patents or other property right claims or to contest validity of any\n",
+"such claims; this section has the sole purpose of protecting the\n",
+"integrity of the free software distribution system, which is\n",
+"implemented by public license practices.  Many people have made\n",
+"generous contributions to the wide range of software distributed\n",
+"through that system in reliance on consistent application of that\n",
+"system; it is up to the author/donor to decide if he or she is willing\n",
+"to distribute software through any other system and a licensee cannot\n",
+"impose that choice.\n",
+"\n",
+"This section is intended to make thoroughly clear what is believed to\n",
+"be a consequence of the rest of this License.\n",
+"
+\n",
+"  8. If the distribution and/or use of the Program is restricted in\n",
+"certain countries either by patents or by copyrighted interfaces, the\n",
+"original copyright holder who places the Program under this License\n",
+"may add an explicit geographical distribution limitation excluding\n",
+"those countries, so that distribution is permitted only in or among\n",
+"countries not thus excluded.  In such case, this License incorporates\n",
+"the limitation as if written in the body of this License.\n",
+"\n",
+"  9. The Free Software Foundation may publish revised and/or new versions\n",
+"of the General Public License from time to time.  Such new versions will\n",
+"be similar in spirit to the present version, but may differ in detail to\n",
+"address new problems or concerns.\n",
+"\n",
+"Each version is given a distinguishing version number.  If the Program\n",
+"specifies a version number of this License which applies to it and \"any\n",
+"later version\", you have the option of following the terms and conditions\n",
+"either of that version or of any later version published by the Free\n",
+"Software Foundation.  If the Program does not specify a version number of\n",
+"this License, you may choose any version ever published by the Free Software\n",
+"Foundation.\n",
+"\n",
+"  10. If you wish to incorporate parts of the Program into other free\n",
+"programs whose distribution conditions are different, write to the author\n",
+"to ask for permission.  For software which is copyrighted by the Free\n",
+"Software Foundation, write to the Free Software Foundation; we sometimes\n",
+"make exceptions for this.  Our decision will be guided by the two goals\n",
+"of preserving the free status of all derivatives of our free software and\n",
+"of promoting the sharing and reuse of software generally.\n",
+"\n",
+"			    NO WARRANTY\n",
+"\n",
+"  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n",
+"FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n",
+"OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n",
+"PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n",
+"OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n",
+"MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n",
+"TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n",
+"PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n",
+"REPAIR OR CORRECTION.\n",
+"\n",
+"  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n",
+"WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n",
+"REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n",
+"INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n",
+"OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n",
+"TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n",
+"YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n",
+"PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n",
+"POSSIBILITY OF SUCH DAMAGES.\n",
+"\n",
+"		     END OF TERMS AND CONDITIONS\n"};
Index: /indexers/branches/3.03a/mg/src/text/conditions.src
===================================================================
--- /indexers/branches/3.03a/mg/src/text/conditions.src	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/conditions.src	(revision 14757)
@@ -0,0 +1,225 @@
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
Index: /indexers/branches/3.03a/mg/src/text/environment.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/environment.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/environment.c	(revision 14757)
@@ -0,0 +1,691 @@
+/**************************************************************************
+ *
+ * environment.c -- mgquery environment functions
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.2  2004/04/25 23:01:18  kjdon
+   added a new -M option to mg_passes, allowing maxnumeric to be altered - made this change to keep gsdl3 mg inline with gsdl2 mg.
+
+   Revision 1.1  2003/02/20 21:18:23  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:17:50  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:34:37  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.5  1995/03/14  05:15:26  tes
+   * Updated the boolean query optimiser to do different types of optimisation.
+   * A query environment variable "optimise_type" specifies which one is to be
+   * used. Type 1 is the new one which is faster than 2.
+   *
+   * Revision 1.4  1994/11/25  03:47:43  tes
+   * Committing files before adding the merge stuff.
+   *
+   * Revision 1.3  1994/10/20  03:56:43  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:25  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "locallib.h"
+#include "local_strings.h"
+#include "messages.h"
+
+#include "environment.h"
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+# define STRCASECMP      stricmp
+#else
+# define STRCASECMP      strcasecmp
+#endif
+
+typedef struct
+  {
+    char *Name, *Data;
+    char *(*Constraint) (char *Old, char *New);
+  }
+EEntry;
+
+typedef struct Env
+  {
+    EEntry *Environment;
+    int NumEnv;
+    struct Env *Next;
+  }
+Env;
+
+
+char *ConstraintErrorStr;
+
+static Env Base =
+{NULL, 0, NULL};
+
+
+/*
+ * Add name and data to the environment (data may be NULL)
+ * All names are converted to lower case
+ * returns 0 on success, -1 on memory failure or -2 on constraint failure
+ */
+int 
+SetEnv (char *name, char *data, char *(*Constraint) (char *, char *))
+{
+  int i;
+  EEntry *newenv, *env = Base.Environment;
+
+  if (data && *data == '\0')
+    data = NULL;
+
+  /* search for name in the environment */
+  for (i = 0; i < Base.NumEnv && STRCASECMP (name, env->Name); i++, env++);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  /* if not found the increase the environment size */
+  if (i >= Base.NumEnv)
+    {
+      if (Constraint)
+	{
+	  data = Constraint (NULL, data);
+	  if (!data)
+	    return (-2);
+	}
+      /* allocate memory for the new environment */
+      newenv = Base.Environment ?
+	Xrealloc (Base.Environment, sizeof (EEntry) * (Base.NumEnv + 1)) :
+	Xmalloc (sizeof (EEntry) * (Base.NumEnv + 1));
+      if (!newenv)
+	return (-1);
+      Base.Environment = newenv;
+      env = &newenv[Base.NumEnv];
+      env->Data = NULL;
+      env->Name = NULL;
+      env->Constraint = Constraint;
+      env->Name = Xstrdup (name);
+      if (!env->Name)
+	return (-1);
+      Base.NumEnv++;
+      for (i = 0; env->Name[i]; i++)
+	env->Name[i] = tolower (env->Name[i]);
+    }
+  if (env->Constraint)
+    {
+      data = env->Constraint (env->Data, data);
+      if (!data)
+	return (-2);
+    }
+  if (env->Data)
+    Xfree (env->Data);
+  env->Data = NULL;
+  if (data && *data != '\0')
+    {
+      env->Data = Xstrdup (data);
+      if (!env->Data)
+	return (-1);
+    }
+  return (0);
+}
+
+
+
+/*
+ * Returns the data associated with name. If Data = NULL then this routine
+ * returns a pointer to "". If the specified name does not exist then this 
+ * routine returns NULL.
+ */
+char *
+GetEnv (char *name)
+{
+  int i;
+  EEntry *env = Base.Environment;
+  /* search for name in the environment */
+  for (i = 0; i < Base.NumEnv && STRCASECMP (name, env->Name); i++, env++);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  if (i >= Base.NumEnv)
+    return (NULL);
+
+  return (env->Data ? env->Data : "");
+}
+
+/*
+ * Returns the data associated with name. If Data = NULL then this routine
+ * returns a pointer to "". If the specified name does not exist then this 
+ * routine returns default.
+ */
+char *
+GetDefEnv (char *name, char *def)
+{
+  char *data = GetEnv (name);
+  return (data ? data : def);
+}
+
+
+
+/*
+ * This function pushes the environment on to a stack and duplicated it in 
+ * the current stack.
+ *
+ */
+int 
+PushEnv (void)
+{
+  Env *env = Xmalloc (sizeof (Env));
+  int i;
+  *env = Base;
+  Base.Next = env;
+  Base.Environment = NULL;
+  Base.NumEnv = 0;
+  for (i = 0; i < env->NumEnv; i++)
+    if (SetEnv (env->Environment[i].Name, env->Environment[i].Data,
+		env->Environment[i].Constraint))
+      return (-1);
+  return (0);
+}
+
+int 
+PopEnv (void)
+{
+  Env *env;
+  int i;
+  if (!Base.Next)
+    return (-1);
+  for (i = 0; i < Base.NumEnv; i++)
+    {
+      Xfree (Base.Environment[i].Name);
+      if (Base.Environment[i].Data)
+	Xfree (Base.Environment[i].Data);
+    }
+  if (Base.Environment)
+    Xfree (Base.Environment);
+  env = Base.Next;
+  Base = *env;
+  Xfree (env);
+  return (0);
+}
+
+
+/*
+ * Count the number of environments on the stack, including the current one.
+ *
+ */
+int 
+EnvStackHeight (void)
+{
+  int i = 1;
+  Env *env = &Base;
+  while (env->Next)
+    {
+      i++;
+      env = env->Next;
+    }
+  return (i);
+}
+
+/*
+ * Delete environment variable name. If name does not exist it returns -1
+ * otherwise it returns 0
+ */
+int 
+UnsetEnv (char *name, int Force)
+{
+  int i;
+  EEntry *env = Base.Environment;
+  /* search for name in the environment */
+  for (i = 0; i < Base.NumEnv && STRCASECMP (name, env->Name); i++, env++);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  if (i >= Base.NumEnv ||
+      (Base.Environment[i].Constraint && !Force))
+    return (-1);
+  Xfree (Base.Environment[i].Name);
+  if (Base.Environment[i].Data)
+    Xfree (Base.Environment[i].Data);
+  for (i++; i < Base.NumEnv; i++)
+    Base.Environment[i - 1] = Base.Environment[i];
+  Base.NumEnv--;
+  if (Base.NumEnv == 0)
+    {
+      Xfree (Base.Environment);
+      Base.Environment = NULL;
+    }
+  return (0);
+}
+
+
+
+
+
+
+
+
+/*
+ * Returns the name of environment variable number i or NULL if i is greater 
+ * than or equal to the number of environment variables. Names start from
+ * zero. 
+ */
+char *
+GetEnvName (int i)
+{
+  return (i < Base.NumEnv ? Base.Environment[i].Name : NULL);
+}
+
+static char *BooleanStrs[] =
+{"false", "true", "no", "yes", "off", "on"};
+
+static char *
+BooleanCons (char *Old, char *New)
+{
+  int i;
+  int old = -1, new = -1;
+  if (Old)
+    for (i = 0; i < sizeof (BooleanStrs) / sizeof (char *); i++)
+      if (!STRCASECMP (Old, BooleanStrs[i]))  /* [RPAP - Feb 97: WIN32 Port] */
+	{
+	  old = i;
+	  break;
+	}
+  if (New)
+    for (i = 0; i < sizeof (BooleanStrs) / sizeof (char *); i++)
+      if (!STRCASECMP (New, BooleanStrs[i]))  /* [RPAP - Feb 97: WIN32 Port] */
+	{
+	  new = i;
+	  break;
+	}
+  if (new >= 0)
+    return (New);
+  if (!New)
+    return (BooleanStrs[Old ? old ^ 1 : 0]);
+  ConstraintErrorStr = "Invalid argument [true|false|yes|no|on|off] required";
+  return (NULL);
+}
+
+/*
+ * returns 0 or 1  for a boolean string
+ * or default on a error
+ */
+int 
+BooleanEnv (char *data, int def)
+{
+  int i;
+  if (!data)
+    return (def);
+  for (i = 0; i < sizeof (BooleanStrs) / sizeof (char *); i++)
+    if (!STRCASECMP (data, BooleanStrs[i]))  /* [RPAP - Feb 97: WIN32 Port] */
+      return (i & 1);
+  return (def);
+}
+
+/*
+ * returns the value for a integer string
+ * or default on a error
+ */
+long 
+IntEnv (char *data, long def)
+{
+  long val;
+  char *ptr;
+  if (!data)
+    return (def);
+  val = strtol (data, &ptr, 10);
+  return *ptr ? def : val;
+}
+
+static char *
+NumberCmp (char *num, int min, int max)
+{
+  char *err;
+  int val;
+  static char Err[100];
+  ConstraintErrorStr = "Not a valid number";
+  if (!num)
+    return (NULL);
+  val = strtol (num, &err, 10);
+  if (*err)
+    return (NULL);
+  sprintf (Err, "Not in legal range [%d <= num <= %d]", min, max);
+  ConstraintErrorStr = Err;
+  if (val < min || val > max)
+    return (NULL);
+  return (num);
+}
+
+/*ARGSUSED */
+static char *
+MaxDocsCons (char *Old, char *New)
+{
+  if (!STRCASECMP (New, "all"))  /* [RPAP - Feb 97: WIN32 Port] */
+    return (New);
+  return (NumberCmp (New, 1, ((unsigned) (~0)) >> 1));
+}
+
+/*ARGSUSED */
+static char *
+MaxTermsCons (char *Old, char *New)
+{
+  if (!STRCASECMP (New, "all"))  /* [RPAP - Feb 97: WIN32 Port] */
+    return (New);
+  return (NumberCmp (New, 1, ((unsigned) (~0)) >> 1));
+}
+
+/* ARGSUSED */
+static char *
+BufferCons (char *Old, char *New)
+{
+  return (NumberCmp (New, 0, 16 * 1024 * 1024));
+}
+
+/* ARGSUSED */
+static char *
+MaxNodesCons (char *Old, char *New)
+{
+  if (!STRCASECMP (New, "all"))  /* [RPAP - Feb 97: WIN32 Port] */
+    return (New);
+  return (NumberCmp (New, 8, 256 * 1024 * 1024));
+}
+
+/* ARGSUSED */
+static char *
+MaxHashCons (char *Old, char *New)
+{
+  return (NumberCmp (New, 8, 256 * 1024 * 1024));
+}
+
+/* ARGSUSED */
+static char *
+MaxParasCons (char *Old, char *New)
+{
+  return (NumberCmp (New, 1, 256 * 1024 * 1024));
+}
+
+/* ARGSUSED */
+static char *
+MaxHeadsCons (char *Old, char *New)
+{
+  return (NumberCmp (New, 1, 1000));
+}
+
+/* ARGSUSED */
+char *
+OptimiseCons (char *Old, char *New)
+{
+  return (NumberCmp (New, 0, 2));
+}
+
+/* ARGSUSED */
+char *
+MaxNumericCons (char *Old, char *New)
+{
+  return (NumberCmp (New, 4, 512));
+}
+
+
+/*
+ * Makes sure that New is a valid query type
+ *
+ */
+/* ARGSUSED */
+static char *
+QueryCons (char *Old, char *New)
+{
+  static char *QueryStrs[] =
+  {
+    "boolean", "ranked",
+    "docnums", "approx-ranked"};
+  int i;
+  int new = -1;
+  if (New)
+    for (i = 0; i < sizeof (QueryStrs) / sizeof (char *); i++)
+      if (!STRCASECMP (New, QueryStrs[i]))  /* [RPAP - Feb 97: WIN32 Port] */
+	{
+	  new = i;
+	  break;
+	}
+  if (new >= 0)
+    return (New);
+  ConstraintErrorStr = "Invalid argument [boolean|ranked|docnums|approx-ranked] required";
+  return (NULL);
+}
+
+/*
+ * Makes sure that New is a valid accum type
+ *
+ */
+/* ARGSUSED */
+static char *
+AccumCons (char *Old, char *New)
+{
+  static char *AccumStrs[] =
+  {
+    "array", "splay_tree", "hash_table", "list"};
+  int i;
+  int new = -1;
+  if (New)
+    for (i = 0; i < sizeof (AccumStrs) / sizeof (char *); i++)
+      if (!STRCASECMP (New, AccumStrs[i]))  /* [RPAP - Feb 97: WIN32 Port] */
+	{
+	  new = i;
+	  break;
+	}
+  if (new >= 0)
+    return (New);
+  ConstraintErrorStr = "Invalid argument "
+    "[array|splay_tree|hash_table|list] required";
+  return (NULL);
+}
+
+
+
+/*
+ * Makes sure that New is a valid output type type
+ *
+ */
+/* ARGSUSED */
+static char *
+OutputTypeCons (char *Old, char *New)
+{
+  static char *OutputTypeStrs[] =
+  {"text", "silent", "docnums",
+   "count", "heads", "hilite"
+#ifdef TREC_MODE
+   ,"extras_for_trec"
+#endif
+  };
+
+  int i;
+  int new = -1;
+  if (New)
+    for (i = 0; i < sizeof (OutputTypeStrs) / sizeof (char *); i++)
+      if (!STRCASECMP (New, OutputTypeStrs[i]))  /* [RPAP - Feb 97: WIN32 Port] */
+	{
+	  new = i;
+	  break;
+	}
+  if (new >= 0)
+    return (New);
+  ConstraintErrorStr = "Invalid argument [text|silent|docnums|heads|count|hilite"
+#ifdef TREC_MODE
+    "|extras_for_trec"
+#endif
+    "] required";
+  return (NULL);
+}
+
+/*
+ * Makes sure that New is a valid query type
+ *
+ */
+/* ARGSUSED */
+char *
+HiliteStyleCons (char *Old, char *New)
+{
+  static char *StyleStrs[] =
+  {"bold", "underline"};
+  int i;
+  int new = -1;
+  if (New)
+    for (i = 0; i < sizeof (StyleStrs) / sizeof (char *); i++)
+      if (!STRCASECMP (New, StyleStrs[i]))  /* [RPAP - Feb 97: WIN32 Port] */
+	{
+	  new = i;
+	  break;
+	}
+  if (new >= 0)
+    return (New);
+  ConstraintErrorStr = "Invalid argument [bold|underline] required";
+  return (NULL);
+}
+
+/* =========================================================================
+ * Function: get_output_type
+ * Description:
+ *      Map a mode string onto a mode char e.g. OUTPUT_????
+ * Input:
+ * Output:
+ *      The mode char which is a subrange value.
+ * ========================================================================= */
+
+char
+get_output_type (void)
+{
+  char *env_str = GetDefEnv ("mode", "text");
+  char ch1 = toupper (env_str[0]);
+  char ch2 = toupper (env_str[1]);
+
+  switch (ch1)
+    {
+    case 'T':
+      return OUTPUT_TEXT;
+    case 'S':
+      return OUTPUT_SILENT;
+    case 'E':
+      return OUTPUT_EXTRAS;
+    case 'C':
+      return OUTPUT_COUNT;
+    case 'D':
+      return OUTPUT_DOCNUMS;
+    case 'H':
+      if (ch2 == 'E')
+	return OUTPUT_HEADERS;
+      else
+	return OUTPUT_HILITE;
+    default:
+      FatalError (1, "Problem in output type switch");
+    }
+
+  return '\0';			/*shouldn't reach here -- keep compiler happy */
+}
+
+/* =========================================================================
+ * Function: get_query_type
+ * Description:
+ *      Map a query type string onto a char.
+ * Input:
+ * Output:
+ *      Query type char.
+ * ========================================================================= */
+
+char
+get_query_type (void)
+{
+  char *env_str = GetDefEnv ("query", "boolean");
+  char ch1 = toupper (env_str[0]);
+
+  switch (ch1)
+    {
+    case 'R':
+      return QUERY_RANKED;
+    case 'A':
+      return QUERY_APPROX;
+    case 'B':
+      return QUERY_BOOLEAN;
+    case 'D':
+      return QUERY_DOCNUMS;
+    default:
+      FatalError (1, "Problem in query type switch");
+    }
+
+  return '\0';			/*shouldn't reach here */
+}
+
+
+
+/*
+ * This initialises certain environment variables
+ *
+ */
+void 
+InitEnv (void)
+{
+  SetEnv ("hilite_style", "underline", HiliteStyleCons);	/*[TS:Sep/94] */
+  SetEnv ("briefstats", "off", BooleanCons);
+  SetEnv ("diskstats", "off", BooleanCons);
+  SetEnv ("expert", "false", BooleanCons);
+  SetEnv ("mgdir", getenv ("MGDATA") ? getenv ("MGDATA") : ".", NULL);
+  SetEnv ("mgname", "", NULL);
+  SetEnv ("maxdocs", "all", MaxDocsCons);
+  SetEnv ("memstats", "off", BooleanCons);
+  SetEnv ("mode", "text", OutputTypeCons);
+  SetEnv ("pager", getenv ("PAGER") ? getenv ("PAGER") : "more", NULL);
+  SetEnv ("qfreq", "true", BooleanCons);
+  SetEnv ("query", "boolean", QueryCons);
+  SetEnv ("sizestats", "off", BooleanCons);
+  SetEnv ("timestats", "off", BooleanCons);
+  SetEnv ("verbatim", "off", BooleanCons);
+  SetEnv ("sorted_terms", "on", BooleanCons);
+  SetEnv ("accumulator_method", "array", AccumCons);
+  SetEnv ("stop_at_max_accum", "off", BooleanCons);
+  SetEnv ("buffer", "1048576", BufferCons);
+  SetEnv ("max_accumulators", "50000", MaxNodesCons);
+  SetEnv ("max_terms", "all", MaxTermsCons);
+  SetEnv ("maxparas", "1000", MaxParasCons);
+  SetEnv ("hash_tbl_size", "1000", MaxHashCons);
+  SetEnv ("skip_dump", "skips.%d", NULL);
+  SetEnv ("ranked_doc_sepstr", "---------------------------------- %n %w\\n", NULL);
+  SetEnv ("doc_sepstr", "---------------------------------- %n\\n", NULL);
+  SetEnv ("para_sepstr", "\\n######## PARAGRAPH %n ########\\n", NULL);
+  SetEnv ("para_start", "***** Weight = %w *****\\n", NULL);
+  SetEnv ("terminator", "", NULL);
+  SetEnv ("heads_length", "50", MaxHeadsCons);
+  SetEnv ("optimise_type", "1", OptimiseCons);	/*[TS:Mar/95] */
+  SetEnv ("casefold", "on", BooleanCons);  /* [RPAP - Jan 97: Stem Index Change] */
+  SetEnv ("stem", "on", BooleanCons);  /* [RPAP - Jan 97: Stem Index Change] */
+  SetEnv ("term_freq", "off", BooleanCons);  /* [RPAP - Feb 97: Term Frequency] */
+  SetEnv ("maxnumeric", "4", MaxNumericCons);  /* [sjboddie - Jun 2002: Max Numeric word length] */
+}
+
+
+void 
+UninitEnv (void)
+{
+  char *name;
+  while (PopEnv () == 0);
+  while ((name = GetEnvName (0)) != 0)
+    UnsetEnv (name, 1);
+}
Index: /indexers/branches/3.03a/mg/src/text/environment.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/environment.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/environment.h	(revision 14757)
@@ -0,0 +1,61 @@
+/**************************************************************************
+ *
+ * environment.h -- mgquery environment functions
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#ifndef ENVIRONMENT_H
+#define ENVIRONMENT_H
+
+#define OUTPUT_TEXT     'T'
+#define OUTPUT_HEADERS  'H'
+#define OUTPUT_SILENT   'S'
+#define OUTPUT_EXTRAS   'E'
+#define OUTPUT_HILITE   'I'
+#define OUTPUT_COUNT    'C'
+#define OUTPUT_DOCNUMS  'D'
+
+#define QUERY_RANKED    'R'
+#define QUERY_APPROX    'A'
+#define QUERY_BOOLEAN   'B'
+#define QUERY_DOCNUMS   'D'
+
+
+char get_output_type (void);
+char get_query_type (void);
+
+extern char *ConstraintErrorStr;
+int SetEnv (char *name, char *data, char *(*Constraint) (char *, char *));
+char *GetEnv (char *name);
+char *GetDefEnv (char *name, char *def);
+int UnsetEnv (char *name, int Force);
+char *de_escape_string (char *s);
+int PushEnv (void);
+int PopEnv (void);
+int EnvStackHeight (void);
+char *GetEnvName (int i);
+int BooleanEnv (char *data, int def);
+long IntEnv (char *data, long def);
+
+void InitEnv (void);
+void UninitEnv (void);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/globals.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/globals.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/globals.h	(revision 14757)
@@ -0,0 +1,32 @@
+/**************************************************************************
+ *
+ * globals.h -- Some global stuff for mgquery
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#ifndef H_GLOBALS
+#define H_GLOBALS
+
+
+extern FILE *OutFile;
+extern FILE *InFile;
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/hash.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/hash.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/hash.h	(revision 14757)
@@ -0,0 +1,44 @@
+/**************************************************************************
+ *
+ * hash.h -- Hash function
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#ifndef H_HASH
+#define H_HASH
+
+
+
+#define HASH(h, step, wd, tablesize)			\
+	do {						\
+		register u_char *p=wd;			\
+		register long len = *p++;		\
+		register unsigned long hval;		\
+		if (len>25) len = 25;			\
+		for (hval=0; len; --len)		\
+		  hval = (hval << 5) - hval + *p++;	\
+		step = hval % (tablesize - 2) + 1;	\
+		h = hval % tablesize;			\
+	} while (0)
+
+
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/help.mg.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/help.mg.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/help.mg.h	(revision 14757)
@@ -0,0 +1,320 @@
+static char *help_str[] = {
+"\n",
+"			  HELP for mgquery\n",
+"		   ================================\n",
+"\n",
+"The text is a summary of the information in the \"mgquery\" manual pages.\n",
+"\n",
+"The input to 'mgquery' consists of a series of input lines. The backslash\n",
+"character (\"\\\") is used at the end of lines to indicate that input \n",
+"continues on the next line.\n",
+"\n",
+"Input lines on which the first character is a dot (\".\") are commands to\n",
+"the mgquery program. Input lines that do not start with a dot are queries.\n",
+"\n",
+"A query consists of two parts. One part is a boolean or ranked query that\n",
+"identifies documents. The second part is a post-processing pattern matching\n",
+"operation. Any text between the first speech mark (\") and the last speech\n",
+"mark is considered to the a post-processing pattern. \n",
+"\n",
+"\n",
+"The following command are available :-\n",
+"\n",
+"    .help	     - displays this text.\n",
+"    .quit            - quits the program.\n",
+"    .set name value  - sets parameter \"name\" to \"value\" . If the parameter\n",
+"                       is a boolean parameter and value is omitted the\n",
+"	    	       parameter will be inverted (i.e. if it is true it\n",
+"		       will change to false, if it is false it will change\n",
+"		       to true).\n",
+"    .unset name      - deletes parameter \"name\"\n",
+"    .reset           - sets all the parameters to their initial state.\n",
+"    .display         - displays the values of all the current parameters.\n",
+"    .push            - pushes the current parameters on to a stack.\n",
+"    .pop             - destroys the current parameters and pops a new set\n",
+"                       of parameters off the stack.\n",
+"    .output arg      - This is used to specify where to send the documents.\n",
+"                       Arg may one be of the following:\n",
+"		       > filename  : Send output to the specified file.\n",
+"		       >> filename : Append output to the specified file.\n",
+"                       | command   : The output is piped into command, \n",
+"                                     which is executed by sh.\n",
+"    .input arg       - This is used to specify where input comes from.\n",
+"                       Arg may one be of the following:\n",
+"		       < filename  : Get the input from the specified\n",
+"                                     file.\n",
+"                       | command   : The input comes from the standard\n",
+"                                     output of command, which is executed\n",
+"                                     by sh.\n",
+"\n",
+"On startup the mgquery program reads from the file .mgrc a sequence \n",
+"of commands (NOTE: The .mgrc file may not contain any queries). mgquery \n",
+"first looks for .mgrc in the current directory and then in the users home \n",
+"directory. Lines starting with a '#' in the .mgrc file are considered to\n",
+"be comments and are ignored.\n",
+"\n",
+"The following parameters (used in the .set and .unset commands) are \n",
+"predefined and have special significance :-\n",
+"\n",
+"accumulator_method = `array'\n",
+"	This parameter is used during ranking, and specifies how the\n",
+"	weight for each document should be accumulated. The following\n",
+"	methods are available `array', `splay_tree', `hash_table', and\n",
+"	`list'.\n",
+"\n",
+"briefstats = `off'\n",
+"	This is a boolean parameter that determines whether the the\n",
+"	totals for disk, memory and time usage statistics will be \n",
+"	displayed. at the end of each query. \n",
+"	NOTE: this takes precedence over the parameters \"diskstats\",\n",
+"	\"memstats\" and \"timestats\". This parameter may take the values \n",
+"	`yes', `no', `true', `false', `on' or `off'.\n",
+"\n",
+"buffer = `1048576'\n",
+"	When the documents are being read in they are read into a \n",
+"	buffer of this size and then displayed from this buffer. If \n",
+"        the documents are larger than this buffer the buffer is\n",
+"	expanded automatically. Having a large buffer gives a very\n",
+"	slight performance improvement because it allows the order of \n",
+"	disk operations to be optimised. The buffer size is measured\n",
+"	in bytes.\n",
+"\n",
+"diskstats = `off'\n",
+"	This is a boolean parameter that determines whether the disk\n",
+"	usage statistics for the preceding query will be displayed\n",
+"	after each query. This parameter may take the values `yes',\n",
+"	`no', `true', `false', `on' or `off'.\n",
+"\n",
+"doc_sepstr = `---------------------------------- %n\\n'\n",
+"	This specifies the string that will be used to separate \n",
+"	documents when they are displayed for `boolean' or `docnums'\n",
+"	queries. The standard C escape character sequences (see the \n",
+"	man page) may be used to place special characters in the \n",
+"	string. For example, a newline would the `\\n'. To include a `%'\n",
+"	use the sequence `%%'. To include the MG document number use\n",
+"	the sequence `%n'.\n",
+"\n",
+"expert = `false'\n",
+"	If this is true then a lot of the waffle that the program \n",
+"	spits out is suppressed. This parameter may take the values\n",
+"	`yes', `no', `true', `false', `on' or `off'.\n",
+"\n",
+"hash_tbl_size = `1000'\n",
+"	One of the options during ranking queries is to use a hash \n",
+"	table to accumulate the weights for each document. The hash \n",
+"	table is a simple chained type. This parameter specifies the \n",
+"	size of the hash table and may take any value between 8 and\n",
+"	268435456. \n",
+"\n",
+"heads_length = `50'\n",
+"	When the mode is `heads' this specifies the number of \n",
+"	characters that	will be output for each document.\n",
+"\n",
+"maxdocs = `all'\n",
+"	The maximum number of documents to display in response to a\n",
+"	query. This parameter may take on a numeric value between 1 \n",
+"	and 429467295 or the word `all'.\n",
+"\n",
+"maxparas = `1000'\n",
+"	The maximum number of paragraphs to identify during a ranked\n",
+"	query with paragraph indexing. After the paragraphs have been\n",
+"	identified the paragraphs are converted into documents, and \n",
+"	because some of the paragraphs may refer to the same documents \n",
+"	the final number of answers may be less that maxparas. The \n",
+"	maxdocs parameter will then be applied. This parameter may \n",
+"	take on a numeric value between 1 and 429467295.\n",
+"\n",
+"max_accumulators = `50000'\n",
+"	This parameter limits the number of different paragraph/\n",
+"	document numbers to be accumulated during ranked queries when \n",
+"	the parameter `accumulator_method` is set to `splay_tree',\n",
+"	`hash_table', or `list'.  This parameter may take any value \n",
+"	between 8 and 268435456.\n",
+"\n",
+"max_terms = `all'\n",
+"	This parameter limits the number of terms that will actually\n",
+"	be used during a ranked query. If more terms than the number\n",
+"	specified by max_terms are entered, then the extra terms will\n",
+"	be discarded. If `sorted_terms' is on then the limiting will \n",
+"	be done after the terms have been sorted. This parameter may\n",
+"	take any value between 1 and 429467295 or the word `all'.\n",
+"\n",
+"memstats = `off'\n",
+"	This is a boolean parameter that determines whether the memory \n",
+"	usage statistics for the preceding query will be displayed\n",
+"	after each query. This parameter may take the values `yes', \n",
+"	`no', `true', `false', `on' or `off'.\n",
+"\n",
+"mgdir = `.'\n",
+"	This specifies the directory where the MG files may be found.\n",
+"	If the environment variable `MGDATA' is set then `mgdir' is\n",
+"	initialised to the value in `MGDATA'.\n",
+"\n",
+"mgname = `'\n",
+"	This specifies the name of the MG database to process.\n",
+"\n",
+"mode = `text'\n",
+"	This specifies how documents should be displayed when they\n",
+"	are retrieved it may take four different values `text', \n",
+"	`docnums', `silent', `heads' or `count'. `text' displays \n",
+"	the contents of the document. `docnums' displays only the\n",
+"	document numbers. `Silent' retrieves all the documents but\n",
+"	displays nothing except how many documents were retrieved.\n",
+"	This mode is intended to be used in timing experiments. \n",
+"	`Heads` is used to print out the head of each document.\n",
+"	`Count' does the minimum amount of work required to determine\n",
+"	how many documents would be retrieved, but does not retrieve\n",
+"	them.\n",
+"\n",
+"pager = `more'\n",
+"	This is the name of the program that will be used to display\n",
+"	the help and the retrieved documents. If the environment \n",
+"	variable \"PAGER\" is defined then `pager' takes on that value.\n",
+"\n",
+"para_sepstr = `\\n######## PARAGRAPH %n ########\\n'\n",
+"	This specifies the string that will be used to separate \n",
+"	paragraphs. The standard C escape character sequences (see the \n",
+"	man page) may be used to place special characters in the \n",
+"	string. For example, a newline would the `\\n'. To include a `%'\n",
+"	use the sequence `%%'. To include the paragraph number within\n",
+"	the document use the sequence `%n'.\n",
+"\n",
+"para_start = `***** Weight = %w *****\\n'\n",
+"	This specifies the string that will be used at the head of \n",
+"	paragraphs for a paraghaph level index following a ranked query.\n",
+"	The standard C escape character sequences (see the man page)\n",
+"	may be used to place special characters in the string. For \n",
+"	example, a newline would the `\\n'. To include a `%' use the\n",
+"	sequence `%%'. To include the paragraph weight use the \n",
+"	sequence `%w'.\n",
+"\n",
+"qfreq = `true'\n",
+"	This determine whether the ranked queries will take into \n",
+"	account the number of times each query term is specified.\n",
+"	When this is `true' the number of times a term appears in\n",
+"	the query is used in the ranking. When this is `false' all \n",
+"	query term are assumed to occur only once. This parameter\n",
+"	may take the values `yes', `no', `true', `false', `on' or\n",
+"	`off'.\n",
+"\n",
+"query = `boolean'\n",
+"	This specifies the type of queries that are to be specified.\n",
+"	It can take four different values `boolean', `ranked', \n",
+"	`docnums' or `approx-ranked'. \n",
+"\n",
+"	`boolean' is for boolean queries. \n",
+"		The yacc grammar for boolean queries is as follows :-\n",
+"\n",
+"		query   : or;\n",
+" \n",
+"		or      : or '|' and\n",
+"		        | and ;	\n",
+" \n",
+"		and     : and '&' not\n",
+"        		| and not\n",
+"        		| not ;\n",
+"\n",
+"		not     : term\n",
+"		        | '!' not ;\n",
+" \n",
+"		term    : TERM\n",
+"		        | '(' or ')' ;\n",
+" \n",
+"\n",
+"\n",
+"\n",
+"	`ranked' and `approx-ranked' are for queries ranked by the\n",
+"		cosine measure. `approx-ranked' uses only the low\n",
+"		precision document lengths, and therefore only\n",
+"		produces an approximation to full cosine ranking.\n",
+"\n",
+"		query   : TERM\n",
+"      			| query TERM ;\n",
+"	\n",
+"	`docnums' allows the entry of document numbers. Multiple \n",
+"		numbers separated by spaces may be specified\n",
+"		or ranges separated by hyphens.\n",
+"\n",
+"\n",
+"		query   : range\n",
+"			| query range ;\n",
+"\n",
+"\n",
+"		range   : num\n",
+"			| num '-' num ;\n",
+"\n",
+"\n",
+"ranked_doc_sepstr = `---------------------------------- %n %w\\n'\n",
+"	This specifies the string that will be used to separate \n",
+"	documents when they are displayed for `ranked' or \n",
+"	`approx-ranked'	queries. The standard C escape character \n",
+"	sequences (see the man page) may be used to place special\n",
+"	characters in the string. For example, a newline would the\n",
+"	`\\n'. To include a `%' use the sequence `%%'. To include the\n",
+"	MG document number use the sequence `%n'. To include the\n",
+"	document weight use the sequence `%w'.\n",
+"\n",
+"sizestats = `false'\n",
+"	If this is true then various numbers are output at the end\n",
+"	of each query indicating what went on during the query. \n",
+"	This parameter may take the values `yes', `no', `true', \n",
+"	`false', `on' or `off'.\n",
+"\n",
+"skip_dump = `skips.%d'\n",
+"	If this parameter is set then during ranked queries on skipped\n",
+"	inverted files when `accumulator_method' is set to `splay_tree',\n",
+"	`hash_table', or `list` a file will be produced in the current\n",
+"	directory. The name of the file is the value of this parameter,\n",
+"	a `%d' in the file name will be replaced with the process id of\n",
+"	mgquery. This file will contain information about the usage of\n",
+"	skips during the query processing. This option is expensive; \n",
+"	use `.unset skip_dump' to obtain optimal performance.\n",
+"\n",
+"sorted_terms = `on'\n",
+"	This specifies whether of not the terms should be sorted into\n",
+"	decreasing occurrence in documents so that the least often\n",
+"	occurring terms are processed first when ranked queries are\n",
+"	being done. When this is true the terms are sorted. When this\n",
+"	is false the terms are not sorted and are instead processed in\n",
+"	order of occurrence. This parameter may take the values `yes',\n",
+"	`no', `true', `false', `on' or `off'.\n",
+"\n",
+"\n",
+"stop_at_max_accum = `on'\n",
+"	This specifies what should happen when the maximum number of\n",
+"	accumulators set by `max_accumulators' is reached. When this\n",
+"	is true the the processing of terms is stopped at the completion\n",
+"	of the current term. When this is false processing continues but\n",
+"	no new accumulators are created. This parameter may take the \n",
+"	values `yes', `no', `true', `false', `on' or `off'.\n",
+"\n",
+"terminator = `'\n",
+"	This specifies the string that will be output after the	last\n",
+"	document from the previous query has been output. The standard\n",
+"	C escape character sequences (see the man page) may be used to\n",
+"	place special characters in the string. For example, a newline\n",
+"	would the `\\n'. To include a `%' use the sequence `%%'.\n",
+"	\n",
+"\n",
+"timestats = `false'\n",
+"	If this is true then the time to process a query is displayed\n",
+"	in both real time and CPU time. This parameter may take the\n",
+"	values `yes', `no', `true', `false', `on' or `off'.\n",
+"\n",
+"verbatim = `off'\n",
+"	This is a boolean parameter that determines whether the program\n",
+"	should attempt to do a regular expression match on the retrieved\n",
+"	text. If verbatim is `on' and a post-processing strng is specified\n",
+"	with the query then the post-processing string will be searched for\n",
+"	in the documents just before they are displayed. If the string is\n",
+"	found the document will be displayed, if not the document will not\n",
+"	be displayed. If verbatim is `off' the post-processing string will\n",
+"	be considered a regular expression like in `vi' or `egrep'.\n",
+"	E.G. If verbatim is `on', \"and.*the\" will look for the 8 character\n",
+"	     sequence \"and.*the\". If verbatim is `off', \"and.*the\" will\n",
+"	     look for the sequence \"and\" followed somewhere later in the\n",
+"	     document by the sequence \"the\".\n",
+"	This parameter may take the values `yes', `no', `true', `false',\n",
+"	`on' or `off'.\n",
+"\n",
+"\n"};
Index: /indexers/branches/3.03a/mg/src/text/help.mg.src
===================================================================
--- /indexers/branches/3.03a/mg/src/text/help.mg.src	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/help.mg.src	(revision 14757)
@@ -0,0 +1,347 @@
+###########################################################################
+#
+# help.mg.src -- Source for the help command
+# Copyright (C) 1994  Neil Sharman
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#       @(#)help.mg.src	1.8 21 Mar 1994
+#
+###########################################################################
+#
+# The help file for mgquery.  
+# Lines starting with '#' are treated as comments and are discarded when
+# the 'help.mg.h' file is produced
+#
+###########################################################################
+
+			  HELP for mgquery
+		   ================================
+
+The text is a summary of the information in the "mgquery" manual pages.
+
+The input to 'mgquery' consists of a series of input lines. The backslash
+character ("\") is used at the end of lines to indicate that input 
+continues on the next line.
+
+Input lines on which the first character is a dot (".") are commands to
+the mgquery program. Input lines that do not start with a dot are queries.
+
+A query consists of two parts. One part is a boolean or ranked query that
+identifies documents. The second part is a post-processing pattern matching
+operation. Any text between the first speech mark (") and the last speech
+mark is considered to the a post-processing pattern. 
+
+
+The following command are available :-
+
+    .help	     - displays this text.
+    .quit            - quits the program.
+    .set name value  - sets parameter "name" to "value" . If the parameter
+                       is a boolean parameter and value is omitted the
+	    	       parameter will be inverted (i.e. if it is true it
+		       will change to false, if it is false it will change
+		       to true).
+    .unset name      - deletes parameter "name"
+    .reset           - sets all the parameters to their initial state.
+    .display         - displays the values of all the current parameters.
+    .push            - pushes the current parameters on to a stack.
+    .pop             - destroys the current parameters and pops a new set
+                       of parameters off the stack.
+    .output arg      - This is used to specify where to send the documents.
+                       Arg may one be of the following:
+		       > filename  : Send output to the specified file.
+		       >> filename : Append output to the specified file.
+                       | command   : The output is piped into command, 
+                                     which is executed by sh.
+    .input arg       - This is used to specify where input comes from.
+                       Arg may one be of the following:
+		       < filename  : Get the input from the specified
+                                     file.
+                       | command   : The input comes from the standard
+                                     output of command, which is executed
+                                     by sh.
+
+On startup the mgquery program reads from the file .mgrc a sequence 
+of commands (NOTE: The .mgrc file may not contain any queries). mgquery 
+first looks for .mgrc in the current directory and then in the users home 
+directory. Lines starting with a '#' in the .mgrc file are considered to
+be comments and are ignored.
+
+The following parameters (used in the .set and .unset commands) are 
+predefined and have special significance :-
+
+accumulator_method = `array'
+	This parameter is used during ranking, and specifies how the
+	weight for each document should be accumulated. The following
+	methods are available `array', `splay_tree', `hash_table', and
+	`list'.
+
+briefstats = `off'
+	This is a boolean parameter that determines whether the the
+	totals for disk, memory and time usage statistics will be 
+	displayed. at the end of each query. 
+	NOTE: this takes precedence over the parameters "diskstats",
+	"memstats" and "timestats". This parameter may take the values 
+	`yes', `no', `true', `false', `on' or `off'.
+
+buffer = `1048576'
+	When the documents are being read in they are read into a 
+	buffer of this size and then displayed from this buffer. If 
+        the documents are larger than this buffer the buffer is
+	expanded automatically. Having a large buffer gives a very
+	slight performance improvement because it allows the order of 
+	disk operations to be optimised. The buffer size is measured
+	in bytes.
+
+diskstats = `off'
+	This is a boolean parameter that determines whether the disk
+	usage statistics for the preceding query will be displayed
+	after each query. This parameter may take the values `yes',
+	`no', `true', `false', `on' or `off'.
+
+doc_sepstr = `---------------------------------- %n\n'
+	This specifies the string that will be used to separate 
+	documents when they are displayed for `boolean' or `docnums'
+	queries. The standard C escape character sequences (see the 
+	man page) may be used to place special characters in the 
+	string. For example, a newline would the `\n'. To include a `%'
+	use the sequence `%%'. To include the MG document number use
+	the sequence `%n'.
+
+expert = `false'
+	If this is true then a lot of the waffle that the program 
+	spits out is suppressed. This parameter may take the values
+	`yes', `no', `true', `false', `on' or `off'.
+
+hash_tbl_size = `1000'
+	One of the options during ranking queries is to use a hash 
+	table to accumulate the weights for each document. The hash 
+	table is a simple chained type. This parameter specifies the 
+	size of the hash table and may take any value between 8 and
+	268435456. 
+
+heads_length = `50'
+	When the mode is `heads' this specifies the number of 
+	characters that	will be output for each document.
+
+maxdocs = `all'
+	The maximum number of documents to display in response to a
+	query. This parameter may take on a numeric value between 1 
+	and 429467295 or the word `all'.
+
+maxparas = `1000'
+	The maximum number of paragraphs to identify during a ranked
+	query with paragraph indexing. After the paragraphs have been
+	identified the paragraphs are converted into documents, and 
+	because some of the paragraphs may refer to the same documents 
+	the final number of answers may be less that maxparas. The 
+	maxdocs parameter will then be applied. This parameter may 
+	take on a numeric value between 1 and 429467295.
+
+max_accumulators = `50000'
+	This parameter limits the number of different paragraph/
+	document numbers to be accumulated during ranked queries when 
+	the parameter `accumulator_method` is set to `splay_tree',
+	`hash_table', or `list'.  This parameter may take any value 
+	between 8 and 268435456.
+
+max_terms = `all'
+	This parameter limits the number of terms that will actually
+	be used during a ranked query. If more terms than the number
+	specified by max_terms are entered, then the extra terms will
+	be discarded. If `sorted_terms' is on then the limiting will 
+	be done after the terms have been sorted. This parameter may
+	take any value between 1 and 429467295 or the word `all'.
+
+memstats = `off'
+	This is a boolean parameter that determines whether the memory 
+	usage statistics for the preceding query will be displayed
+	after each query. This parameter may take the values `yes', 
+	`no', `true', `false', `on' or `off'.
+
+mgdir = `.'
+	This specifies the directory where the MG files may be found.
+	If the environment variable `MGDATA' is set then `mgdir' is
+	initialised to the value in `MGDATA'.
+
+mgname = `'
+	This specifies the name of the MG database to process.
+
+mode = `text'
+	This specifies how documents should be displayed when they
+	are retrieved it may take four different values `text', 
+	`docnums', `silent', `heads' or `count'. `text' displays 
+	the contents of the document. `docnums' displays only the
+	document numbers. `Silent' retrieves all the documents but
+	displays nothing except how many documents were retrieved.
+	This mode is intended to be used in timing experiments. 
+	`Heads` is used to print out the head of each document.
+	`Count' does the minimum amount of work required to determine
+	how many documents would be retrieved, but does not retrieve
+	them.
+
+pager = `more'
+	This is the name of the program that will be used to display
+	the help and the retrieved documents. If the environment 
+	variable "PAGER" is defined then `pager' takes on that value.
+
+para_sepstr = `\n######## PARAGRAPH %n ########\n'
+	This specifies the string that will be used to separate 
+	paragraphs. The standard C escape character sequences (see the 
+	man page) may be used to place special characters in the 
+	string. For example, a newline would the `\n'. To include a `%'
+	use the sequence `%%'. To include the paragraph number within
+	the document use the sequence `%n'.
+
+para_start = `***** Weight = %w *****\n'
+	This specifies the string that will be used at the head of 
+	paragraphs for a paraghaph level index following a ranked query.
+	The standard C escape character sequences (see the man page)
+	may be used to place special characters in the string. For 
+	example, a newline would the `\n'. To include a `%' use the
+	sequence `%%'. To include the paragraph weight use the 
+	sequence `%w'.
+
+qfreq = `true'
+	This determine whether the ranked queries will take into 
+	account the number of times each query term is specified.
+	When this is `true' the number of times a term appears in
+	the query is used in the ranking. When this is `false' all 
+	query term are assumed to occur only once. This parameter
+	may take the values `yes', `no', `true', `false', `on' or
+	`off'.
+
+query = `boolean'
+	This specifies the type of queries that are to be specified.
+	It can take four different values `boolean', `ranked', 
+	`docnums' or `approx-ranked'. 
+
+	`boolean' is for boolean queries. 
+		The yacc grammar for boolean queries is as follows :-
+
+		query   : or;
+ 
+		or      : or '|' and
+		        | and ;	
+ 
+		and     : and '&' not
+        		| and not
+        		| not ;
+
+		not     : term
+		        | '!' not ;
+ 
+		term    : TERM
+		        | '(' or ')' ;
+ 
+
+
+
+	`ranked' and `approx-ranked' are for queries ranked by the
+		cosine measure. `approx-ranked' uses only the low
+		precision document lengths, and therefore only
+		produces an approximation to full cosine ranking.
+
+		query   : TERM
+      			| query TERM ;
+	
+	`docnums' allows the entry of document numbers. Multiple 
+		numbers separated by spaces may be specified
+		or ranges separated by hyphens.
+
+
+		query   : range
+			| query range ;
+
+
+		range   : num
+			| num '-' num ;
+
+
+ranked_doc_sepstr = `---------------------------------- %n %w\n'
+	This specifies the string that will be used to separate 
+	documents when they are displayed for `ranked' or 
+	`approx-ranked'	queries. The standard C escape character 
+	sequences (see the man page) may be used to place special
+	characters in the string. For example, a newline would the
+	`\n'. To include a `%' use the sequence `%%'. To include the
+	MG document number use the sequence `%n'. To include the
+	document weight use the sequence `%w'.
+
+sizestats = `false'
+	If this is true then various numbers are output at the end
+	of each query indicating what went on during the query. 
+	This parameter may take the values `yes', `no', `true', 
+	`false', `on' or `off'.
+
+skip_dump = `skips.%d'
+	If this parameter is set then during ranked queries on skipped
+	inverted files when `accumulator_method' is set to `splay_tree',
+	`hash_table', or `list` a file will be produced in the current
+	directory. The name of the file is the value of this parameter,
+	a `%d' in the file name will be replaced with the process id of
+	mgquery. This file will contain information about the usage of
+	skips during the query processing. This option is expensive; 
+	use `.unset skip_dump' to obtain optimal performance.
+
+sorted_terms = `on'
+	This specifies whether of not the terms should be sorted into
+	decreasing occurrence in documents so that the least often
+	occurring terms are processed first when ranked queries are
+	being done. When this is true the terms are sorted. When this
+	is false the terms are not sorted and are instead processed in
+	order of occurrence. This parameter may take the values `yes',
+	`no', `true', `false', `on' or `off'.
+
+
+stop_at_max_accum = `on'
+	This specifies what should happen when the maximum number of
+	accumulators set by `max_accumulators' is reached. When this
+	is true the the processing of terms is stopped at the completion
+	of the current term. When this is false processing continues but
+	no new accumulators are created. This parameter may take the 
+	values `yes', `no', `true', `false', `on' or `off'.
+
+terminator = `'
+	This specifies the string that will be output after the	last
+	document from the previous query has been output. The standard
+	C escape character sequences (see the man page) may be used to
+	place special characters in the string. For example, a newline
+	would the `\n'. To include a `%' use the sequence `%%'.
+	
+
+timestats = `false'
+	If this is true then the time to process a query is displayed
+	in both real time and CPU time. This parameter may take the
+	values `yes', `no', `true', `false', `on' or `off'.
+
+verbatim = `off'
+	This is a boolean parameter that determines whether the program
+	should attempt to do a regular expression match on the retrieved
+	text. If verbatim is `on' and a post-processing strng is specified
+	with the query then the post-processing string will be searched for
+	in the documents just before they are displayed. If the string is
+	found the document will be displayed, if not the document will not
+	be displayed. If verbatim is `off' the post-processing string will
+	be considered a regular expression like in `vi' or `egrep'.
+	E.G. If verbatim is `on', "and.*the" will look for the 8 character
+	     sequence "and.*the". If verbatim is `off', "and.*the" will
+	     look for the sequence "and" followed somewhere later in the
+	     document by the sequence "the".
+	This parameter may take the values `yes', `no', `true', `false',
+	`on' or `off'.
+
+
Index: /indexers/branches/3.03a/mg/src/text/invf.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/invf.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/invf.h	(revision 14757)
@@ -0,0 +1,79 @@
+/**************************************************************************
+ *
+ * invf.h -- Data structures for inverted files
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+
+#ifndef H_INVF
+#define H_INVF
+
+/* NOTE: This does not include the magic number */
+struct invf_dict_header
+  {
+    unsigned long lookback;
+    unsigned long dict_size;
+    unsigned long total_bytes;
+    unsigned long index_string_bytes;
+    double input_bytes; /* [RJM 07/97: 4G limit] */
+    unsigned long num_of_docs;
+    unsigned long static_num_of_docs;
+    unsigned long num_of_words;
+    unsigned long stemmer_num;
+    unsigned long stem_method;
+  };
+
+struct stem_dict_header
+  {
+    unsigned long lookback;
+    unsigned long block_size;
+    unsigned long num_blocks;
+    unsigned long blocks_start;
+    unsigned long index_chars;
+    unsigned long num_of_docs;
+    unsigned long static_num_of_docs;
+    unsigned long num_of_words;
+    unsigned long stemmer_num;
+    unsigned long stem_method;
+    unsigned long indexed;       /* [RPAP - Jan 97: Stem Index Change] */
+  };
+
+struct invf_file_header
+  {
+    unsigned long no_of_words;
+    unsigned long no_of_ptrs;
+    unsigned long skip_mode;
+    unsigned long params[16];
+    unsigned long InvfLevel;
+  };
+
+/* [RPAP - Jan 97: Stem Index Change] */
+struct stem_idx_header
+  {
+    unsigned long lookback;
+    unsigned long block_size;
+    unsigned long num_blocks;
+    unsigned long blocks_start;
+    unsigned long index_chars;
+    unsigned long num_of_words;
+  };
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/invf_get.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/invf_get.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/invf_get.c	(revision 14757)
@@ -0,0 +1,1666 @@
+/**************************************************************************
+ *
+ * invf_get.c -- Inverted file reading routines
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "filestats.h"
+#include "timing.h"
+#include "bitio_gen.h"
+#include "bitio_m_mem.h"
+#include "bitio_m.h"
+#include "sptree.h"
+#include "messages.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg.h"
+#include "invf.h"
+#include "text.h"
+#include "lists.h"
+#include "backend.h"
+#include "invf_get.h"
+#include "mg_errors.h"
+
+#define SKIPPING
+#define SHORT_CUT
+
+struct pool
+  {
+    int length, pos;
+    struct pool *next;
+    Invf_Doc_Entry ide[1];
+  };
+
+static int skip_header = 0;
+
+static char skip_header_text0[] =
+"#######################################################################\n"
+"#\n"
+"# 1\tWord number.\n"
+"# 2\tNumber of time the word occurs in the collection.\n"
+"# 3\tNumber of documents the word occurs in.\n"
+"# 4\tThe word.\n"
+"# 5\tNumber of docnum/word_count entries decoded.\n"
+"# 6\tNumber of hits.\n"
+"# 7\tNumber of entries in the splay tree or hash table.\n"
+"# 8\tAmount added to the accumulators while while processing this word.\n"
+"#\n"
+"#######################################################################\n";
+
+static char skip_header_text1[] =
+"#######################################################################\n"
+"#\n"
+"# 1\tWord number.\n"
+"# 2\tNumber of time the word occurs in the collection.\n"
+"# 3\tNumber of documents the word occurs in.\n"
+"# 4\tThe word.\n"
+"# 5\tNumber of skips taken in evaluating the inverted file entry.\n"
+"# 6\tNumber of docnum/word_count entries decoded.\n"
+"# 7\tNumber of hits.\n"
+"# 8\tNumber of entries in the splay tree or hash table.\n"
+"# 9\tAmount added to the accumulators while while processing this word.\n"
+"#\n"
+"#######################################################################\n";
+
+
+static char skip_header_text2[] =
+"#######################################################################\n"
+"#\n"
+"#  1\tWord number.\n"
+"#  2\tNumber of time the word occurs in the collection.\n"
+"#  3\tNumber of documents the word occurs in.\n"
+"#  4\tThe word.\n"
+"#  5\tSkip size.\n"
+"#  6\tNumber of skips taken in evaluating the inverted file entry.\n"
+"#  7\tNumber of docnum/word_count entries decoded.\n"
+"#  8\tNumber of hits.\n"
+"#  9\tNumber of entries in the splay tree or hash table.\n"
+"# 10\tAmount added to the accumulators while while processing this word.\n"
+"#\n"
+"#######################################################################\n";
+
+static char *skip_header_text[] =
+{skip_header_text0,
+ skip_header_text1,
+ skip_header_text2};
+
+
+
+
+
+
+
+
+/**************************************************************************
+ *
+ * Code for the hash table.
+ *
+ */
+
+static Hash_Table *
+HT_create (query_data * qd, unsigned max_entries,
+	   unsigned max_size)
+{
+  unsigned es, hts;
+  Hash_Table *HT;
+  if (max_entries == 0)
+    max_entries = 8192;
+  es = sizeof (Hash_Table) + sizeof (Invf_Doc_EntryH) * (max_entries - 1);
+  hts = sizeof (Invf_Doc_EntryH *) * max_size;
+
+  HT = Xmalloc (es);
+  if (!HT)
+    return NULL;
+
+  HT->HashTable = Xmalloc (hts);
+  if (!(HT->HashTable))
+    {
+      Xfree (HT);
+      return NULL;
+    }
+
+  ChangeMemInUse (qd, es + hts);
+  bzero ((char *) (HT->HashTable), hts);
+  HT->max = max_entries;
+  HT->num = 0;
+  HT->Suplimentary_Entries = NULL;
+  HT->Suplimentary_Size = 0;
+  HT->Suplimentary_Num = 0;
+  HT->Head = NULL;
+  HT->size = max_size;
+  return HT;
+}
+
+
+static void 
+HT_Sup_create (query_data * qd, Hash_Table * HT, unsigned max_size)
+{
+  int es = sizeof (Invf_Doc_EntryH) * max_size;
+  HT->Suplimentary_Entries = Xmalloc (es);
+  if (!HT->Suplimentary_Entries)
+    return;
+  HT->Suplimentary_Size = max_size;
+  HT->Suplimentary_Num = 0;
+  ChangeMemInUse (qd, es);
+}
+
+static void 
+HT_Sup_Add (Hash_Table * HT, unsigned long DN, float Sum)
+{
+  Invf_Doc_EntryH *IDEH;
+  IDEH = &HT->Suplimentary_Entries[HT->Suplimentary_Num++];
+  IDEH->next = NULL;
+  IDEH->IDE.DocNum = DN;
+  IDEH->IDE.Sum = Sum;
+}
+
+Invf_Doc_Entry *
+HT_find (Hash_Table * HT, unsigned long DN)
+{
+  Invf_Doc_EntryH *IDEH;
+  if (!HT->HashTable)
+    FatalError (1, "Accessing the hash_table through HT_find after HT_sort");
+  IDEH = HT->HashTable[DN % HT->size];
+  while (IDEH)
+    {
+      if (IDEH->IDE.DocNum == DN)
+	return &(IDEH->IDE);
+      IDEH = IDEH->next;
+    }
+  return NULL;
+}
+
+
+static int 
+HT_insert (Hash_Table * HT,
+	   unsigned long DN, float Sum)
+{
+  Invf_Doc_EntryH **IDEH;
+  if (HT->num == HT->max)
+    return 0;
+  IDEH = &(HT->HashTable[DN % HT->size]);
+  while (*IDEH)
+    IDEH = &((*IDEH)->next);
+  *IDEH = &(HT->IDEH[HT->num++]);
+  (*IDEH)->next = NULL;
+  (*IDEH)->IDE.DocNum = DN;
+  (*IDEH)->IDE.Sum = Sum;
+  return 1;
+}
+
+
+void 
+HT_free (query_data * qd, Hash_Table * HT)
+{
+  unsigned es;
+  es = sizeof (Hash_Table) + sizeof (Invf_Doc_EntryH) * HT->max +
+    sizeof (Invf_Doc_EntryH *) * HT->size;
+  if (HT->HashTable)
+    Xfree (HT->HashTable);
+  if (HT->Suplimentary_Entries)
+    {
+      Xfree (HT->Suplimentary_Entries);
+      es += sizeof (Invf_Doc_EntryH) * HT->Suplimentary_Size;
+    }
+  Xfree (HT);
+  ChangeMemInUse (qd, -es);
+}
+
+
+static int 
+IDEH_comp (const void *a, const void *b)
+{
+  const Invf_Doc_EntryH *A = a;
+  const Invf_Doc_EntryH *B = b;
+  return A->IDE.DocNum - B->IDE.DocNum;
+}
+
+static void 
+HT_sort (query_data * qd, Hash_Table * HT)
+{
+  int i;
+  Invf_Doc_EntryH *l, *r, **b;
+  unsigned es = sizeof (Invf_Doc_EntryH *) * HT->size;
+  if (HT->HashTable)
+    Xfree (HT->HashTable);
+  HT->size = 0;
+  HT->HashTable = NULL;
+  ChangeMemInUse (qd, -es);
+
+  qsort (HT->IDEH, HT->num, sizeof (Invf_Doc_EntryH), IDEH_comp);
+
+  for (i = 0; i < HT->num - 1; i++)
+    HT->IDEH[i].next = &HT->IDEH[i + 1];
+  HT->IDEH[i].next = NULL;
+  l = HT->IDEH;
+
+  if (HT->Suplimentary_Entries)
+    {
+      for (i = 0; i < HT->Suplimentary_Num - 1; i++)
+	HT->Suplimentary_Entries[i].next = &HT->Suplimentary_Entries[i + 1];
+      HT->Suplimentary_Entries[i].next = NULL;
+    }
+  r = HT->Suplimentary_Entries;
+
+  b = &HT->Head;
+
+  while (l || r)
+    {
+      if (r && (!l || (l->IDE.DocNum > r->IDE.DocNum)))
+	{
+	  *b = r;
+	  b = &r->next;
+	  r = *b;
+	}
+      else
+	{
+	  *b = l;
+	  b = &l->next;
+	  l = *b;
+	}
+    }
+  *b = NULL;
+}
+
+
+
+
+
+
+/**************************************************************************
+ *
+ * Code for the hash table.
+ *
+ */
+
+static List_Table *
+LT_create (query_data * qd, unsigned max_entries)
+{
+  unsigned es;
+  List_Table *LT;
+  if (max_entries == 0)
+    max_entries = 8192;
+  es = sizeof (List_Table) + sizeof (Invf_Doc_Entry) * (max_entries - 1);
+
+  LT = Xmalloc (es);
+  if (!LT)
+    return NULL;
+
+  ChangeMemInUse (qd, es);
+  LT->max = max_entries;
+  LT->num = 0;
+  return LT;
+}
+
+
+
+Invf_Doc_Entry *
+LT_find (List_Table * LT, unsigned long DN)
+{
+  int l = 0;
+  int r = LT->num - 1;
+  int m, c;
+  while (l <= r)
+    {
+      m = (l + r) / 2;
+      c = DN - LT->IDE[m].DocNum;
+      if (c < 0)
+	r = m - 1;
+      else if (c > 0)
+	l = m + 1;
+      else
+	return &LT->IDE[m];
+    }
+  return NULL;
+}
+
+static List_Table *
+LT_add (query_data * qd, List_Table * LT,
+	unsigned long DN, float Sum)
+{
+  Invf_Doc_Entry *ide;
+
+  /* increase the size of the list if there is not enough */
+  /* room for this entry */
+  if (LT->num == LT->max)
+    {
+      int old, new, max_entries;
+      old = sizeof (List_Table) + sizeof (Invf_Doc_Entry) * LT->max;
+      max_entries = LT->max + (LT->max >> 1);
+      new = sizeof (List_Table) + sizeof (Invf_Doc_Entry) * max_entries;
+
+      LT = Xrealloc (LT, new);
+      if (!LT)
+	return NULL;
+
+      ChangeMemInUse (qd, new - old);
+      LT->max = max_entries;
+    }
+
+  /* add the entry to the end of the list */
+  ide = &LT->IDE[LT->num];
+  ide->DocNum = DN;
+  ide->Sum = Sum;
+  LT->num++;
+
+  return LT;
+}
+
+
+void 
+LT_free (query_data * qd, List_Table * LT)
+{
+  unsigned es;
+  es = sizeof (List_Table) + sizeof (Invf_Doc_Entry) * LT->max;
+  Xfree (LT);
+  ChangeMemInUse (qd, -es);
+}
+
+
+static int 
+IDE_comp (const void *a, const void *b)
+{
+  const Invf_Doc_Entry *A = a;
+  const Invf_Doc_Entry *B = b;
+  return A->DocNum - B->DocNum;
+}
+
+static void 
+LT_sort (List_Table * LT)
+{
+  qsort (LT->IDE, LT->num, sizeof (Invf_Doc_Entry), IDE_comp);
+}
+
+
+/* [RJM 07/97: Ranked Required Terms] */
+/* accumulators with a sum less than or equal to 0.0 are to be deleted */
+static void 
+LT_pack (List_Table * LT)
+{
+  int s, d = 0;
+  for (s = 0; s < LT->num; s++) {
+      if (LT->IDE[s].Sum <= 0.0) {
+	/* ignore this accumulator */
+
+      } else if (d > 0 && LT->IDE[s].DocNum == LT->IDE[d-1].DocNum) {
+	LT->IDE[d-1].Sum += LT->IDE[s].Sum;
+
+      } else {
+	if (d != s) LT->IDE[d] = LT->IDE[s];
+	d++;
+      }
+  }
+
+  if (LT->num) LT->num = d;
+}
+
+
+/**************************************************************************/
+
+
+
+invf_data *
+InitInvfFile (File * InvfFile, stemmed_dict * sd)
+{
+  invf_data *id;
+  if (!(id = Xmalloc (sizeof (invf_data))))
+    {
+      mg_errno = MG_NOMEM;
+      return NULL;
+    }
+
+  id->InvfFile = InvfFile;
+
+  Fread (&id->ifh, sizeof (id->ifh), 1, InvfFile);
+  /* [RPAP - Jan 97: Endian Ordering] */
+  {
+    int i;
+    
+    NTOHUL(id->ifh.no_of_words);
+    NTOHUL(id->ifh.no_of_ptrs);
+    NTOHUL(id->ifh.skip_mode);
+    for (i = 0; i < 16; i++)
+      NTOHUL(id->ifh.params[i]);
+    NTOHUL(id->ifh.InvfLevel);
+  }
+
+  id->N = sd->sdh.num_of_docs;
+  id->Nstatic = sd->sdh.static_num_of_docs;
+
+  return (id);
+}
+
+
+void 
+FreeInvfData (invf_data * id)
+{
+  Xfree (id);
+}
+
+/****************************************************************************/
+
+
+static void 
+CalcBlks (query_data * qd, WordEntry * we, int *blk,
+	  int *dn_blk, int *len_blk, int *k, int *p)
+{
+  *p = we->doc_count;
+
+  *blk = BIO_Bblock_Init (qd->id->Nstatic, *p);
+  switch (qd->id->ifh.skip_mode)
+    {
+    case 1:
+      {
+	unsigned long len;
+	if (*p <= qd->id->ifh.params[0])
+	  *k = 0;
+	else
+	  {
+	    *k = qd->id->ifh.params[0];
+	    len = BIO_Bblock_Bound (qd->id->N, *p);
+	    if (qd->id->ifh.InvfLevel >= 2)
+	      len += we->count;
+	    *dn_blk = BIO_Bblock_Init (qd->sd->sdh.num_of_docs, (*p + *k - 1) / *k);
+	    *len_blk = BIO_Bblock_Init (len, (*p + *k - 1) / *k);
+	  }
+	break;
+      }
+    case 2:
+      {
+	unsigned long len;
+	if (*p <= qd->id->ifh.params[1])
+	  *k = 0;
+	else
+	  {
+	    *k = (int) (2 * sqrt (((double) (*p)) / qd->id->ifh.params[0]));
+	    if (*k <= qd->id->ifh.params[1])
+	      *k = qd->id->ifh.params[1];
+	    len = BIO_Bblock_Bound (qd->id->N, *p);
+	    if (qd->id->ifh.InvfLevel >= 2)
+	      len += we->count;
+	    *dn_blk = BIO_Bblock_Init (qd->sd->sdh.num_of_docs,
+				       (*p + *k - 1) / *k);
+	    *len_blk = BIO_Bblock_Init (len, (*p + *k - 1) / *k);
+	  }
+	break;
+      }
+    default:
+      *k = 0;
+    }
+}
+
+
+/* =========================================================================
+ * Function: GetDocsOp
+ * Description: 
+ *      if op == op_term then 
+ *        look up term in invf and decode all its entries/documents
+ *      if op == op_and_terms then 
+ *        go thru L, testing if it exists in invf using skips  
+ *        if it does exist then overwrite the entry nearer the start of the list
+ *      if op == op_and_or_terms then
+ *        go thru L, testing if it exists in invf using skips  
+ *        BUT only mark ones which are found - keep list intact
+ *      if op == op_diff_terms then     >>>> NOT tested <<<<
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+DocList *
+GetDocsOp (query_data * qd, WordEntry * we, Op_types op, DocList * L)
+{
+  u_char *buffer;
+  DocEntry *src = NULL, *dest = NULL;
+  int i;			/* index counter into inverted list */
+  unsigned long pos;
+  int next_start, next_doc_num, next_i;
+  int block_counter;		/* within counter in block */
+  int dn_blk = 0, len_blk = 0;
+  int skip_size, have_skipping;
+  int blk;			/* bblock control parameter */
+  int ft;			/* The number of documents the word occurs in */
+  unsigned long CurrDoc = 0;	/* NOTE: Document numbers start at 1 */
+  float Weight;
+
+  /* ... AND empty */
+  if (op == op_and_terms && (!L || !L->num))
+    {
+      if (L)
+	Xfree (L);
+      return MakeDocList (0);
+    }
+
+  if (op == op_term)
+    L = MakeDocList (we->doc_count);
+
+  CalcBlks (qd, we, &blk, &dn_blk, &len_blk, &skip_size, &ft);
+  have_skipping = (skip_size != 0);
+  if (!(buffer = Xmalloc (we->invf_len)))
+    return MakeDocList (0);
+
+  ChangeMemInUse (qd, we->invf_len);
+
+  qd->num_of_terms++;
+
+  /* --- Read an inverted file entry for the given word --- */
+  Fseek (qd->File_invf, we->invf_ptr, 0);
+  Fread (buffer, sizeof (char), we->invf_len, qd->File_invf);
+
+  /* Read from the buffer */
+  DECODE_START (buffer, we->invf_len);
+
+  Weight = qd->sd->sdh.num_of_words / (100 * log2 ((float) we->count + 1));
+
+  if (op != op_term)
+    dest = src = L->DE;
+  i = pos = 0;
+  next_i = next_start = next_doc_num = 0;
+  block_counter = skip_size - 1;
+
+  /* Go thru the elements of an inverted list for a term */
+  /* May not go sequentially if skipping is done */
+  while (i < ft && ((op == op_term) || src - L->DE < L->num))
+    {
+      unsigned long diff, Temp;
+
+      if (have_skipping)
+	{
+
+	  /* --- Skip to next block --- */
+	  if (op != op_term && i + skip_size < ft &&
+	      src->DocNum > next_doc_num && next_doc_num >= 0)
+	    {
+	    ShortCut:
+	      i = next_i;
+	      DECODE_SEEK (next_start);
+	      pos = next_start;
+	      CurrDoc = next_doc_num;
+	      qd->hops_taken++;
+	      block_counter = skip_size - 1;
+	    }
+
+	  /* --- Decode the skip block header --- */
+	  if (block_counter == skip_size - 1)
+	    {
+	      if (i + skip_size < ft)
+		{
+		  /* --- Decode the skip block header --- */
+		  int doc_diff, pos_diff;
+		  BBLOCK_DECODE_L (doc_diff, dn_blk, pos);
+		  next_doc_num += doc_diff;
+		  next_i += skip_size;
+		  BBLOCK_DECODE_L (pos_diff, len_blk, pos);
+		  next_start = pos + pos_diff;
+		}
+	      else
+		next_doc_num = -1;
+	    }
+
+	  /* --- Do a skip if c-set doc is higher than block header doc --- */
+	  if (op != op_term && i + skip_size < ft &&
+	      src->DocNum > next_doc_num && next_doc_num >= 0)
+	    goto ShortCut;
+
+
+	}			/*if skipping */
+
+      /* --- increment CurrDoc --- */
+      if (have_skipping && block_counter == 0 && i != ft - 1)
+	CurrDoc = next_doc_num;
+      else
+	{
+	  BBLOCK_DECODE_L (diff, blk, pos);
+	  CurrDoc += diff;
+	}
+
+      /* --- If have f_dt's then eat them up --- */
+      if (qd->id->ifh.InvfLevel >= 2)
+	GAMMA_DECODE_L (Temp, pos);	/* discard word count */
+
+      /* --- Increment counters --- */
+      qd->num_of_ptrs++;
+      i++;
+      block_counter--;
+      if (block_counter < 0)	/* ??? Why would this happen ? */
+	block_counter = skip_size - 1;
+
+      switch (op)
+	{
+	case op_term:
+	  /* --- Add the doc from invf onto the c-set list --- */
+	  L->DE[L->num].DocNum = CurrDoc;
+	  L->DE[L->num].Weight = Weight;
+	  L->DE[L->num].SeekPos = 0;
+	  L->DE[L->num].Len = 0;
+	  L->DE[L->num].CompTextBuffer = NULL;
+	  L->DE[L->num].Next = NULL;
+	  L->DE[L->num].or_included = 0;
+	  L->num++;
+	  break;
+
+	case op_and_terms:
+	case op_and_or_terms:
+	  /* --- see if have a match and save it --- */
+
+	  while (src < (L->DE + L->num) && CurrDoc > src->DocNum)
+	    {
+	      src++;
+	    }
+	  /* Unless at end of list, assert(CurrDoc <= src->DocNum) */
+
+	  /* --- Accept the doc as a candidate --- */
+	  if (src < (L->DE + L->num) && CurrDoc == src->DocNum)
+	    {
+	      if (op == op_and_terms)
+		{
+		  *dest++ = *src;
+		}
+	      else
+		{
+		  src->or_included = 1;
+		}
+	      src++;		/* Move onto next one */
+	    }
+
+	  /* If the next one to try has already been tried then move on again */
+	  if (op == op_and_or_terms)
+	    {
+	      while (src < (L->DE + L->num) && src->or_included)
+		src++;
+	    }
+
+	  break;
+
+	case op_diff_terms:
+	  while (src < (L->DE + L->num) && src->DocNum < CurrDoc)
+	    *dest++ = *src++;
+	  if (src < (L->DE + L->num) && src->DocNum == CurrDoc)
+	    src++;
+	  break;
+
+	default:
+	  break;
+	}			/*switch */
+
+    }				/*while traversing invf */
+
+  if (op == op_and_terms || op == op_diff_terms)
+    {
+      if (op == op_diff_terms)
+	while (src - L->DE < L->num)
+	  *dest++ = *src++;
+
+      /* update size of c-set */
+      L->num = dest - L->DE;
+    }
+  DECODE_DONE
+
+    Xfree (buffer);
+  ChangeMemInUse (qd, -we->invf_len);
+
+  return (L);
+}
+
+
+
+
+
+
+
+float *
+CosineDecode (query_data * qd, TermList * Terms, RankedQueryInfo * rqi)
+{
+  float *AccumulatedWeights;
+  int j, num_docs, num_terms;
+  int seen_must_match = 0; /* [RJM 07/97: Ranked Required Terms] says whether to 'and' queries or not */
+
+  num_docs = qd->sd->sdh.num_of_docs;
+  /* Create the array for the documents */
+  if (!(AccumulatedWeights = Xmalloc (num_docs * sizeof (float))))
+      return (NULL);
+
+  bzero ((char *) AccumulatedWeights, sizeof (float) * num_docs);
+  ChangeMemInUse (qd, sizeof (float) * num_docs);
+
+  if (rqi->MaxTerms == -1)
+    num_terms = Terms->num;
+  else
+    num_terms = rqi->MaxTerms < Terms->num ? rqi->MaxTerms : Terms->num;
+
+
+  /* For each word in the list . . . */
+  for (j = 0; j < num_terms; j++)
+    {
+      u_char *buffer;
+      int i, kd;
+      unsigned long next_mjr_dn = 0;
+      unsigned long CurrDocNum = 0;	/* NOTE: Document numbers start at 1 */
+      unsigned long LastDocNum = 0; /* [RJM 07/97: Ranked Required Terms] */
+      unsigned long TempDocNum = 0; /* [RJM 07/97: Ranked Required Terms] */
+      double Wqt, WordLog;
+      int dn_blk = 0, len_blk = 0, k;
+      int blk;			/* bblock control parameter */
+      int p;			/* The number of documents the word occurs in */
+      int require_match = Terms->TE[j].require_match; /* [RJM 07/97: Ranked Required Terms] */
+      WordEntry *we = &Terms->TE[j].WE;
+      CalcBlks (qd, we, &blk, &dn_blk, &len_blk, &k, &p);
+      if (!(buffer = Xmalloc (we->invf_len)))
+	break;
+
+      ChangeMemInUse (qd, we->invf_len);
+
+      Fseek (qd->File_invf, we->invf_ptr, 0);
+      Fread (buffer, sizeof (char), we->invf_len, qd->File_invf);
+
+      /* Read from the buffer */
+      DECODE_START (buffer, we->invf_len);
+
+      WordLog = log ((double) num_docs / (double) we->max_doc_count);  /* [RPAP - Jan 97: Stem Index Change] */
+
+      Wqt = (rqi->QueryFreqs ? Terms->TE[j].Count : 1) * WordLog;
+
+      qd->num_of_terms++;
+
+      kd = 0;
+      for (i = 0; i < p; i++, kd++)
+	{
+	  int Count;		/* The number of times the word occurs in a document */
+	  double Wdt;
+	  unsigned long diff;
+	  if (kd == k)
+	    {
+	      kd = 0;
+	    }
+	  if (k && kd == 0)
+	    if (i + k < p)
+	      {
+		int temp;
+		BBLOCK_DECODE (next_mjr_dn, dn_blk);
+		next_mjr_dn += CurrDocNum;
+		BBLOCK_DECODE (temp, len_blk);
+	      }
+	  if (k && kd == k - 1 && i != p - 1)
+	    CurrDocNum = next_mjr_dn;
+	  else
+	    {
+	      BBLOCK_DECODE (diff, blk);
+	      CurrDocNum += diff;
+	    }
+	  if (qd->id->ifh.InvfLevel >= 2)
+	    GAMMA_DECODE (Count);
+	  else
+	    Count = (double) we->count / p;
+	  Wdt = Count * WordLog;
+
+	  /* [RJM 07/97: Ranked Required Terms] */
+	  /* zero the weights of intermediate documents if this term is required to match */
+	  if (require_match == 1) {
+	    for (TempDocNum = LastDocNum+1; TempDocNum < CurrDocNum; TempDocNum++)
+	      AccumulatedWeights[TempDocNum - 1] = 0.0;
+	  }
+
+	  /* [RJM 07/97: Ranked Required Terms] */
+	  /* if a term has been required to match before, the weight we are */
+	  /* adding to must be non-zero */
+	  if (!seen_must_match || (AccumulatedWeights[CurrDocNum - 1] > 0.0)) {
+	      AccumulatedWeights[CurrDocNum - 1] += Wqt * Wdt;
+	  }
+
+	  qd->num_of_ptrs++;
+	  LastDocNum = CurrDocNum; /* [RJM 07/97: Ranked Required Terms] */
+	}
+
+      DECODE_DONE
+
+	Xfree (buffer);
+      ChangeMemInUse (qd, -we->invf_len);
+
+      /* [RJM 07/97: Ranked Required Terms] */
+      /* zero the remaining weights if this term is required to match */
+      if (require_match == 1) {
+	for (TempDocNum = LastDocNum+1; TempDocNum <= num_docs; TempDocNum++)
+	  AccumulatedWeights[TempDocNum - 1] = 0.0;
+	seen_must_match = 1;
+      }
+    }
+  return AccumulatedWeights;
+}
+
+
+
+static int 
+doc_comp (void *a, void *b)
+{
+  return ((Invf_Doc_Entry *) a)->DocNum - ((Invf_Doc_Entry *) b)->DocNum;
+}
+
+
+static Invf_Doc_Entry *
+get_ide (query_data * qd, Invf_Doc_Entry_Pool * pool)
+{
+  struct pool *p = pool->pool;
+  if (!p || p->pos == p->length)
+    {
+      register unsigned size = sizeof (struct pool) +
+      (pool->pool_chunks - 1) * sizeof (Invf_Doc_Entry);
+      p = malloc (size);
+      if (!p)
+	return NULL;
+      ChangeMemInUse (qd, size);
+      p->length = pool->pool_chunks;
+      p->pos = 0;
+      p->next = pool->pool;
+      pool->pool = p;
+    }
+  return &(p->ide[p->pos++]);
+}
+
+
+void 
+free_ide_pool (query_data * qd, Invf_Doc_Entry_Pool * pool)
+{
+  while (pool->pool)
+    {
+      struct pool *p = pool->pool;
+      pool->pool = p->next;
+      ChangeMemInUse (qd, -(sizeof (struct pool) + (p->length - 1) *
+			    sizeof (Invf_Doc_Entry)));
+      free (p);
+    }
+  pool->pool = NULL;
+}
+
+
+FILE *
+open_skip (char *sd)
+{
+  char buf[256];
+  if (sd == NULL || *sd == '\0')
+    return NULL;
+  sprintf (buf, sd, getpid ());
+  return fopen (buf, "a");
+}
+
+
+
+Splay_Tree *
+CosineDecodeSplay (query_data * qd, TermList * Terms,
+		   RankedQueryInfo * rqi, Invf_Doc_Entry_Pool * pool)
+{
+  Splay_Tree *Doc_Set;
+  int j, num_docs, num_terms, MoreAccum;
+  int Anding = 0;
+  FILE *sk = open_skip (rqi->skip_dump);
+  u_char indent = 0;
+  if (sk)
+    {
+      if (!skip_header)
+	{
+	  skip_header = 1;
+	  fprintf (sk, "%s", skip_header_text[qd->id->ifh.skip_mode]);
+	  fprintf (sk, "\nSkipping method %ld\n", qd->id->ifh.skip_mode);
+	  switch (qd->id->ifh.skip_mode)
+	    {
+	    case 1:
+	      fprintf (sk, "Skipping is every %ld docnums\n",
+		       qd->id->ifh.params[0]);
+	      break;
+	    case 2:
+	      fprintf (sk, "Max nodes = %ld\nNo skips smaller or equal to %ld\n",
+		       qd->id->ifh.params[0], qd->id->ifh.params[1]);
+	      break;
+	    }
+	}
+      fprintf (sk, "\n\t\t\t-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n");
+      for (j = 0; j < Terms->num; j++)
+	if (Terms->TE[j].Word[0] > indent)
+	  indent = Terms->TE[j].Word[0];
+    }
+
+  num_docs = qd->sd->sdh.num_of_docs;
+  /* Create the array for the documents */
+  Doc_Set = SP_createset (doc_comp);
+
+  pool->pool = NULL;
+  pool->pool_chunks = 1024;
+
+  if (rqi->MaxTerms == -1)
+    num_terms = Terms->num;
+  else
+    num_terms = rqi->MaxTerms < Terms->num ? rqi->MaxTerms : Terms->num;
+
+  MoreAccum = 1;
+
+  /* For each word in the list . . . */
+  for (j = 0; j < num_terms; j++)
+    {
+      int Abort = 0;
+      u_char *buffer;
+      int pos, i;
+      unsigned long CurrDocNum = 0;	/* NOTE: Document numbers start at 1 */
+      double Wqt, WordLog;
+      int dn_blk = 0, len_blk = 0, k, kd;
+      int blk;			/* bblock control parameter */
+      int p;			/* The number of documents the word occurs in */
+      WordEntry *we = &Terms->TE[j].WE;
+      Invf_Doc_Entry *next = NULL;
+      int next_i, next_doc_num, next_start;
+      int skips_taken = 0, ptrs_dec = 0;
+      double total_added = 0.0;
+      int hits = 0;
+      if (sk)
+	{
+	  fprintf (sk, "%3d : %8ld %6ld \"%.*s\"%*s", j, we->count,
+		 we->doc_count, Terms->TE[j].Word[0], Terms->TE[j].Word + 1,
+		   indent - Terms->TE[j].Word[0], "");
+	}
+
+      CalcBlks (qd, we, &blk, &dn_blk, &len_blk, &k, &p);
+      if (!(buffer = Xmalloc (we->invf_len)))
+	break;
+
+      ChangeMemInUse (qd, we->invf_len);
+
+      if (sk && qd->id->ifh.skip_mode == 2)
+	fprintf (sk, "%4d", k);
+
+      Fseek (qd->File_invf, we->invf_ptr, 0);
+      Fread (buffer, sizeof (char), we->invf_len, qd->File_invf);
+
+      /* Read from the buffer */
+      DECODE_START (buffer, we->invf_len);
+
+      WordLog = log ((double) num_docs / (double) we->max_doc_count);  /* [RPAP - Jan 97: Stem Index Change] */
+
+      Wqt = (rqi->QueryFreqs ? Terms->TE[j].Count : 1) * WordLog;
+
+      qd->num_of_terms++;
+
+      if (rqi->MaxAccums != -1 && Doc_Set->no_of_items >= rqi->MaxAccums)
+	{
+	  MoreAccum = 0;
+	  Anding = 1;
+	  next = SP_get_first (Doc_Set);
+	}
+      i = pos = 0;
+      next_i = next_start = next_doc_num = 0;
+      kd = k - 1;
+      while (i < p && (!Anding || next))
+	{
+	  int Count;		/* The number of times the occurs in a document */
+	  double Wdt;
+	  unsigned long diff;
+	  Invf_Doc_Entry ent, *mem;
+	  if (k)
+	    {
+	      if (Anding && i + k < p && next->DocNum > next_doc_num &&
+		  next_doc_num >= 0)
+		{
+		  i = next_i;
+		  DECODE_SEEK (next_start);
+		  pos = next_start;
+		  CurrDocNum = next_doc_num;
+		  qd->hops_taken++;
+		  skips_taken++;
+		  kd = k - 1;
+		}
+	      if (kd == k - 1)
+		if (i + k < p)
+		  {
+		    int doc_diff, pos_diff;
+		    BBLOCK_DECODE_L (doc_diff, dn_blk, pos);
+		    next_doc_num += doc_diff;
+		    next_i += k;
+		    BBLOCK_DECODE_L (pos_diff, len_blk, pos);
+		    next_start = pos + pos_diff;
+		  }
+		else
+		  next_doc_num = -1;
+	      if (Anding && i + k < p && next->DocNum > next_doc_num &&
+		  next_doc_num >= 0)
+		continue;
+	    }
+	  if (k && kd == 0 && i != p - 1)
+	    CurrDocNum = next_doc_num;
+	  else
+	    {
+	      BBLOCK_DECODE_L (diff, blk, pos);
+	      CurrDocNum += diff;
+	    }
+	  qd->num_of_ptrs++;
+	  ptrs_dec++;
+	  if (qd->id->ifh.InvfLevel >= 2)
+	    GAMMA_DECODE_L (Count, pos);
+	  else
+	    Count = (double) we->count / p;
+	  i++;
+	  kd--;
+	  if (kd < 0)
+	    kd = k - 1;
+	  Wdt = Count * WordLog;
+
+
+	  if (Anding)
+	    {
+	      while (next && next->DocNum < CurrDocNum - 1)
+		next = SP_get_next (Doc_Set);
+	      if (next && next->DocNum == CurrDocNum - 1)
+		{
+		  next->Sum += Wqt * Wdt;
+		  total_added += Wqt * Wdt;
+		  hits++;
+		}
+	      if (next && next->DocNum <= CurrDocNum - 1)
+		next = SP_get_next (Doc_Set);
+	      goto NextDocNum;
+	    }
+	  ent.DocNum = CurrDocNum - 1;
+	  if ((mem = SP_member (&ent, Doc_Set)) == NULL)
+	    {
+	      hits++;
+	      if (rqi->MaxAccums != -1 &&
+		  Doc_Set->no_of_items >= rqi->MaxAccums &&
+		  !MoreAccum)
+		goto NextDocNum;
+	      if ((mem = get_ide (qd, pool)) == NULL)
+		return NULL;
+	      ChangeMemInUse (qd, sizeof (*mem));
+	      mem->DocNum = CurrDocNum - 1;
+	      mem->Sum = 0;
+	      ChangeMemInUse (qd, -Doc_Set->mem_in_use);
+	      if (SP_insert (mem, Doc_Set) == NULL)
+		{
+		  Message ("Unable to allocate memory for a splay node");
+		  Abort = 1;
+		  goto FastAbort;
+		}
+	      ChangeMemInUse (qd, Doc_Set->mem_in_use);
+	      if (rqi->MaxAccums != -1 &&
+		  Doc_Set->no_of_items >= rqi->MaxAccums &&
+		  rqi->StopAtMaxAccum)
+		Abort = 1;
+	    }
+
+	  mem->Sum += Wqt * Wdt;
+	  total_added += Wqt * Wdt;
+
+	NextDocNum:
+	  ;
+	}
+
+    FastAbort:
+
+      DECODE_DONE
+
+	Xfree (buffer);
+      ChangeMemInUse (qd, -we->invf_len);
+      if (sk)
+	{
+	  if (qd->id->ifh.skip_mode != 0)
+	    fprintf (sk, " %6d", skips_taken);
+	  fprintf (sk, " %6d %6d %6d%12.2f\n",
+		   ptrs_dec, hits, Doc_Set->no_of_items, total_added);
+	}
+      if (Abort)
+	break;
+    }
+  if (sk)
+    fclose (sk);
+  return Doc_Set;
+}
+
+
+
+
+Hash_Table *
+CosineDecodeHash (query_data * qd, TermList * Terms,
+		  RankedQueryInfo * rqi)
+{
+  int j, num_docs, num_terms, MoreAccum;
+  Hash_Table *HT;
+  int Anding = 0;
+  int Sorted = 0;
+  FILE *sk = open_skip (rqi->skip_dump);
+  u_char indent = 0;
+  if (sk)
+    {
+      if (!skip_header)
+	{
+	  skip_header = 1;
+	  fprintf (sk, "%s", skip_header_text[qd->id->ifh.skip_mode]);
+	  fprintf (sk, "\nSkipping method %ld\n", qd->id->ifh.skip_mode);
+	  switch (qd->id->ifh.skip_mode)
+	    {
+	    case 1:
+	      fprintf (sk, "Skipping is every %ld docnums\n",
+		       qd->id->ifh.params[0]);
+	      break;
+	    case 2:
+	      fprintf (sk, "Max nodes = %ld\nNo skips smaller or equal to %ld\n",
+		       qd->id->ifh.params[0], qd->id->ifh.params[1]);
+	      break;
+	    }
+	}
+      fprintf (sk, "\n\t\t\t-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n");
+      for (j = 0; j < Terms->num; j++)
+	if (Terms->TE[j].Word[0] > indent)
+	  indent = Terms->TE[j].Word[0];
+    }
+
+  num_docs = qd->sd->sdh.num_of_docs;
+  /* Create the array for the documents */
+  HT = HT_create (qd, rqi->MaxAccums, rqi->HashTblSize);
+  if (!HT)
+    return NULL;
+
+  if (rqi->MaxTerms == -1)
+    num_terms = Terms->num;
+  else
+    num_terms = rqi->MaxTerms < Terms->num ? rqi->MaxTerms : Terms->num;
+
+  MoreAccum = 1;
+
+  /* For each word in the list . . . */
+  for (j = 0; j < num_terms; j++)
+    {
+      int Abort = 0;
+      u_char *buffer;
+      int pos;
+      int i;
+      unsigned long CurrDocNum = 0;	/* NOTE: Document numbers start at 1 */
+      double Wqt, WordLog;
+      int dn_blk = 0, len_blk = 0, k, kd;
+      int blk;			/* bblock control parameter */
+      int p;			/* The number of documents the word occurs in */
+      WordEntry *we = &Terms->TE[j].WE;
+      Invf_Doc_EntryH *next = NULL;
+      int next_i, next_doc_num, next_start;
+      int skips_taken = 0, ptrs_dec = 0;
+      double total_added = 0.0;
+      int hits = 0;
+      if (sk)
+	{
+	  fprintf (sk, "%3d : %8ld %6ld \"%.*s\"%*s", j, we->count,
+		 we->doc_count, Terms->TE[j].Word[0], Terms->TE[j].Word + 1,
+		   indent - Terms->TE[j].Word[0], "");
+	}
+
+      CalcBlks (qd, we, &blk, &dn_blk, &len_blk, &k, &p);
+      if (!(buffer = Xmalloc (we->invf_len)))
+	break;
+
+      ChangeMemInUse (qd, we->invf_len);
+
+      if (sk && qd->id->ifh.skip_mode == 2)
+	fprintf (sk, "%4d", k);
+
+      Fseek (qd->File_invf, we->invf_ptr, 0);
+      Fread (buffer, sizeof (char), we->invf_len, qd->File_invf);
+
+      /* Read from the buffer */
+      DECODE_START (buffer, we->invf_len);
+
+      WordLog = log ((double) num_docs / (double) we->max_doc_count);  /* [RPAP - Jan 97: Stem Index Change] */
+
+      Wqt = (rqi->QueryFreqs ? Terms->TE[j].Count : 1) * WordLog;
+
+      qd->num_of_terms++;
+
+      if (rqi->MaxAccums != -1 && HT->num >= rqi->MaxAccums)
+	{
+	  MoreAccum = 0;
+	  Anding = 1;
+	  if (!Sorted)
+	    {
+	      HT_sort (qd, HT);
+	      Sorted = 1;
+	    }
+	  next = HT->Head;
+	}
+      i = pos = 0;
+      next_i = next_start = next_doc_num = 0;
+      kd = k - 1;
+      while (i < p && (!Anding || next))
+	{
+	  int Count;		/* The number of times the occurs in a document */
+	  double Wdt;
+	  unsigned long diff;
+	  Invf_Doc_Entry *mem;
+	  if (k)
+	    {
+	      if (Anding && i + k < p && next->IDE.DocNum > next_doc_num &&
+		  next_doc_num >= 0)
+		{
+#ifdef SHORT_CUT
+		ShortCut:
+#endif
+		  i = next_i;
+		  DECODE_SEEK (next_start);
+		  pos = next_start;
+		  CurrDocNum = next_doc_num;
+		  qd->hops_taken++;
+		  skips_taken++;
+		  kd = k - 1;
+		}
+	      if (kd == k - 1)
+		{
+		  if (i + k < p)
+		    {
+		      int doc_diff, pos_diff;
+		      BBLOCK_DECODE_L (doc_diff, dn_blk, pos);
+		      next_doc_num += doc_diff;
+		      next_i += k;
+		      BBLOCK_DECODE_L (pos_diff, len_blk, pos);
+		      next_start = pos + pos_diff;
+		    }
+		  else
+		    next_doc_num = -1;
+		}
+#ifdef SHORT_CUT
+	      if (Anding && i + k < p && next->IDE.DocNum > next_doc_num &&
+		  next_doc_num >= 0)
+		goto ShortCut;
+#else
+	      if (Anding && i + k < p && next->IDE.DocNum > next_doc_num &&
+		  next_doc_num >= 0)
+		continue;
+#endif
+	    }
+	  if (k && kd == 0 && i != p - 1)
+	    {
+	      CurrDocNum = next_doc_num;
+	    }
+	  else
+	    {
+	      BBLOCK_DECODE_L (diff, blk, pos);
+	      CurrDocNum += diff;
+	    }
+	  qd->num_of_ptrs++;
+	  ptrs_dec++;
+	  if (qd->id->ifh.InvfLevel >= 2)
+	    GAMMA_DECODE_L (Count, pos);
+	  else
+	    Count = (double) we->count / p;
+	  i++;
+	  kd--;
+	  if (kd < 0)
+	    kd = k - 1;
+
+
+	  if (Anding)
+	    {
+	      while (next && next->IDE.DocNum < CurrDocNum - 1)
+		next = next->next;
+	      if (next && next->IDE.DocNum == CurrDocNum - 1)
+		{
+		  Wdt = Count * WordLog;
+		  next->IDE.Sum += Wqt * Wdt;
+		  total_added += Wqt * Wdt;
+		  hits++;
+		}
+	      if (next && next->IDE.DocNum <= CurrDocNum - 1)
+		next = next->next;
+	      goto NextDocNum;
+	    }
+	  if ((mem = HT_find (HT, CurrDocNum - 1)) == NULL)
+	    {
+	      if (rqi->MaxAccums != -1 && HT->num >= rqi->MaxAccums &&
+		  !MoreAccum)
+		goto NextDocNum;
+	      Wdt = Count * WordLog;
+	      if (!HT_insert (HT, CurrDocNum - 1, Wqt * Wdt))
+		{
+		  if (!HT->Suplimentary_Entries)
+		    HT_Sup_create (qd, HT, we->doc_count - i + 1);
+		  HT_Sup_Add (HT, CurrDocNum - 1, Wqt * Wdt);
+		}
+	      if (rqi->MaxAccums != -1 && HT->num >= rqi->MaxAccums &&
+		  rqi->StopAtMaxAccum)
+		Abort = 1;
+	    }
+	  else
+	    {
+	      Wdt = Count * WordLog;
+	      mem->Sum += Wqt * Wdt;
+	      total_added += Wqt * Wdt;
+	      hits++;
+	    }
+
+	NextDocNum:
+	  ;
+	}
+
+      DECODE_DONE
+
+	Xfree (buffer);
+      ChangeMemInUse (qd, -we->invf_len);
+      if (sk)
+	{
+	  if (qd->id->ifh.skip_mode != 0)
+	    fprintf (sk, " %6d", skips_taken);
+	  fprintf (sk, " %6d %6d %6d%12.2f\n",
+	       ptrs_dec, hits, HT->num + HT->Suplimentary_Num, total_added);
+	}
+      if (Abort)
+	break;
+    }
+  if (sk)
+    fclose (sk);
+  if (!HT->Head)
+    HT_sort (qd, HT);
+  return HT;
+}
+
+
+
+List_Table *
+CosineDecodeList (query_data * qd, TermList * Terms,
+		  RankedQueryInfo * rqi)
+{
+  int j, num_docs, num_terms, MoreAccum;
+  List_Table *LT;
+  int Anding = 0;
+  int Sorted = 0;
+  int has_grown = 0; /* [RJM 07/97: Ranked Required Match] whether elements have been added lately */
+  FILE *sk = open_skip (rqi->skip_dump);
+  u_char indent = 0;
+  if (sk)
+    {
+      if (!skip_header)
+	{
+	  skip_header = 1;
+	  fprintf (sk, "%s", skip_header_text[qd->id->ifh.skip_mode]);
+	  fprintf (sk, "\nSkipping method %ld\n", qd->id->ifh.skip_mode);
+	  switch (qd->id->ifh.skip_mode)
+	    {
+	    case 1:
+	      fprintf (sk, "Skipping is every %ld docnums\n",
+		       qd->id->ifh.params[0]);
+	      break;
+	    case 2:
+	      fprintf (sk, "Max nodes = %ld\nNo skips smaller or equal to %ld\n",
+		       qd->id->ifh.params[0], qd->id->ifh.params[1]);
+	      break;
+	    }
+	}
+      fprintf (sk, "\n\t\t\t-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n");
+      for (j = 0; j < Terms->num; j++)
+	if (Terms->TE[j].Word[0] > indent)
+	  indent = Terms->TE[j].Word[0];
+    }
+
+  num_docs = qd->sd->sdh.num_of_docs;
+
+  /* Create the list for the documents */
+  LT = LT_create (qd, rqi->MaxAccums);
+  if (!LT)
+    return NULL;
+
+  if (rqi->MaxTerms == -1)
+    num_terms = Terms->num;
+  else
+    num_terms = rqi->MaxTerms < Terms->num ? rqi->MaxTerms : Terms->num;
+
+  MoreAccum = 1;
+
+  /* For each word in the list . . . */
+  for (j = 0; j < num_terms; j++)
+    {
+      int Abort = 0;
+      u_char *buffer;
+      int pos;
+      int i, n = 0;
+      unsigned long CurrDocNum = 0;	/* NOTE: Document numbers start at 1 */
+      unsigned long LastDocNum = 0;	/* [RJM 07/97: Ranked Required Match] */
+      int this_item = 0; /* [RJM 07/97: Ranked Required Match] points to the next possible LT to delete */
+      double Wqt, WordLog;
+      int dn_blk = 0, len_blk = 0, k, kd;
+      int blk;			/* bblock control parameter */
+      int p;			/* The number of documents the word occurs in */
+      int require_match = Terms->TE[j].require_match; /* [RJM 07/97: Ranked Required Match] */
+      WordEntry *we = &Terms->TE[j].WE;
+      Invf_Doc_Entry *next = NULL;
+      int next_i, next_doc_num, next_start;
+      int skips_taken = 0, ptrs_dec = 0;
+      double total_added = 0.0;
+      int hits = 0;
+
+      if (sk)
+	{
+	  fprintf (sk, "%3d : %8ld %6ld \"%.*s\"%*s", j, we->count,
+		 we->doc_count, Terms->TE[j].Word[0], Terms->TE[j].Word + 1,
+		   indent - Terms->TE[j].Word[0], "");
+	}
+
+      CalcBlks (qd, we, &blk, &dn_blk, &len_blk, &k, &p);
+      if (!(buffer = Xmalloc (we->invf_len)))
+	break;
+
+      ChangeMemInUse (qd, we->invf_len);
+
+      if (sk && qd->id->ifh.skip_mode == 2)
+	fprintf (sk, "%4d", k);
+
+      Fseek (qd->File_invf, we->invf_ptr, 0);
+      Fread (buffer, sizeof (char), we->invf_len, qd->File_invf);
+
+      /* Read from the buffer */
+      DECODE_START (buffer, we->invf_len);
+
+      WordLog = log ((double) num_docs / (double) we->max_doc_count);  /* [RPAP - Jan 97: Stem Index Change] */
+
+      Wqt = (rqi->QueryFreqs ? Terms->TE[j].Count : 1) * WordLog;
+
+      qd->num_of_terms++;
+
+      if (rqi->MaxAccums != -1 && LT->num >= rqi->MaxAccums)
+	MoreAccum = 0;
+
+      if ((rqi->MaxAccums != -1 && LT->num >= rqi->MaxAccums) || Anding)
+	{
+	  Anding = 1;
+	  if (!Sorted || has_grown)
+	    {
+	      LT_sort (LT);
+	      LT_pack (LT);
+	      Sorted = 1;
+	      has_grown = 0;
+	    }
+	  next = LT->IDE;
+	  n = 0;
+	}
+
+      /* [RJM 07/97: Ranked Required Terms] */
+      /* make sure that the document list is set up correctly for */
+      /* requiring a term to match */
+      if (require_match == 1) {
+	if (!Sorted || has_grown) {
+	  LT_sort (LT);
+	  LT_pack (LT);
+	  Sorted = 1;
+	  has_grown = 0;
+	}
+	/* this_item is already set to zero */
+      }
+
+      i = pos = 0;
+      next_i = next_start = next_doc_num = 0;
+      kd = k - 1;
+      while (i < p && (!Anding || n < LT->num))
+	{
+	  int Count;		/* The number of times the occurs in a document */
+	  double Wdt;
+	  unsigned long diff;
+	  Invf_Doc_Entry *mem;
+
+	  /* deal with skipping */
+	  if (k)
+	    {
+	      /* see if we should take a skip */
+	      if (Anding && i + k < p && next->DocNum > next_doc_num &&
+		  next_doc_num >= 0)
+		{
+		  i = next_i;
+		  DECODE_SEEK (next_start);
+		  pos = next_start;
+		  CurrDocNum = next_doc_num;
+		  qd->hops_taken++;
+		  skips_taken++;
+		  kd = k - 1;
+		}
+	      if (kd == k - 1)
+		if (i + k < p)
+		  {
+		    int doc_diff, pos_diff;
+		    BBLOCK_DECODE_L (doc_diff, dn_blk, pos);
+		    next_doc_num += doc_diff;
+		    next_i += k;
+		    BBLOCK_DECODE_L (pos_diff, len_blk, pos);
+		    next_start = pos + pos_diff;
+		  }
+		else
+		  next_doc_num = -1;
+
+	      /* should we take another skip? */
+	      if (Anding && i + k < p && next->DocNum > next_doc_num &&
+		  next_doc_num >= 0)
+		continue;
+	    }
+	  if (k && kd == 0 && i != p - 1)
+	    CurrDocNum = next_doc_num;
+	  else
+	    {
+	      BBLOCK_DECODE_L (diff, blk, pos);
+	      CurrDocNum += diff;
+	    }
+	  qd->num_of_ptrs++;
+	  ptrs_dec++;
+	  if (qd->id->ifh.InvfLevel >= 2)
+	    GAMMA_DECODE_L (Count, pos);
+	  else
+	    Count = (double) we->count / p;
+	  i++;
+	  kd--;
+	  if (kd < 0)
+	    kd = k - 1;
+	  Wdt = Count * WordLog;
+
+	  /* [RJM 07/97: Ranked Required Terms] */
+	  /* if this is a required match we must remove all accumulators */
+	  /* of intermediate documents */
+	  if (require_match == 1) {
+	    while (this_item < LT->num && LT->IDE[this_item].DocNum < CurrDocNum - 1) {
+	      if (LastDocNum==0 ||(LT->IDE[this_item].DocNum > LastDocNum - 1))
+		LT->IDE[this_item].Sum = -1000.0; /* mark for deletion */
+	      this_item++;
+	    }
+	  }
+
+	  if (Anding)
+	    {
+	      while (n < LT->num && next->DocNum < CurrDocNum - 1)
+		{
+		  next++;
+		  n++;
+		}
+	      if (n < LT->num && next->DocNum == CurrDocNum - 1)
+		{
+		  next->Sum += Wqt * Wdt;
+		  total_added += Wqt * Wdt;
+		  hits++;
+		}
+	      if (n < LT->num && next->DocNum <= CurrDocNum - 1)
+		{
+		  next++;
+		  n++;
+		}
+	      goto NextDocNum;
+	    }
+	  if (!Anding)
+	    {
+	      if (rqi->MaxAccums != -1 && LT->num >= rqi->MaxAccums &&
+		  !MoreAccum)
+		goto NextDocNum;
+	      LT = LT_add (qd, LT, CurrDocNum - 1, Wqt * Wdt);
+	      if (!LT)
+		{
+		  Abort = 1;
+		  goto FastAbort;
+		}
+
+	      /* the list of accumulators just got bigger */
+	      has_grown = 1;
+
+	      if (rqi->MaxAccums != -1 && LT->num >= rqi->MaxAccums &&
+		  rqi->StopAtMaxAccum)
+		Abort = 1;
+
+
+	    }
+	  else if ((mem = LT_find (LT, CurrDocNum - 1)))
+	    {
+	      mem->Sum += Wqt * Wdt;
+	      total_added += Wqt * Wdt;
+	      hits++;
+	    }
+
+	NextDocNum:
+
+	  LastDocNum = CurrDocNum;
+	}
+
+    FastAbort:
+
+      DECODE_DONE
+
+	Xfree (buffer);
+      ChangeMemInUse (qd, -we->invf_len);
+      if (sk)
+	{
+	  if (qd->id->ifh.skip_mode != 0)
+	    fprintf (sk, " %6d", skips_taken);
+	  fprintf (sk, " %6d %6d %6d%12.2f\n",
+		   ptrs_dec, hits, LT->num, total_added);
+	}
+      if (Abort)
+	break;
+
+      /* [RJM 07/97: Ranked Required Terms] */
+      /* remove the remaining accumulators if this term is required to match */
+      if (require_match == 1) {
+	while (this_item < LT->num) {
+	  if (LT->IDE[this_item].DocNum > LastDocNum - 1)
+	    LT->IDE[this_item].Sum = -1000.0; /* mark for deletion */
+	  this_item++;
+	}
+	Anding = 1; /* no more documents should be added */
+
+	/* Get rid of any documents which have been deleted */
+	LT_pack (LT);
+      }
+    }
+
+  if (sk)
+    fclose (sk);
+  return LT;
+}
Index: /indexers/branches/3.03a/mg/src/text/invf_get.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/invf_get.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/invf_get.h	(revision 14757)
@@ -0,0 +1,103 @@
+/**************************************************************************
+ *
+ * invf_get.h -- Inverted file reading routines
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#ifndef H_INVF_GET
+#define H_INVF_GET
+
+typedef struct Invf_Doc_Entry
+  {
+    int DocNum;
+    float Sum;
+  }
+Invf_Doc_Entry;
+
+typedef struct Invf_Doc_Entry_Pool
+  {
+    void *pool;
+    unsigned pool_chunks;
+  }
+Invf_Doc_Entry_Pool;
+
+typedef struct Invf_Doc_EntryH
+  {
+    Invf_Doc_Entry IDE;
+    struct Invf_Doc_EntryH *next;
+  }
+Invf_Doc_EntryH;
+
+typedef struct Hash_Table
+  {
+    Invf_Doc_EntryH *Suplimentary_Entries;
+    int Suplimentary_Size;
+    int Suplimentary_Num;
+    unsigned max;
+    unsigned num;
+    unsigned size;
+    Invf_Doc_EntryH **HashTable;
+    Invf_Doc_EntryH *Head;
+    Invf_Doc_EntryH IDEH[1];
+  }
+Hash_Table;
+
+typedef struct List_Table
+  {
+    unsigned max;
+    unsigned num;
+    Invf_Doc_Entry IDE[1];
+  }
+List_Table;
+
+typedef enum
+  {
+    op_term, op_and_terms, op_and_or_terms, op_diff_terms
+  }
+Op_types;
+
+/*Invf_Doc_Entry *HT_find(Hash_Table *HT, unsigned long DN); */
+void HT_free (query_data * qd, Hash_Table * HT);
+void LT_free (query_data * qd, List_Table * LT);
+
+invf_data *InitInvfFile (File * InvfFile, stemmed_dict * sd);
+void FreeInvfData (invf_data * id);
+
+DocList *GetDocs (query_data * qd, WordEntry * we, BooleanQueryInfo * bqi);
+
+float *CosineDecode (query_data * qd, TermList * Terms, RankedQueryInfo * rqi);
+
+void free_ide_pool (query_data * qd, Invf_Doc_Entry_Pool * pool);
+
+Splay_Tree *CosineDecodeSplay (query_data * qd, TermList * Terms,
+			 RankedQueryInfo * rqi, Invf_Doc_Entry_Pool * pool);
+
+Hash_Table *CosineDecodeHash (query_data * qd, TermList * Terms,
+			      RankedQueryInfo * rqi);
+List_Table *CosineDecodeList (query_data * qd, TermList * Terms,
+			      RankedQueryInfo * rqi);
+
+
+DocList *GetDocsOp (query_data * qd, WordEntry * we, Op_types op, DocList * L);
+
+
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/ivf.pass1.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/ivf.pass1.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/ivf.pass1.c	(revision 14757)
@@ -0,0 +1,866 @@
+/**************************************************************************
+ *
+ * ivf.pass1.c -- Memory efficient pass 1 inversion
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "messages.h"
+#include "bitio_m.h"
+#include "bitio_m_stdio.h"
+#include "bitio_gen.h"
+#include "local_strings.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "invf.h"
+#include "mg.h"
+#include "build.h"
+#include "locallib.h"
+#include "words.h"
+#include "stemmer.h"
+#include "hash.h"
+
+#include "longlong.h"
+
+/*
+   $Log$
+   Revision 1.2  2004/06/10 03:02:05  kjdon
+   fixed the bug that was causing it not to be able to create a second index using jni - basically had to reset all the static variables at the start of each pass. the tricky thing to find was the static variables in occur_to_lexical in ivf.pass2
+
+   Revision 1.1  2003/02/20 21:18:23  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.2  2001/09/21 12:46:42  kjm18
+   updated mg to be in line with mg_1.3f. Now uses long long for some variables
+   to enable indexing of very large collections.
+
+   Revision 1.1  1999/08/10 21:17:54  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.3  1998/12/17 09:12:50  rjmcnab
+
+   Altered mg to process utf-8 encoded Unicode. The main changes
+   are in the parsing of the input, the casefolding, and the stemming.
+
+   Revision 1.2  1998/11/25 07:55:43  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:34:44  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.6  1995/01/16  03:57:05  tes
+   * Fixed bug for index_string_bytes which was calculated
+   * by adding the suffix lengths except for every lookback (block)
+   * number of words. This was incorrect as invf.dict is fully
+   * front coded - perhaps it was partially coded in the past.
+   * This would only affect a statistic - hence the reason why the
+   * bug could exist ;-)
+   *
+   * Revision 1.5  1994/11/29  00:31:59  tes
+   * Committing the new merged files and changes.
+   *
+   * Revision 1.3  1994/10/20  03:56:48  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:34  tes
+   * For version 1.1
+   *
+ */
+
+/*
+ *  Modified:
+ *   - long long bit counts for inverted file
+ *     (1999-08-05 Tim Bell <bhat@cs.mu.oz.au>)
+ */
+static char *RCSID = "$Id$";
+
+#define LOGLOOKBACK	2
+#define POOL_SIZE 1024*1024
+#define HASH_POOL_SIZE 8192
+#define INITIAL_HASH_SIZE 7927
+
+#define INIT_CHECK_FRAC 0.10
+#define CHECK_FRAC 0.75
+#define CHECK_CLOSE 0.999
+#define PARA_DIV 1.5
+#define NORM_DIV 1.0
+
+
+typedef struct hash_rec
+  {
+    unsigned long fcnt;		/* fragment frequency */
+    unsigned long lfcnt;	/* local fragment frequency */
+    unsigned long fnum;		/* last fragment to use stem */
+    unsigned long wcnt;		/* stem frequency */
+    unsigned long lwcnt;	/* local stem frequency */
+    u_char *word;
+  }
+hash_rec;
+
+static unsigned long words_read = 0, words_diff = 0, bytes_diff = 0;
+static unsigned long outputbytes = 0;
+static unsigned long inputbytes = 0;
+static unsigned long MaxMemInUse = 0;
+static unsigned long MemInUse = 0;
+static unsigned long ChunksWritten = 0;
+
+
+static FILE *ic;		/* The invf block file */
+static stdio_bitio_state sbs;
+
+static hash_rec **HashTable;
+static unsigned long HashSize=0;
+static unsigned long HashUsed=0;
+static u_char *Pool;
+static int PoolLeft=0;
+
+static hash_rec *hr_pool;
+static int hr_PoolLeft=0;
+
+static hash_rec **first_occr;
+static int max_first_occr=0;
+
+static mg_ullong L1_bits = 0;
+static mg_ullong L2_bits = 0;
+static mg_ullong L3_bits = 0;
+static unsigned long L1_ohead = 0;
+static unsigned long L2_ohead = 0;
+static unsigned long L3_ohead = 0;
+static unsigned long callnum = 0, lcallnum = 0, wordnum = 0, lwordnum = 0;
+static unsigned long ptrcnt = 0;
+static unsigned long checknum=0;
+static long max_mem = 0;
+
+
+static void 
+ChangeMem (int Change)
+{
+  MemInUse += Change;
+  if (MemInUse > MaxMemInUse)
+    MaxMemInUse = MemInUse;
+}
+
+void
+ResetStaticI1Vars () 
+{
+  words_read = 0;
+  words_diff = 0; 
+  bytes_diff = 0;
+  outputbytes = 0;
+  inputbytes = 0;
+  MaxMemInUse = 0;
+  MemInUse = 0;
+  ChunksWritten = 0;
+  
+  HashSize=0;
+  HashUsed=0;
+  PoolLeft=0;
+  
+  hr_PoolLeft=0;
+  
+  max_first_occr=0;
+  
+  L1_bits = 0;
+  L2_bits = 0;
+  L3_bits = 0;
+  L1_ohead = 0;
+  L2_ohead = 0;
+  L3_ohead = 0;
+  callnum = 0;
+  lcallnum = 0;
+  wordnum = 0;
+  lwordnum = 0;
+  ptrcnt = 0;
+  checknum=0;
+  max_mem = 0;
+  
+}
+int 
+init_ivf_1 (char *file_name)
+{
+  ResetStaticI1Vars();
+  if (!(ic = create_file (file_name, INVF_CHUNK_SUFFIX, "wb", MAGIC_CHUNK,
+			  MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return (COMPERROR);
+  fwrite ("    ", sizeof (u_long), 1, ic);	/* Space for the maxmem */
+  ENCODE_START (ic)
+    ENCODE_PAUSE (sbs)
+
+    if (!(Pool = Xmalloc (POOL_SIZE)))
+    {
+      Message ("Unable to allocate memory for pool");
+      return (COMPERROR);
+    }
+  PoolLeft = POOL_SIZE;
+  ChangeMem (POOL_SIZE);
+
+  if (!(hr_pool = Xmalloc (HASH_POOL_SIZE * sizeof (hash_rec))))
+    {
+      Message ("Unable to allocate memory for pool");
+      return (COMPERROR);
+    }
+  hr_PoolLeft = HASH_POOL_SIZE;
+  ChangeMem (HASH_POOL_SIZE * sizeof (hash_rec));
+
+  HashSize = INITIAL_HASH_SIZE;
+  HashUsed = 0;
+  if (!(HashTable = Xmalloc (sizeof (hash_rec *) * HashSize)))
+    {
+      Message ("Unable to allocate memory for table");
+      return (COMPERROR);
+    }
+  ChangeMem (sizeof (hash_rec *) * HashSize);
+  bzero ((char *) HashTable, sizeof (hash_rec *) * HashSize);
+  max_first_occr = 8192;
+  if (!(first_occr = Xmalloc (sizeof (hash_rec *) * max_first_occr)))
+    {
+      Message ("Unable to allocate memory for first_occur");
+      return (COMPERROR);
+    }
+  ChangeMem (sizeof (hash_rec *) * max_first_occr);
+
+  checknum = (invf_buffer_size * INIT_CHECK_FRAC) /
+    (InvfLevel == 3 ? PARA_DIV : NORM_DIV);
+
+  return (COMPALLOK);
+}
+
+
+
+static unsigned long 
+mem_reqd (void)
+{
+  register int i;
+  register unsigned long total = 0;
+/*  register unsigned long N = InvfLevel == 3 ? lwordnum : lcallnum; */
+  register unsigned long N = lcallnum;
+  for (i = 0; i < HashUsed; i++)
+    {
+      register hash_rec *ent = first_occr[i];
+/*      register unsigned long p = InvfLevel == 3 ? ent->lwcnt : ent->lfcnt; */
+      register unsigned long p = ent->lfcnt;
+      if (p)
+	total += BIO_Bblock_Bound (N, p);
+      if (InvfLevel >= 2)
+	total += ent->lwcnt;
+    }
+
+  total = (total + 7) >> 3;
+  return total;
+}
+
+static unsigned long 
+max_mem_reqd (void)
+{
+  register int i;
+  register unsigned long total = 0;
+/*  register unsigned long N = InvfLevel == 3 ? wordnum : callnum; */
+  register unsigned long N = callnum;
+  for (i = 0; i < HashUsed; i++)
+    {
+      register hash_rec *ent = first_occr[i];
+/*      register unsigned long p = InvfLevel == 3 ? ent->wcnt : ent->fcnt; */
+      register unsigned long p = ent->fcnt;
+      if (p)
+	total += BIO_Bblock_Bound (N, p);
+      if (InvfLevel >= 2)
+	total += ent->wcnt;
+    }
+
+  total = (total + 7) >> 3;
+  return total;
+}
+
+
+static void 
+dump_dict (unsigned long mem)
+{
+  int i;
+
+  ChunksWritten++;
+
+  ENCODE_CONTINUE (sbs)
+
+    GAMMA_ENCODE (lcallnum + 1);
+  if (mem > max_mem)
+    max_mem = mem;
+  GAMMA_ENCODE (mem + 1);
+  lwordnum = lcallnum = 0;
+  GAMMA_ENCODE (HashUsed + 1);
+  for (i = 0; i < HashUsed; i++)
+    {
+      hash_rec *ent = first_occr[i];
+      GAMMA_ENCODE (ent->lwcnt + 1);
+      if (ent->lwcnt >= 2)
+	GAMMA_ENCODE (ent->lfcnt);
+      ent->lwcnt = ent->lfcnt = 0;
+    }
+  ptrcnt = 0;
+  ENCODE_PAUSE (sbs)
+}
+
+
+
+static int 
+process_doc (u_char * s_in, int l_in)
+{
+  u_char *end = s_in + l_in - 1;
+
+  callnum++;
+  lcallnum++;
+  inputbytes += l_in;
+
+  if (!inaword (s_in, end))
+    if (SkipSGML)
+      PARSE_NON_STEM_WORD_OR_SGML_TAG (s_in, end);
+    else
+      PARSE_NON_STEM_WORD (s_in, end);
+  /*
+   ** Alternately parse off words and non-words from the input
+   ** stream beginning with a non-word. Each token is then
+   ** inserted into the set if it does not exist or has it's
+   ** frequency count incremented if it does.
+   */
+  while (s_in <= end)
+    {
+      u_char Word[MAXSTEMLEN + 1];
+
+      PARSE_STEM_WORD (Word, s_in, end);
+      
+      stemmer (stem_method, stemmer_num, Word);
+      if (SkipSGML)
+	PARSE_NON_STEM_WORD_OR_SGML_TAG (s_in, end);
+      else
+	PARSE_NON_STEM_WORD (s_in, end);
+
+      words_read++;
+      wordnum++;
+      lwordnum++;
+      /* Search the hash table for Word */
+      {
+	register unsigned long hashval, step;
+	register int hsize = HashSize;
+	HASH (hashval, step, Word, hsize);
+	for (;;)
+	  {
+	    register u_char *s1;
+	    register u_char *s2;
+	    register int len;
+	    register hash_rec *ent;
+	    ent = HashTable[hashval];
+	    if (!ent)
+	      {
+		int len = *Word + 1;
+		if (!hr_PoolLeft)
+		  {
+		    if (!(hr_pool = Xmalloc (HASH_POOL_SIZE *
+					     sizeof (hash_rec))))
+		      {
+			Message ("Unable to allocate memory for pool");
+			return (COMPERROR);
+		      }
+		    hr_PoolLeft = HASH_POOL_SIZE;
+		    ChangeMem (HASH_POOL_SIZE * sizeof (hash_rec));
+		  }
+		ent = hr_pool++;
+		hr_PoolLeft--;
+		if (len > PoolLeft)
+		  {
+		    if (!(Pool = Xmalloc (POOL_SIZE)))
+		      {
+			Message ("Unable to allocate memory for pool");
+			return (COMPERROR);
+		      }
+		    PoolLeft = POOL_SIZE;
+		    ChangeMem (POOL_SIZE);
+		  }
+		ent->wcnt = 1;
+		ent->fcnt = 1;
+		ent->lwcnt = 1;
+		ent->lfcnt = 1;
+		ent->fnum = callnum;
+		ent->word = Pool;
+		memcpy (Pool, Word, len);
+		Pool += len;
+		PoolLeft -= len;
+		if (HashUsed == max_first_occr - 1)
+		  {
+		    ChangeMem (-sizeof (hash_rec *) * max_first_occr);
+		    max_first_occr *= 2;
+		    if (!(first_occr = Xrealloc (first_occr, sizeof (hash_rec *) *
+						 max_first_occr)))
+		      {
+			Message ("Unable to allocate memory for first_occr");
+			return (COMPERROR);
+		      }
+		    ChangeMem (sizeof (hash_rec *) * max_first_occr);
+		  }
+		first_occr[HashUsed] = ent;
+		HashUsed++;
+		HashTable[hashval] = ent;
+		bytes_diff += Word[0];
+		break;
+	      }
+
+	    /* Compare the words */
+	    s1 = Word;
+	    s2 = ent->word;
+	    len = *s1 + 1;
+	    for (; len; len--)
+	      if (*s1++ != *s2++)
+		break;
+
+	    if (len)
+	      {
+		hashval = (hashval + step);
+		if (hashval >= hsize)
+		  hashval -= hsize;
+	      }
+	    else
+	      {
+		ent->wcnt++;
+		ent->lwcnt++;
+		if (callnum > ent->fnum)
+		  {
+		    ptrcnt++;
+		    ent->fcnt++;
+		    ent->lfcnt++;
+		    ent->fnum = callnum;
+		  }
+		break;
+	      }
+	  }
+      }
+
+      if (HashUsed >= HashSize >> 1)
+	{
+	  hash_rec **ht;
+	  unsigned long size;
+	  unsigned long i;
+	  size = prime (HashSize * 2);
+	  if (!(ht = Xmalloc (sizeof (hash_rec *) * size)))
+	    {
+	      Message ("Unable to allocate memory for table");
+	      return (COMPERROR);
+	    }
+	  bzero ((char *) ht, sizeof (hash_rec *) * size);
+	  ChangeMem (sizeof (hash_rec *) * size);
+
+	  for (i = 0; i < HashSize; i++)
+	    if (HashTable[i])
+	      {
+		register u_char *wptr;
+		hash_rec *ent;
+		register unsigned long hashval, step;
+
+		wptr = HashTable[i]->word;
+		HASH (hashval, step, wptr, size);
+		ent = ht[hashval];
+		while (ent)
+		  {
+		    hashval += step;
+		    if (hashval >= size)
+		      hashval -= size;
+		    ent = ht[hashval];
+		  }
+		ht[hashval] = HashTable[i];
+	      }
+	  Xfree (HashTable);
+	  ChangeMem (-sizeof (hash_rec *) * HashSize);
+	  HashTable = ht;
+	  HashSize = size;
+	}
+
+    }
+
+  if (ptrcnt >= checknum)
+    {
+      unsigned long mem;
+      /*fprintf(stderr, "Checking at %u . . . ", ptrcnt); */
+      mem = mem_reqd ();
+      if (mem >= invf_buffer_size * CHECK_CLOSE)
+	{
+	  /*fprintf(stderr, "Got a match\n"); */
+	  dump_dict (mem);
+	  checknum = (invf_buffer_size * INIT_CHECK_FRAC) /
+	    (InvfLevel == 3 ? PARA_DIV : NORM_DIV);
+	}
+      else
+	{
+	  checknum = checknum * ((CHECK_FRAC * (invf_buffer_size - mem)) / mem) +
+	    checknum;
+	  if (checknum <= ptrcnt)
+	    checknum = ptrcnt + 1;
+	  /*fprintf(stderr, "Next check at %u\n", checknum); */
+	}
+    }
+  return (COMPALLOK);
+
+}				/* encode */
+
+
+int 
+process_ivf_1 (u_char * s_in, int l_in)
+{
+  if (InvfLevel <= 2)
+    return process_doc (s_in, l_in);
+  else
+    {
+      int pos = 0;
+      u_char *start = s_in;
+      while (pos < l_in)
+	{
+	  if (s_in[pos] == TERMPARAGRAPH)
+	    {
+	      int len = pos + s_in + 1 - start;
+	      if (process_doc (start, len) != COMPALLOK)
+		return (COMPERROR);
+	      start = s_in + pos + 1;
+	    }
+	  pos++;
+	}
+      if (start < s_in + pos)
+	return process_doc (start, pos + s_in - start);
+    }
+  return COMPALLOK;
+}
+
+static int 
+PackHashTable (void)
+{
+  int s, d;
+  for (s = d = 0; s < HashSize; s++)
+    if (HashTable[s])
+      HashTable[d++] = HashTable[s];
+  ChangeMem (-sizeof (hash_rec *) * HashSize);
+  ChangeMem (sizeof (hash_rec *) * HashUsed);
+  if (!(HashTable = Xrealloc (HashTable, sizeof (hash_rec *) * HashUsed)))
+    {
+      Message ("Out of memory");
+      return COMPERROR;
+    }
+  HashSize = HashUsed;
+  return COMPALLOK;
+}
+
+
+
+
+
+static int 
+ent_comp (const void *A, const void *B)
+{
+  u_char *s1 = (*((hash_rec **) A))->word;
+  u_char *s2 = (*((hash_rec **) B))->word;
+
+  return (casecompare (s1, s2)); /* [RPAP - Jan 97: Stem Index Change] */
+}				/* stem_comp */
+
+
+
+
+
+/*
+ * void count_text()
+ *
+ * The maths used in this function is described in the paper "Coding for 
+ * Compression in Full-Text Retrieval Systems"
+ *
+ */
+static void 
+count_text ()
+{
+  int i;
+  mg_ullong oldL12_bits = 0;
+  for (i = 0; i < HashUsed; i++)
+    {
+      hash_rec *wrd = HashTable[i];
+      /* estimate size of a level 1 inverted file */
+      L1_bits += (int) (0.99 + wrd->fcnt * (1.6 + log2 (1.0 * callnum / wrd->fcnt)));
+      L1_ohead += BIO_Gamma_Length (wrd->fcnt);
+
+      L2_bits += BIO_Unary_Length (wrd->wcnt);
+      L2_ohead += BIO_Gamma_Length (wrd->wcnt - wrd->fcnt + 1);
+
+      L3_bits += (int) (0.99 + wrd->wcnt *
+		  (1.6 + log2 (1.0 * words_read / (wrd->wcnt + callnum))));
+      L3_ohead += 0;
+
+      /* check for overflow */
+      if (L1_bits + L2_bits < oldL12_bits) {
+	fprintf(stderr, "ERROR: Inverted file size will probably overflow %d byte unsigned integer\n", sizeof (mg_ullong));
+	fprintf(stderr, "       counter in pass 2.\n");
+	if (sizeof (mg_ullong) < 8) {
+	  fprintf(stderr, "       Try compiling with GCC to enable use of 8 bytes for this counter.\n");
+	}
+	fprintf(stderr, "       Build aborted.\n");
+	exit(1);
+      }
+      oldL12_bits = L1_bits + L2_bits;
+    }
+  L3_bits = (L3_bits + L2_bits + L1_bits + 7) / 8;
+  L3_ohead = (L3_ohead + L2_ohead + L1_ohead + 7) / 8;
+  L2_bits = (L2_bits + L1_bits + 7) / 8;
+  L2_ohead = (L2_ohead + L1_ohead + 7) / 8;
+  L1_bits = (L1_bits + 7) / 8;
+  L1_ohead = (L1_ohead + 7) / 8;
+}				/* count_text */
+
+
+
+/*
+ *    write_stem_file():
+ *              writes out the stemmed dictionary file
+ *              in the following format 
+ *                      lookback value (int)
+ *                      totalbytes value (int)
+ *                      indexstringbytes (int)
+ *                      for each word 
+ *                        wordlen (4 bits)
+ *                        prefix match (4 bits)
+ *                        word (wordlen bytes)
+ *                        word frequency (int)
+ *                        word count (int)
+ *
+ *      Accesses outside variables:     
+ *
+ *      Return value...:                
+ */
+
+static void 
+write_stem_file (char *file_name)
+{
+  long j;
+  struct invf_dict_header idh;
+  long lookback = (1 << LOGLOOKBACK);	/* ???? */
+  long totalbytes = 0;		/* The sum of the length of all words, including 
+				   the length byte */
+  long indexstringbytes = 0;	/* The amount of space required to store the 
+				   words in the diction, this takes into account 
+				   the prefixes */
+  u_char *lastword = NULL;	/* A pointer to the last word processed */
+  FILE *sp;
+
+
+  /* Calculate the size of certain things */
+  for (j = 0; j < HashSize; j++)
+    {
+      u_char *word = HashTable[j]->word;
+      indexstringbytes += word[0] + 2;
+      totalbytes += word[0] + 1;
+      if (lastword)
+	indexstringbytes -= prefixlen (lastword, word);
+      lastword = word;
+    }
+
+  lastword = NULL;
+
+  if (!(sp = create_file (file_name, INVF_DICT_SUFFIX, "wb", MAGIC_STEM_BUILD,
+			  MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return;
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL2(lookback, idh.lookback);
+  HTONUL2(HashSize, idh.dict_size);
+  HTONUL2(totalbytes, idh.total_bytes);
+  HTONUL2(indexstringbytes, idh.index_string_bytes);
+  HTOND2(inputbytes, idh.input_bytes); /* [RJM 07/97: 4G limit] */
+  HTONUL2(callnum, idh.num_of_docs);
+  HTONUL2(callnum, idh.static_num_of_docs);
+  HTONUL2(words_read, idh.num_of_words);
+  HTONUL2(stemmer_num, idh.stemmer_num);
+  HTONUL2(stem_method, idh.stem_method);
+
+  fwrite ((char *) &idh, sizeof (idh), 1, sp);
+  outputbytes += sizeof (idh);
+
+  for (j = 0; j < HashSize; j++)
+    {
+      int i;
+      unsigned long wcnt, fcnt;  /* [RPAP - Jan 97: Endian Ordering] */
+      hash_rec *ent = HashTable[j];
+      if (lastword != NULL)
+	/* look for prefix match with prev string */
+	i = prefixlen (lastword, ent->word);
+      else
+	i = 0;
+      fputc (i, sp);
+      fputc (ent->word[0] - i, sp);
+      fwrite ((char *) ent->word + i + 1, sizeof (u_char), ent->word[0] - i, sp);
+      outputbytes += ent->word[0] - i + 1;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      HTONUL2(ent->fcnt, fcnt);
+      fwrite ((char *) &(fcnt), sizeof (fcnt), 1, sp);
+
+      outputbytes += sizeof (ent->fcnt);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      HTONUL2(ent->wcnt, wcnt);
+      fwrite ((char *) &(wcnt), sizeof (wcnt), 1, sp);
+
+      outputbytes += sizeof (ent->wcnt);
+      lastword = ent->word;
+    }
+
+  fclose (sp);
+}				/* write_stem_file() */
+
+
+
+/*
+ *    write_codes():
+ *              calls functions to assign and write out codes and
+ *              then prints out stats about execution results.
+ *
+ *      Accesses outside variables:     z
+ *
+ *      Return value...:                z
+ */
+
+static void 
+write_codes (char *file_name)
+{
+  unsigned long dicts = 0;
+  outputbytes = 0;
+  write_stem_file (file_name);
+  dicts = outputbytes;
+
+#ifndef SILENT
+  Message ("Chunks written      : %d\n",
+	   ChunksWritten);
+  if (InvfLevel == 3)
+    Message ("Paragraphs          : %8d\n", callnum);
+  Message ("Peak memory usage   : %10.1f Mb\n",
+	   (double) MaxMemInUse / 1024.0 / 1024.0);
+  Message ("Stems size          : %10.1f kB  %5.2f%%\n",
+	   (double) dicts / 1024, (double) 100 * dicts / inputbytes);
+  Message ("Lev 1 inverted file : %10.1f kB  %5.2f%%\n",
+	   (double) (L1_bits + L1_ohead) / 1024,
+	   (double) 100 * (L1_bits + L1_ohead) / inputbytes);
+  Message ("Lev 2 inverted file : %10.1f kB  %5.2f%%\n",
+	   (double) (L2_bits + L2_ohead) / 1024,
+	   (double) 100 * (L2_bits + L2_ohead) / inputbytes);
+  Message ("Lev 3 inverted file : %10.1f kB  %5.2f%%\n",
+	   (double) (L3_bits + L3_ohead) / 1024,
+	   (double) 100 * (L3_bits + L3_ohead) / inputbytes);
+  Message ("Record addresses    : %10.1f kB  %5.2f%%\n",
+	   (double) words_diff * 4 / 1024, (double) 100 * words_diff * 4 / inputbytes);
+#endif
+}				/* write_codes() */
+
+
+
+void 
+write_num_file (char *file_name)
+{
+
+  int i;
+  FILE *f;
+
+  for (i = 0; i < HashSize; i++)
+    HashTable[i]->fnum = i;
+
+  if (!(f = create_file (file_name, INVF_CHUNK_TRANS_SUFFIX, "wb",
+			 MAGIC_CHUNK_TRANS, MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return;
+
+#if 1
+  ENCODE_START (f)
+
+    for (i = 0; i < HashSize; i++)
+    BINARY_ENCODE (first_occr[i]->fnum + 1, HashSize + 1);
+
+  ENCODE_DONE;
+#else
+  for (i = 0; i < HashSize; i++)
+    {
+      /* [RPAP - Jan 97: Endian Ordering] */
+      unsigned long fnum;
+      HTONUL2(first_occur[i]->fnum, fnum);
+      fwrite ((char *) &fnum, sizeof (unsigned long), 1, f);
+    }
+#endif
+
+  fclose (f);
+}
+
+int 
+done_ivf_1 (char *FileName)
+{
+  char *temp_str = msg_prefix;
+  msg_prefix = "ivf.pass1";
+#ifndef SILENT
+  Message ("Mem reqd for 1 chunk: %8u bytes\n",
+	   max_mem_reqd ());
+#endif
+  if (lcallnum)
+    dump_dict (mem_reqd ());
+
+  if (PackHashTable () == COMPERROR)
+    return COMPERROR;
+
+  qsort (HashTable, HashUsed, sizeof (hash_rec *), ent_comp);
+
+  count_text ();
+  write_codes (FileName);
+
+  ENCODE_CONTINUE (sbs)
+    GAMMA_ENCODE (1);
+  ENCODE_DONE
+    fseek (ic, sizeof (long), 0);
+  
+  HTONSL(max_mem);  /* [RPAP - Jan 97: Endian Ordering] */
+  fwrite (&max_mem, sizeof (max_mem), 1, ic);
+  NTOHSL(max_mem);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  fclose (ic);
+
+  write_num_file (FileName);
+
+  msg_prefix = temp_str;
+
+  /* free the memory */
+  Xfree(HashTable);
+  if (Pool) {
+    Pool -= (POOL_SIZE-PoolLeft);
+    Xfree(Pool);
+  }
+  if (hr_pool) {
+    hr_pool -= (HASH_POOL_SIZE-hr_PoolLeft);
+    Xfree(hr_pool);
+  }
+  if (first_occr) {
+    Xfree(first_occr);
+  }
+
+  return (COMPALLOK);
+}				/* done_encode */
Index: /indexers/branches/3.03a/mg/src/text/ivf.pass2.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/ivf.pass2.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/ivf.pass2.c	(revision 14757)
@@ -0,0 +1,1191 @@
+/**************************************************************************
+ *
+ * ivf.pass2.c -- Memory efficient pass 2 inversion
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.3  2004/06/10 05:07:43  kjdon
+   have to declare vars before calling functions!!
+
+   Revision 1.2  2004/06/10 03:02:05  kjdon
+   fixed the bug that was causing it not to be able to create a second index using jni - basically had to reset all the static variables at the start of each pass. the tricky thing to find was the static variables in occur_to_lexical in ivf.pass2
+
+   Revision 1.1  2003/02/20 21:18:23  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.2  2001/09/21 12:46:42  kjm18
+   updated mg to be in line with mg_1.3f. Now uses long long for some variables
+   to enable indexing of very large collections.
+
+ * Revision 1.2  1997/08/02  05:01:57  wew
+ * changed literal values of 32 for the bit size of magic numbers of
+ * files to sizeof (unsigned long) * 8, increased the gap at the start
+ * of the invf during processing to 200 bytes
+
+   Revision 1.1  1999/08/10 21:17:54  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.3  1998/12/17 09:12:51  rjmcnab
+
+   Altered mg to process utf-8 encoded Unicode. The main changes
+   are in the parsing of the input, the casefolding, and the stemming.
+
+   Revision 1.2  1998/11/25 07:55:43  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:34:45  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:56:49  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:35  tes
+   * For version 1.1
+   *
+ */
+
+/*
+ *  Modified:
+ *   - long long disk pointers and bit counts for inverted file
+ *     (1999-08-03 Tim Bell <bhat@cs.mu.oz.au>)
+ *     Code provided by Owen de Kretser <oldk@cs.mu.oz.au>
+ */
+
+static char *RCSID = "$Id$";
+
+#include "local_strings.h"
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "messages.h"
+#include "stemmer.h"
+#include "perf_hash.h"
+#include "bitio_m.h"
+#include "bitio_m_mems.h"
+#include "bitio_gen.h"
+#include "bitio_random.h"
+#include "bitio_stdio.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "invf.h"
+#include "locallib.h"
+#include "mg.h"
+#include "build.h"
+#include "words.h"
+#include "hash.h"
+
+#include "longlong.h"
+
+#ifdef USE_LONG_LONG
+#define BIO_Random_Seek_X BIO_Random_Seek_LL
+#define BIO_Random_Tell_X BIO_Random_Tell_LL
+#else
+#define BIO_Random_Seek_X BIO_Random_Seek
+#define BIO_Random_Tell_X BIO_Random_Tell
+#endif
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+#include <io.h>
+#endif
+
+#ifndef RND_BUF_SIZE
+#define RND_BUF_SIZE 8*1024
+/*#define RND_BUF_SIZE 128 */
+#endif
+
+#define print_fsize(file)\
+do\
+  {\
+    struct stat file_state;\
+    fstat(fileno(invf_out), &file_state);\
+    Message("len(invf) = %ld", file_state.st_size);\
+  }while(0)
+
+typedef struct word_rec
+  {
+    unsigned long ptr;
+    unsigned long last;
+  }
+word_rec;
+
+typedef struct invf_state_rec
+  {
+    mg_ullong Disk_Ptr;
+    mg_ullong Disk_Last;
+    unsigned long Disk_B;
+  }
+invf_state_rec;
+
+typedef struct chunk
+  {
+    unsigned long start_doc;
+    unsigned long params_pos;
+    unsigned long disk_pos;
+    unsigned long N;
+  }
+chunk;
+
+
+static FILE *dict;		/* Stemmed dictionary file */
+static FILE *hash;		/* Stemmed dictionary hash file */
+static FILE *invf;		/* Inverted file */
+static FILE *invf_in;		/* Inverted file */
+static FILE *invf_out;		/* Inverted file */
+static FILE *invf_idx;		/* Inverted index file */
+static FILE *count;		/* Count file */
+static FILE *count_trans;	/* Count translation file */
+static FILE *invf_state;	/* Inverted file State */
+static FILE *chunk_state;	/* Chunk state */
+static FILE *chunks;		/* Chunk state */
+static FILE *invf_para = NULL;	/* Paragraph counts file */
+static FILE *weights = NULL;	/* Weights file */
+
+static stdio_bitio_state sbs;
+static random_bitio_state crbs;
+static chunk *chunk_data = NULL;
+static random_bitio_state rbs, rbsp;
+
+static int docs_left = 0, next_docs_left = 0;
+static unsigned long N;
+
+static word_rec *WordRecs;
+static u_char *lg_bs;
+static float *idf = NULL;
+
+static char *MemoryBuffer = NULL;
+static unsigned long MemBufSize;
+static unsigned long BufToUse;
+static struct invf_dict_header idh;
+
+static perf_hash_data *phd;
+
+static unsigned long *word_list = NULL;
+static unsigned long wl_size = 0;
+
+static unsigned long dict_size;
+static unsigned long no_of_ptrs = 0;
+static unsigned long chunks_read = 0;
+static unsigned long Disk_pos = 0;
+static unsigned long callnum = 0;
+static unsigned long wordnum = 0;
+
+static unsigned long totalIbytes = 0;
+static unsigned long totalDbytes = 0;
+static unsigned long totalHbytes = 0;
+
+static unsigned long MemInUse = 0;
+static unsigned long MaxMemInUse = 0;
+static unsigned long max_buffer_len;
+
+void 
+ChangeMemInUse (int mem)
+{
+  MemInUse += mem;
+  if (MemInUse > MaxMemInUse)
+    MaxMemInUse = MemInUse;
+}
+
+void 
+ResetStaticI2Vars() 
+{
+  docs_left = 0;
+  next_docs_left = 0;
+  N = 0;
+  MemBufSize=0;
+  BufToUse=0;
+  memset(&idh, 0, sizeof(idh));
+  wl_size = 0;
+  
+  dict_size = 0;
+  no_of_ptrs = 0;
+  chunks_read = 0;
+  Disk_pos = 0;
+  callnum = 0;
+  wordnum = 0;
+  
+  totalIbytes = 0;
+  totalDbytes = 0;
+  totalHbytes = 0;
+  
+  MemInUse = 0;
+  MaxMemInUse = 0;
+  max_buffer_len = 0;
+
+}
+
+
+static int 
+open_files (char *file_name)
+{
+  char FName[200];
+
+  if (!(dict = open_file (file_name, INVF_DICT_SUFFIX, "rb",
+			  MAGIC_STEM_BUILD, MG_CONTINUE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return (COMPERROR);
+
+  if (!(hash = open_file (file_name, INVF_DICT_HASH_SUFFIX, "rb",
+			  MAGIC_HASH, MG_CONTINUE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return (COMPERROR);
+
+  if (!(count = open_file (file_name, INVF_CHUNK_SUFFIX, "rb",
+			   MAGIC_CHUNK, MG_CONTINUE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return (COMPERROR);
+  fread (&max_buffer_len, sizeof (max_buffer_len), 1, count);
+  NTOHUL(max_buffer_len);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  BIO_Stdio_Decode_Start (count, &sbs);
+  next_docs_left = BIO_Stdio_Gamma_Decode (&sbs, NULL) - 1;
+
+  if (!(count_trans = open_file (file_name, INVF_CHUNK_TRANS_SUFFIX, "rb",
+				 MAGIC_CHUNK_TRANS, MG_CONTINUE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return (COMPERROR);
+
+  if (!(invf = create_file (file_name, INVF_SUFFIX, "w+b",
+			    MAGIC_INVF, MG_CONTINUE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return (COMPERROR);
+  fflush (invf);
+  if (!(invf_in = open_file (file_name, INVF_SUFFIX, "rb",
+			     MAGIC_INVF, MG_CONTINUE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return (COMPERROR);
+  if (!(invf_out = create_file (file_name, INVF_SUFFIX, "wb",
+				MAGIC_INVF, MG_CONTINUE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return (COMPERROR);
+  BIO_Random_Start (invf, RND_BUF_SIZE, &rbs);
+  BIO_Random_Start (invf, RND_BUF_SIZE, &rbsp);
+  ChangeMemInUse (RND_BUF_SIZE * 2);
+
+  if (!(invf_idx = create_file (file_name, INVF_IDX_SUFFIX, "wb",
+				MAGIC_INVI, MG_CONTINUE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return (COMPERROR);
+
+  if (InvfLevel == 3)
+    if (!(invf_para = create_file (file_name, INVF_PARAGRAPH_SUFFIX, "wb",
+				   MAGIC_PARAGRAPH, MG_CONTINUE)))  /* [RPAP - Feb 97: WIN32 Port] */
+      return (COMPERROR);
+
+  sprintf (FName, FILE_NAME_FORMAT ".%ld", get_basepath (), file_name,
+	   ".invf.state", (long) getpid ());  /* [RPAP - Feb 97: WIN32 Port] */
+  if (!(invf_state = fopen (FName, "w+b")))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      Message ("Unable to create \"%s\"", FName);
+      return (COMPERROR);
+    }
+  unlink (FName);
+
+  sprintf (FName, FILE_NAME_FORMAT ".%ld", get_basepath (), file_name,
+	   ".chunk.state", (long) getpid ());  /* [RPAP - Feb 97: WIN32 Port] */
+  if (!(chunk_state = fopen (FName, "w+b")))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      Message ("Unable to create \"%s\"", FName);
+      return (COMPERROR);
+    }
+  unlink (FName);
+  BIO_Random_Start (chunk_state, RND_BUF_SIZE, &crbs);
+  ChangeMemInUse (RND_BUF_SIZE);
+
+  sprintf (FName, FILE_NAME_FORMAT ".%ld", get_basepath (), file_name,
+	   ".chunks", (long) getpid ());  /* [RPAP - Feb 97: WIN32 Port] */
+  if (!(chunks = fopen (FName, "w+b")))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      Message ("Unable to create \"%s\"", FName);
+      return (COMPERROR);
+    }
+  unlink (FName);
+
+  return (COMPALLOK);
+}
+
+
+
+
+
+#define ISR_CACHE 1024
+#define ISR_ENTRY_SIZE (sizeof(mg_ullong)*2 + sizeof(unsigned long))
+
+invf_state_rec *
+in_cache (int pos)
+{
+  static char isr_data[ISR_CACHE * ISR_ENTRY_SIZE];
+  static invf_state_rec isr;
+  static int isr_base = 0, isr_num = -1, isr_pos = -1;
+  if (isr_pos >= 0)
+    bcopy ((char *) &isr, &isr_data[isr_pos * ISR_ENTRY_SIZE], ISR_ENTRY_SIZE);
+  if (pos < isr_base || pos >= isr_base + isr_num)
+    {
+      if (isr_num >= 0)
+	{
+	  fseek (invf_state, isr_base * ISR_ENTRY_SIZE, 0);
+	  fwrite (isr_data, 1, ISR_ENTRY_SIZE * isr_num, invf_state);
+	}
+      isr_base = pos;
+      fseek (invf_state, isr_base * ISR_ENTRY_SIZE, 0);
+      fread (isr_data, 1, ISR_ENTRY_SIZE * ISR_CACHE, invf_state);
+      isr_num = ISR_CACHE;
+    }
+  isr_pos = pos - isr_base;
+  bcopy (&isr_data[isr_pos * ISR_ENTRY_SIZE], (char *) &isr, ISR_ENTRY_SIZE);
+  return &isr;
+}
+
+
+
+
+
+unsigned long 
+occur_to_lexical (long occ, int clear_state)
+{
+  static long pos = -1;
+  static random_bitio_state rbs;
+  static int val = 0;
+  if (clear_state) {
+    pos = -1;
+    val = 0;
+    return 0;
+  }
+  if (pos == -1)
+    {
+      BIO_Random_Start (count_trans, RND_BUF_SIZE, &rbs);
+      pos = 0x7fffffff;
+    }
+  if (occ < pos)
+    {
+      if (occ == -1)
+	{
+	  BIO_Random_Done (&rbs);
+	  return 0;
+	}
+      BIO_Random_Seek_X (sizeof (unsigned long) * 8, &rbs);
+      pos = 0;
+    }
+  while (pos <= occ)
+    {
+      val = BIO_Random_Binary_Decode (dict_size + 1, &rbs, NULL) - 1;
+      pos++;
+    }
+  return (val);
+}
+
+
+void 
+add_chunk_state (unsigned long pos, unsigned long start_doc,
+		 unsigned long N)
+{
+  chunk_data[chunks_read].params_pos = pos;
+  chunk_data[chunks_read].start_doc = start_doc;
+  chunk_data[chunks_read].N = N;
+  chunks_read++;
+}
+
+
+int 
+init_ivf_2 (char *file_name)
+{
+  u_char prev[MAXSTEMLEN + 1];
+  int i;
+  mg_ullong totalIbits;
+  mg_ullong lasttotalIbits;
+  double logN = 0.0;
+
+  ResetStaticI2Vars(); /* clear the global statics */
+  occur_to_lexical(0, 1); /* clear the statics in here*/
+
+  if (open_files (file_name) == COMPERROR)
+    return COMPERROR;
+
+
+  /* Read in the stemmed dictionary file header */
+  fread ((char *) &idh, sizeof (idh), 1, dict);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(idh.lookback);
+  NTOHUL(idh.dict_size);
+  NTOHUL(idh.total_bytes);
+  NTOHUL(idh.index_string_bytes);
+  NTOHD(idh.input_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(idh.num_of_docs);
+  NTOHUL(idh.static_num_of_docs);
+  NTOHUL(idh.num_of_words);
+  NTOHUL(idh.stemmer_num);
+  NTOHUL(idh.stem_method);
+
+  dict_size = idh.dict_size;
+
+  N = idh.num_of_docs;
+
+  if (!(phd = read_perf_hash_data (hash)))
+    {
+      Message ("Unable to read in hash data");
+      return COMPERROR;
+    }
+  totalHbytes = sizeof (perf_hash_data) + sizeof (u_char) * 256 +
+    sizeof (int) * (phd->MAX_N + 1) + sizeof (int *) * 3 * phd->MAX_CH +
+    sizeof (long) * phd->MAX_CH * phd->MAX_L;
+
+  if (!(WordRecs = Xmalloc (sizeof (word_rec) * idh.dict_size)))
+    {
+      Message ("No memory for word entries");
+      return COMPERROR;
+    }
+  totalDbytes += sizeof (word_rec) * idh.dict_size;
+  /* separate storage for the log(b) values, one byte each */
+  if (!(lg_bs = Xmalloc (sizeof (u_char) * idh.dict_size)))
+    {
+      Message ("No memory for lg b's");
+      return COMPERROR;
+    }
+  totalDbytes += sizeof (u_char) * idh.dict_size;
+
+  if (MakeWeights)
+    {
+      /* separate storage for the idf values, one single each */
+      if (!(idf = Xmalloc (sizeof (float) * idh.dict_size)))
+	{
+	  Message ("No memory for idf's");
+	  return COMPERROR;
+	}
+      totalDbytes += sizeof (float) * idh.dict_size;
+
+      if (!(weights = create_file (file_name, WEIGHTS_SUFFIX, "wb",
+				 MAGIC_WGHT, MG_CONTINUE))) { /* [RPAP - Feb 97: WIN32 Port] */
+	Message ("Couldn't open weights file for writing");
+	return (COMPERROR);
+      }
+    }
+  else
+    {
+      unlink (make_name (file_name, WEIGHTS_SUFFIX, NULL));
+    }
+
+  chunk_data = Xmalloc (sizeof (chunk) * (ChunkLimit + 2));
+  totalDbytes += sizeof (chunk) * (ChunkLimit + 2);
+
+  totalIbits = sizeof (unsigned long) * 8;		/* The magic number */
+  totalIbits += 8 * 200;	/* A 200 byte gap */
+
+  if (MakeWeights)
+    {
+      wl_size = 1024;
+      if (!(word_list = Xmalloc (sizeof (*word_list) * wl_size)))
+	{
+	  Message ("No memory for word_list");
+	  return COMPERROR;
+	}
+
+      logN = log ((double) N);
+    }
+
+  for (i = 0; i < idh.dict_size; i++)
+    {
+      invf_state_rec *isr;
+      register unsigned long copy, suff, p;
+      unsigned long fcnt, wcnt;
+
+      lasttotalIbits = totalIbits;
+      
+      copy = fgetc (dict);
+      suff = fgetc (dict);
+      *prev = copy + suff;
+      fread (prev + copy + 1, sizeof (u_char), suff, dict);
+
+      fread ((char *) &fcnt, sizeof (fcnt), 1, dict);
+      fread ((char *) &wcnt, sizeof (wcnt), 1, dict);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(fcnt);
+      NTOHUL(wcnt);
+
+      WordRecs[i].last = 0;
+      WordRecs[i].ptr = 0;
+
+      p = fcnt;
+
+      if (MakeWeights)
+	idf[i] = logN - log ((double) fcnt);
+
+
+      isr = in_cache (i);
+
+      isr->Disk_Last = 0;
+      isr->Disk_Ptr = totalIbits;
+
+      isr->Disk_B = BIO_Bblock_Init (N, p);
+
+      totalIbits += BIO_Bblock_Bound_b (N, p, isr->Disk_B);
+
+      if (InvfLevel >= 2)
+	totalIbits += BIO_Gamma_Bound (wcnt, fcnt);
+
+#ifdef USE_LONG_LONG
+      totalIbits = (totalIbits + 7ull) & 0xfffffffffffffff8ull;
+#else
+      totalIbits = (totalIbits + 7ul) & 0xfffffff8ul;
+#endif
+
+      if (totalIbits < lasttotalIbits) {
+	fprintf(stderr, "ERROR: The totalIbits counter (%d byte unsigned integer) has overflowed.\n", sizeof (mg_ullong));
+	if (sizeof (mg_ullong) < 8) {
+	  fprintf(stderr, "       Try compiling with GCC to enable use of 8 bytes for this counter.\n");
+	}
+	fprintf(stderr, "       Build aborted.\n");
+	exit(1);
+      }
+    }
+
+
+  /* now convert to bytes, and actually get the space */
+#ifdef USE_LONG_LONG
+  totalIbytes = (totalIbits + 7ull) >> 3ull;
+#else
+  totalIbytes = (totalIbits + 7ul) >> 3ul;
+#endif
+  return (COMPALLOK);
+
+}
+
+
+
+
+
+static void 
+LoadCounts (void)
+{
+  unsigned long numwords, i, last_total;
+  static unsigned long local_N = 0;
+  unsigned long totalIbits, crbs_pos;
+  word_rec *wr;
+  unsigned long *counts;
+
+  if (MemoryBuffer == NULL)
+    {
+      MemBufSize = sizeof (unsigned long) * dict_size;
+      if (max_buffer_len > MemBufSize) 
+	MemBufSize = max_buffer_len;
+      if (!(MemoryBuffer = Xmalloc (MemBufSize)))
+	FatalError (1, "Unable to allocate memory for buffer");
+      ChangeMemInUse (MemBufSize);
+    }
+  counts = (unsigned long *) MemoryBuffer;
+/*   bzero ((char *) counts, sizeof (unsigned long) * dict_size); */
+  bzero ((char *) counts, MemBufSize);
+  docs_left = next_docs_left; 
+  if (!docs_left)
+    FatalError (1, "The number of docs in the current chunk is 0");
+
+  BufToUse = BIO_Stdio_Gamma_Decode (&sbs, NULL) - 1;
+
+  numwords = BIO_Stdio_Gamma_Decode (&sbs, NULL) - 1;
+
+  local_N = docs_left;
+
+  for (wr = WordRecs, i = 0; i < dict_size; i++, wr++)
+    wr->ptr = 0; 
+
+  bzero ((char *) lg_bs, dict_size);
+
+  for (i = 0; i < numwords; i++)
+    {
+      unsigned long word_num, wcnt, fcnt, p;
+      word_num = occur_to_lexical (i,0);
+      
+      wr = &WordRecs[word_num];
+      
+      wcnt = BIO_Stdio_Gamma_Decode (&sbs, NULL) - 1;
+      if (wcnt >= 2)
+	fcnt = BIO_Stdio_Gamma_Decode (&sbs, NULL);
+      else
+	fcnt = wcnt;
+
+
+      p = fcnt;
+      if (wcnt)
+	{
+	  register unsigned long length;
+	  counts[word_num] = p;
+	  length = BIO_Bblock_Bound (local_N, p);
+	  if (InvfLevel >= 2)
+	    length += wcnt;
+	  wr->ptr = length;
+	  lg_bs[word_num] = floorlog_2 (BIO_Bblock_Init_W (local_N, p));
+	}
+
+
+  }  
+  crbs_pos = BIO_Random_Tell (&crbs);
+  totalIbits = 0;
+  last_total = 0;
+  for (wr = WordRecs, i = 0; i < dict_size; i++, wr++)
+    {
+      register unsigned long length;
+      length = wr->ptr;
+      wr->last = callnum;
+      BIO_Random_Gamma_Encode (counts[i] + 1, &crbs, NULL);
+      if (counts[i])
+	{
+	  if (i)
+	    BIO_Random_Delta_Encode (totalIbits - last_total + 1, &crbs, NULL);
+	  else
+	    BIO_Random_Delta_Encode (1, &crbs, NULL);
+
+	  last_total = totalIbits;
+	}
+      wr->ptr = totalIbits;
+      totalIbits += length;
+    }
+  add_chunk_state (crbs_pos, callnum, local_N);
+
+  if ((totalIbits + 7ul) >> 3ul > BufToUse)
+    FatalError (1, "Pointers exceed buffer size");
+
+  next_docs_left = BIO_Stdio_Gamma_Decode (&sbs, NULL) - 1;
+}
+
+
+
+
+static void 
+DumpChunk (void)
+{
+  chunk_data[chunks_read - 1].disk_pos = Disk_pos << 3;
+  fseek (chunks, Disk_pos, 0);
+  fwrite (MemoryBuffer, sizeof (char), BufToUse, chunks);
+  Disk_pos += BufToUse;
+}
+
+
+
+
+static void 
+DiskMerge (void)
+{
+  random_bitio_state *rbsi;
+  random_bitio_state *chks = NULL;
+  unsigned long *chunk_ptrs;
+  int i;
+
+  BIO_Random_Flush (&crbs);
+
+  chunk_ptrs = Xmalloc (chunks_read * sizeof (unsigned long));
+  ChangeMemInUse (chunks_read * sizeof (unsigned long));
+  bzero ((char *) chunk_ptrs, chunks_read * sizeof (unsigned long));
+
+  rbsi = Xmalloc (chunks_read * sizeof (random_bitio_state));
+  ChangeMemInUse (chunks_read * sizeof (random_bitio_state));
+  for (i = 0; i < chunks_read; i++)
+    {
+      rbsi[i] = crbs;
+      rbsi[i].Buf = Xmalloc (rbsi[i].len);
+      ChangeMemInUse (rbsi[i].len);
+      bcopy ((char *) (crbs.Buf), (char *) (rbsi[i].Buf), rbsi[i].len);
+      BIO_Random_Seek (chunk_data[i].params_pos, &rbsi[i]);
+    }
+
+  if (chunks_read > 1)
+    {
+      int j;
+      chks = Xmalloc ((chunks_read - 1) * sizeof (random_bitio_state));
+      ChangeMemInUse ((chunks_read - 1) * sizeof (random_bitio_state));
+      BIO_Random_Start (chunks, RND_BUF_SIZE, &chks[0]);
+      ChangeMemInUse (RND_BUF_SIZE);
+      for (j = 1; j < chunks_read - 1; j++)
+	{
+	  chks[j] = chks[0];
+	  chks[j].Buf = Xmalloc (chks[0].len);
+	  ChangeMemInUse (chks[0].len);
+	  bcopy ((char *) (chks[0].Buf), (char *) (chks[j].Buf), chks[0].len);
+	}
+    }
+  for (i = 0; i < dict_size; i++)
+    {
+      int j;
+      invf_state_rec *isr = in_cache (i);
+      register int B;
+
+      BIO_Random_Seek_X (isr->Disk_Ptr, &rbs);	/* Position in invf file */
+
+      B = isr->Disk_B;
+
+      for (j = 0; j < chunks_read; j++)
+	{
+	  int p;
+	  p = BIO_Random_Gamma_Decode (&rbsi[j], NULL) - 1;
+
+	  if (p)
+	    {
+	      int ptr, b;
+	      chunk_ptrs[j] += BIO_Random_Delta_Decode (&rbsi[j], NULL) - 1;
+	      ptr = chunk_ptrs[j];
+	      b = 1 << floorlog_2 (BIO_Bblock_Init_W (chunk_data[j].N, p));
+
+	      if (j == chunks_read - 1)
+		{
+		  int k, CurrDoc;
+		  DECODE_START ((u_char *) MemoryBuffer, ptr)
+		    CurrDoc = isr->Disk_Last;
+		  for (k = 0; k < p; k++)
+		    {
+		      register unsigned long x, tf;
+		      BBLOCK_DECODE (x, b);
+		      if (k == 0)
+			x = x + chunk_data[j].start_doc - isr->Disk_Last;
+		      CurrDoc += x;
+		      BIO_Random_Bblock_Encode (x, B, &rbs, NULL);
+		      if (InvfLevel >= 2)
+			{
+			  UNARY_DECODE (tf);
+			  BIO_Random_Gamma_Encode (tf, &rbs, NULL);
+			}
+		    }
+		  DECODE_DONE
+		    isr->Disk_Last = CurrDoc;
+		}
+	      else
+		{
+		  int k, CurrDoc;
+		  random_bitio_state *Chks = chks + j;
+		  BIO_Random_Seek (chunk_data[j].disk_pos + ptr, Chks);
+		  CurrDoc = isr->Disk_Last;
+		  for (k = 0; k < p; k++)
+		    {
+		      register unsigned long x, tf;
+		      x = BIO_Random_Bblock_Decode (b, Chks, NULL);
+		      if (k == 0)
+			x = x + chunk_data[j].start_doc - isr->Disk_Last;
+		      CurrDoc += x;
+		      BIO_Random_Bblock_Encode (x, B, &rbs, NULL);
+		      if (InvfLevel >= 2)
+			{
+			  tf = BIO_Random_Unary_Decode (Chks, NULL);
+			  BIO_Random_Gamma_Encode (tf, &rbs, NULL);
+			}
+		    }
+		  isr->Disk_Last = CurrDoc;
+		}
+	    }
+	}
+
+      isr->Disk_Ptr = BIO_Random_Tell_X (&rbs);
+
+    }
+  if (chunks_read > 1)
+    {
+      int j;
+      for (j = 0; j < chunks_read - 1; j++)
+	{
+	  Xfree (chks[j].Buf);
+	  ChangeMemInUse (-chks[j].len);
+	}
+      Xfree (chks);
+      ChangeMemInUse (-(chunks_read - 1) * sizeof (random_bitio_state));
+    }
+
+  for (i = 0; i < chunks_read; i++)
+    {
+      Xfree (rbsi[i].Buf);
+      ChangeMemInUse (-rbsi[i].len);
+    }
+  Xfree (rbsi);
+  ChangeMemInUse (-chunks_read * sizeof (random_bitio_state));
+/*   chunks_read = 0; */
+  Xfree (chunk_ptrs);
+  ChangeMemInUse (-chunks_read * sizeof (unsigned long));
+  chunks_read = 0;
+  Disk_pos = 0;
+  BIO_Random_Seek (0, &crbs);
+}
+
+static void 
+MergeIn (void)
+{
+  static int disk_chunks = 0;
+  static header = 0;
+  if (!header)
+    {
+      fprintf (stderr, "ivf.pass2 : ");
+      header = 1;
+    }
+  if (disk_chunks == ChunkLimit || next_docs_left == 0)
+    {
+      fprintf (stderr, "M");
+      DiskMerge ();
+      disk_chunks = 0;
+    }
+  else
+    {
+      fprintf (stderr, "-");
+      DumpChunk ();
+      disk_chunks++;
+    }
+  if (next_docs_left == 0)
+    fprintf (stderr, "\n");
+}
+
+
+static int 
+wl_comp (const void *a, const void *b)
+{
+  return *((int *) a) - *((int *) b);
+}
+
+static int 
+process_doc (u_char * s_in, int l_in)
+{
+  int res;
+  u_char *end = s_in + l_in - 1;
+  unsigned long tocode;
+  unsigned long wl_pos = 0;
+
+  if (!docs_left)
+    LoadCounts ();
+
+  callnum++;
+
+  if (!inaword (s_in, end))
+    if (SkipSGML)
+      PARSE_NON_STEM_WORD_OR_SGML_TAG (s_in, end);
+    else
+      PARSE_NON_STEM_WORD (s_in, end);
+
+  while (s_in <= end)
+    {
+      u_char Word[MAXSTEMLEN + 1];
+
+      PARSE_STEM_WORD (Word, s_in, end);
+      stemmer (idh.stem_method, idh.stemmer_num, Word);
+      if (SkipSGML)
+	PARSE_NON_STEM_WORD_OR_SGML_TAG (s_in, end);
+      else
+	PARSE_NON_STEM_WORD (s_in, end);
+
+      if (*Word == 0)
+	continue;
+
+      res = perf_hash (phd, Word);
+
+      {
+	word_rec *arr = &WordRecs[res];
+	int b = 1 << lg_bs[res];
+	wordnum++;
+
+	tocode = callnum;
+
+	ENCODE_START ((u_char *) MemoryBuffer, arr->ptr)
+
+	  if (tocode > arr->last)
+	  {
+	    register int x;
+	    x = tocode - arr->last - 1;
+	    BBLOCK_ENCODE (x + 1, b);
+	    if (InvfLevel >= 2)
+	      ENCODE_BIT (1);
+	    no_of_ptrs++;
+	    arr->last = tocode;
+	  }
+	else if (InvfLevel >= 2)
+	  {
+	    __pos--;
+	    ENCODE_BIT (0);
+	    ENCODE_BIT (1);
+	  }
+	arr->ptr = __pos;
+	ENCODE_DONE
+      }
+
+      if (MakeWeights)
+	{
+	  if (wl_pos >= wl_size)
+	    {
+	      wl_size += (wl_size >> 1);
+	      word_list = Xrealloc (word_list, sizeof (*word_list) * wl_size);
+	    }
+	  word_list[wl_pos++] = res;
+	}
+    }
+  if (MakeWeights)
+    {
+      float doc_weight = 0.0;
+      if (wl_pos)
+	{
+	  unsigned long *wl = word_list;
+	  unsigned long i, count, val;
+	  qsort (wl, wl_pos, sizeof (*wl), wl_comp);
+	  count = 1;
+	  val = *wl++;
+	  for (i = 1; i <= wl_pos; i++, wl++)
+	    if (i == wl_pos || val != *wl)
+	      {
+		double weight = count * idf[val];
+		doc_weight += weight * weight;
+		count = 1;
+		val = *wl;
+	      }
+	    else
+	      count++;
+	}
+      HTONF(doc_weight);  /* [RPAP - Jan 97: Endian Ordering] */
+      fwrite ((char *) &doc_weight, sizeof (doc_weight), 1, weights);
+    }
+  docs_left--;
+  if (!docs_left)
+    MergeIn ();
+
+  return COMPALLOK;
+}
+
+int 
+process_ivf_2 (u_char * s_in, int l_in)
+{
+  if (InvfLevel <= 2)
+    return process_doc (s_in, l_in);
+  else
+    {
+      int count = 0;
+      int pos = 0;
+      u_char *start = s_in;
+      while (pos < l_in)
+	{
+	  if (s_in[pos] == TERMPARAGRAPH)
+	    {
+	      int len = pos + s_in + 1 - start;
+	      if (process_doc (start, len) != COMPALLOK)
+		return (COMPERROR);
+	      start = s_in + pos + 1;
+	      count++;
+	    }
+	  pos++;
+	}
+      if (start < s_in + pos)
+	{
+	  if (process_doc (start, pos + s_in - start) != COMPALLOK)
+	    return (COMPERROR);
+	  count++;
+	}
+      HTONSI(count);  /* [RPAP - Jan 97: Endian Ordering] */
+      fwrite ((char *) &count, sizeof (count), 1, invf_para);
+    }
+  return COMPALLOK;
+}
+
+
+
+
+
+static void 
+stats (unsigned long len)
+{
+#ifndef SILENT
+  fseek (count, 0, 2);
+  fseek (count_trans, 0, 2);
+  fseek (invf_state, 0, 2);
+  fseek (invf, 0, 0);
+  fseek (invf, 0, 2);
+  fseek (chunks, 0, 2);
+  fseek (chunk_state, 0, 2);
+  Message ("File sizes\n");
+  Message ("  Chunk desc    : %10u bytes\n", ftell (count));
+  Message ("  Chunk trans   : %10u bytes\n", ftell (count_trans));
+  Message ("  Chunks        : %10u bytes\n", ftell (chunks));
+  Message ("  Chunk state   : %10u bytes\n", ftell (chunk_state));
+  Message ("  Invf state    : %10u bytes\n", ftell (invf_state));
+  Message ("  Peak invf     : %10u bytes\n", len);
+  Message ("  Final invf    : %10u bytes\n", ftell (invf));
+  Message ("Peak disk usage : %10.2f %%\n",
+	   (double) (ftell (count) + ftell (count_trans) +
+		     ftell (invf_state) + ftell (chunks) +
+		     ftell (chunk_state) + len) / ftell (invf) * 100.0);
+#endif
+}
+
+
+/* ARGSUSED */
+int 
+done_ivf_2 (char *FileName)
+{
+  long i;
+  mg_ullong totalIbits;
+  unsigned long invf_len;
+  unsigned long bytes_output;
+  struct invf_file_header ifh;
+
+  if (weights)
+    fclose (weights);
+  if (invf_para)
+    fclose (invf_para);
+
+  free_perf_hash (phd);
+  phd = NULL;
+
+  Xfree (MemoryBuffer);
+  MemoryBuffer = NULL;
+  ChangeMemInUse (-MemBufSize);
+
+  BIO_Random_Done (&rbs);
+  BIO_Random_Done (&rbsp);
+  fflush (invf);
+
+  fseek (invf, 0, 2);
+  invf_len = ftell (invf);
+
+  fseek (invf_out, sizeof (long), 0);
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL2(dict_size, ifh.no_of_words);
+  HTONUL2(no_of_ptrs, ifh.no_of_ptrs);
+  ifh.skip_mode = 0;
+  bzero ((char *) ifh.params, sizeof (ifh.params));
+  HTONUL2(InvfLevel, ifh.InvfLevel);
+  fwrite ((char *) &ifh, sizeof (ifh), 1, invf_out);
+
+  bytes_output = ftell (invf_out);
+
+  totalIbits = sizeof (unsigned long) * 8;		/* The magic number */
+  totalIbits += 8 * 200;	/* A 200 byte gap */
+
+  /* find the right place in the file to start reading p values */
+  fseek (dict, sizeof (unsigned long) + sizeof (struct invf_dict_header), 0);
+  for (i = 0; i < dict_size; i++)
+    {
+      invf_state_rec *isr;
+      unsigned long fcnt, wcnt, s, e;
+      register unsigned long p;
+      u_char dummy1, dummy2[MAXSTEMLEN + 1];
+
+      /* output location to the invf_idx  */
+      HTONUL(bytes_output);  /* [RPAP - Jan 97: Endian Ordering] */
+      fwrite ((char *) &bytes_output, sizeof (bytes_output), 1, invf_idx);
+      NTOHUL(bytes_output);  /* [RPAP - Jan 97: Endian Ordering] */
+
+      /* read an entry for a word, just to get p value */
+      dummy1 = fgetc (dict);
+      dummy1 = fgetc (dict);
+      fread (dummy2, sizeof (u_char), dummy1, dict);
+      fread ((char *) &fcnt, sizeof (fcnt), 1, dict);
+      fread ((char *) &wcnt, sizeof (wcnt), 1, dict);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(fcnt);
+      NTOHUL(wcnt);
+
+      p = fcnt;
+
+      isr = in_cache (i);
+
+      e = (isr->Disk_Ptr + 7ul) >> 3ul;
+      s = totalIbits >> 3;
+
+      fseek (invf_in, s, 0);
+      while (s < e)
+	{
+	  u_char c = getc (invf_in);
+	  if (s == e - 1)
+	    {
+	      u_char ands[8] =
+	      {0xff, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
+	      c &= ands[isr->Disk_Ptr & 7ul];
+	    }
+	  putc (c, invf_out);
+	  bytes_output++;
+	  s++;
+	}
+
+      totalIbits += BIO_Bblock_Bound_b (N, p, isr->Disk_B);
+      if (InvfLevel >= 2)
+	totalIbits += BIO_Gamma_Bound (wcnt, fcnt);
+#ifdef USE_LONG_LONG
+      totalIbits = (totalIbits + 7ull) & 0xfffffffffffffff8ull;
+#else
+      totalIbits = (totalIbits + 7ul) & 0xfffffff8ul;
+#endif
+
+    }
+
+  fclose (invf_in);
+
+  /* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+  if (!(_chsize (_fileno (invf_out), bytes_output)))
+    Message ("Could not truncate invf.");
+#else
+  ftruncate (fileno (invf_out), bytes_output);
+#endif
+
+  fclose (invf_out);
+
+  HTONUL(bytes_output);  /* [RPAP - Jan 97: Endian Ordering] */
+  fwrite ((char *) &bytes_output, sizeof (bytes_output), 1, invf_idx);
+  NTOHUL(bytes_output);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  fclose (invf_idx);
+
+#ifndef SILENT
+  {
+    char *temp_str = msg_prefix;
+    unsigned long total;
+    msg_prefix = "ivf.pass2";
+    stats (invf_len);
+    Message ("Pass two data structures      : %6.3f Mbyte\n",
+	     (double) totalDbytes / 1024 / 1024);
+    total = totalDbytes;
+    Message ("Pass two hash structure(s)    : %6.3f Mbyte\n",
+	     (double) totalHbytes / 1024 / 1024);
+    total += totalHbytes;
+    Message ("Peak extra memory in use      : %6.3f Mbyte\n",
+	     (double) MaxMemInUse / 1024 / 1024);
+    total += MaxMemInUse;
+    Message ("Peak total memory in use      : %6.3f Mbyte\n",
+	     (double) total / 1024 / 1024);
+    msg_prefix = temp_str;
+  }
+#endif
+
+  Xfree(chunk_data);
+  chunk_data = NULL;
+  Xfree (WordRecs);
+  WordRecs = NULL;
+  Xfree (lg_bs);
+  lg_bs = NULL;
+  Xfree (idf);
+  idf = NULL;
+  Xfree (word_list);
+  word_list = NULL;
+  /* Free the memory allocated for the BIO_Random */
+  occur_to_lexical (-1,1);
+
+  BIO_Random_Done (&crbs);
+
+  fclose (invf);
+  fclose (dict);
+  fclose (hash);
+  fclose (count);
+  fclose (count_trans);
+  fclose (chunk_state);
+  fclose (chunks);
+  fclose (invf_state);
+  return (COMPALLOK);
+}
Index: /indexers/branches/3.03a/mg/src/text/lists.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/lists.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/lists.c	(revision 14757)
@@ -0,0 +1,217 @@
+/**************************************************************************
+ *
+ * lists.c -- List processing functions for boolean queries
+ * Copyright (C) 1994  Neil Sharman, Alistair Moffat and Lachlan Andrew
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+
+#include "lists.h"
+#include "local_strings.h"
+#include "locallib.h"
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:01  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1999/07/01 09:30:48  rjmcnab
+   Changes for better match reporting.
+
+   Revision 1.1  1998/11/17 09:34:47  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:56:50  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:37  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+
+
+
+
+/*
+ * Make a DocList large enough to hold num entries 
+ */
+DocList *
+MakeDocList (int num)
+{
+  DocList *d;
+  if (!(d = Xmalloc (sizeof (DocList) + sizeof (DocEntry) * (num - 1))))
+    return (NULL);
+  d->num = 0;
+  d->total_retrieved = 0;
+  d->is_approx = 0;
+  return (d);
+}
+
+
+/*
+ * Change the size of a DocList so that it can hold num entries 
+ */
+DocList *
+ResizeDocList (DocList * d, int num)
+{
+  if (!(d = Xrealloc (d, sizeof (DocList) + sizeof (DocEntry) * (num - 1))))
+    return (NULL);
+  return (d);
+}
+
+
+/* IntersectLists () */
+/* Returns the intersection of List1 and List2 by deleting from List1 all */
+/* entries not in List2.  All of List2 is freed, and the nodes of List1 not */
+/* included in the resultant list are freed. */
+/* On exit the intersection of the lists is returned, or NULL on empty */
+/* intersection. */
+/* Assumes that both lists are ordered on increasing Value. */
+DocList *
+IntersectLists (DocList * List1, DocList * List2)
+{
+  DocEntry *s1, *d1, *s2;
+  if (!List2 || !List1)
+    {
+      if (List1)
+	Xfree (List1);
+      if (List2)
+	Xfree (List2);
+      return (MakeDocList (0));
+    }
+  d1 = s1 = List1->DE;
+  s2 = List2->DE;
+  while (s1 - List1->DE < List1->num && s2 - List2->DE < List2->num)
+    {
+      if (s1->DocNum == s2->DocNum)
+	*d1++ = *s1++;
+      if (s1 - List1->DE < List1->num)
+	while (s2 - List2->DE < List2->num && s2->DocNum < s1->DocNum)
+	  s2++;
+      if (s2 - List2->DE < List2->num)
+	while (s1 - List1->DE < List1->num && s1->DocNum < s2->DocNum)
+	  s1++;
+    }
+  List1->num = d1 - List1->DE;
+  Xfree (List2);
+  return (List1);
+}
+
+
+/* DiffLists () */
+/* Returns the difference of List1 and List2 by deleting from List1 all */
+/* entries in List2.  All of List2 is freed, and the nodes of List1 not */
+/* included in the resultant list are freed. */
+/* On exit the differrence of the lists is returned, or NULL on empty */
+/* intersection. */
+/* Assumes that both lists are ordered on increasing Value. */
+DocList *
+DiffLists (DocList * List1, DocList * List2)
+{
+  DocEntry *s1, *d1, *s2;
+  if (!List1)
+    {
+      if (List2)
+	Xfree (List2);
+      return (MakeDocList (0));
+    }
+  if (!List2)
+    return (List1);
+  d1 = s1 = List1->DE;
+  s2 = List2->DE;
+  while (s1 - List1->DE < List1->num)
+    {
+      if (s2 - List2->DE == List2->num)
+	*d1++ = *s1++;
+      else
+	{
+	  if (s1->DocNum == s2->DocNum)
+	    {
+	      s1++;
+	      s2++;
+	    }
+	  else if (s1->DocNum < s2->DocNum)
+	    *d1++ = *s1++;
+	  else
+	    s2++;
+	}
+    }
+  List1->num = d1 - List1->DE;
+  Xfree (List2);
+  return (List1);
+}
+
+/* MergeLists () */
+/* Finds the union of two lists and returns the head of the new list formed. */
+/* Assumes that both lists are ordered on increasing Value. */
+DocList *
+MergeLists (DocList * List1, DocList * List2)
+{
+  DocList *NewList;
+  DocEntry *d, *s1, *s2;
+  if (!List1)
+    {
+      if (List2)
+	return (List2);
+      else
+	return (MakeDocList (0));
+    }
+  if (!List2)
+    return (List1);
+  if (!(NewList = MakeDocList (List1->num + List2->num)))
+    {
+      Xfree (List1);
+      Xfree (List2);
+      return (NULL);
+    }
+
+  s1 = List1->DE;
+  s2 = List2->DE;
+  d = NewList->DE;
+  while (s1 - List1->DE < List1->num || s2 - List2->DE < List2->num)
+    {
+      if (s1 - List1->DE >= List1->num)
+	*d++ = *s2++;
+      else if (s2 - List2->DE >= List2->num)
+	*d++ = *s1++;
+      else if (s1->DocNum == s2->DocNum)
+	{
+	  *d = *s1++;
+	  (d++)->Weight += (s2++)->Weight;
+	}
+      else if (s1->DocNum < s2->DocNum)
+	*d++ = *s1++;
+      else
+	*d++ = *s2++;
+    }
+  NewList->num = d - NewList->DE;
+  Xfree (List1);
+  Xfree (List2);
+  return (NewList);
+}
Index: /indexers/branches/3.03a/mg/src/text/lists.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/lists.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/lists.h	(revision 14757)
@@ -0,0 +1,59 @@
+/**************************************************************************
+ *
+ * lists.h -- List processing functions for boolean queries
+ * Copyright (C) 1994  Neil Sharman, Alistair Moffat and Lachlan Andrew
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#ifndef H_LISTS
+#define H_LISTS
+
+
+
+typedef struct DocEntry
+  {
+    float Weight;
+    int DocNum;
+    unsigned long SeekPos;	/* position in the text file in bytes */
+    unsigned long Len;		/* length of the document in bytes */
+    char *CompTextBuffer;
+    struct DocEntry *Next;
+    short or_included;		/*[TS:Mar/95] whether included in an AND of ORed-terms */
+  }
+DocEntry;
+
+typedef struct DocList
+  {
+    int num;
+    int total_retrieved; /* valid if > 0 */
+    int is_approx;       /* whether total_retrieved is approximate */
+    DocEntry DE[1];
+  }
+DocList;
+
+DocList *MakeDocList (int num);
+DocList *ResizeDocList (DocList * d, int num);
+DocList *IntersectLists (DocList * List1, DocList * List2);
+DocList *DiffLists (DocList * List1, DocList * List2);
+DocList *MergeLists (DocList * List1, DocList * List2);
+
+
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/locallib.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/locallib.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/locallib.c	(revision 14757)
@@ -0,0 +1,307 @@
+/**************************************************************************
+ *
+ * locallib.c -- Misc functions
+ * Copyright (C) 1994  Gary Eddy, Alistair Moffat and Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "bitio_gen.h"
+#include "huffman.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "locallib.h"
+#include "text.h"
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:02  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:34:49  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:56:51  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:38  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+
+int 
+vecentropy (int *A, int n)
+{
+  int total = 0, i;
+  double bits = 0.0;
+
+  for (i = 0; i < n; i++)
+    total += A[i];
+  for (i = 0; i < n; i++)
+    if (A[i])
+      bits += A[i] * log2 (1.0 * total / A[i]);
+  return ((int) (bits + 0.9999));
+
+}
+
+static void 
+siftdown (int *A, int i, int n)
+{
+  int ms, t;
+
+  while (2 * i + 1 <= n - 1)
+    {
+      if (2 * i + 1 == n - 1 || A[2 * i + 1] < A[2 * i + 2])
+	ms = 2 * i + 1;
+      else
+	ms = 2 * i + 2;
+      if (A[i] > A[ms])
+	{
+	  t = A[i];
+	  A[i] = A[ms];
+	  A[ms] = t;
+	}
+      i = ms;
+    }
+}
+
+static void 
+buildheap (int *A, int n)
+{
+  int i;
+  for (i = n / 2 - 1; i >= 0; i--)
+    siftdown (A, i, n);
+}
+
+int 
+huffcodebits (unsigned long *A, int n)
+{
+  int i, j, tot = 0, bits = 0, v1, v2, *B;
+
+  B = (int *) Xmalloc (n * sizeof (int));
+  j = 0;
+  for (i = 0; i < n; i++)
+    {
+      if (A[i])
+	{
+	  tot += (B[j++] = A[i]);
+	}
+    }
+  n = j;
+
+  if (n == 0 || tot == 0)
+    return (0);
+
+  buildheap (B, n);
+  while (n > 1)
+    {
+      v1 = B[0];
+      B[0] = B[n - 1];
+      n--;
+      siftdown (B, 0, n);
+      v2 = B[0];
+      B[0] = v1 + v2;
+      siftdown (B, 0, n);
+      bits += v1 + v2;
+    }
+  Xfree (B);
+  return (bits);
+}
+
+
+int 
+modelbits (unsigned long *A, int n)
+{
+  int i, bits = 0, last, N = 0;
+
+  last = -1;
+  for (i = 0; i < n; i++)
+    {
+      if (A[i])
+	{
+	  bits += BIO_Gamma_Length (i - last) + BIO_Gamma_Length (A[i]);
+	  last = i;
+	  N++;
+	}
+    }
+  if (N == 0)
+    return (0);
+  bits += BIO_Gamma_Length (N);
+  return (bits);
+}
+
+
+
+
+
+/* Find the next prime number larger than p */
+int 
+prime (int p)
+{
+  int limit;
+  p += (p & 1) + 1;
+  limit = (int) sqrt ((double) p) + 1;
+  do
+    {
+      int j;
+      while (limit * limit < p)
+	limit++;
+      for (j = 3; j <= limit && p % j; j += 2)
+	;			/* NULLBODY */
+      if (j > limit)
+	break;
+      p += 2;
+    }
+  while (1);
+  return (p);
+}
+
+
+
+int 
+Read_cdh (FILE * f, compression_dict_header * cdh, u_long * mem,
+	  u_long * disk)
+{
+  if (disk)
+    (*disk) += sizeof (*cdh);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  if (fread (cdh, sizeof (*cdh), 1, f) == 1)
+    {
+      int i;
+      NTOHUL(cdh->dict_type);
+      NTOHUL(cdh->novel_method);
+      for (i = 0; i < TEXT_PARAMS; i++)
+	NTOHUL(cdh->params[i]);
+      NTOHUL(cdh->num_words[0]);
+      NTOHUL(cdh->num_words[1]);
+      NTOHUL(cdh->num_word_chars[0]);
+      NTOHUL(cdh->num_word_chars[1]);
+      NTOHUL(cdh->lookback);
+      return 0;
+    }
+  else
+    return -1;
+}
+
+
+int 
+F_Read_cdh (File * f, compression_dict_header * cdh, u_long * mem,
+	    u_long * disk)
+{
+  if (disk)
+    (*disk) += sizeof (*cdh);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  if (Fread (cdh, sizeof (*cdh), 1, f) == 1)
+    {
+      int i;
+      NTOHUL(cdh->dict_type);
+      NTOHUL(cdh->novel_method);
+      for (i = 0; i < TEXT_PARAMS; i++)
+	NTOHUL(cdh->params[i]);
+      NTOHUL(cdh->num_words[0]);
+      NTOHUL(cdh->num_words[1]);
+      NTOHUL(cdh->num_word_chars[0]);
+      NTOHUL(cdh->num_word_chars[1]);
+      NTOHUL(cdh->lookback);
+      return 0;
+    }
+  else
+    return -1;
+}
+
+
+int 
+Read_cfh (FILE * f, comp_frags_header * cfh, u_long * mem, u_long * disk)
+{
+  int i;  /* [RPAP - Jan 97: Endian Ordering] */
+
+  if (Read_Huffman_Data (f, &cfh->hd, mem, disk) == -1)
+    return -1;
+  if (fread (&cfh->uncompressed_size,
+	     sizeof (cfh->uncompressed_size), 1, f) != 1)
+    return -1;
+  NTOHUL(cfh->uncompressed_size);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  if (disk)
+    (*disk) += sizeof (cfh->uncompressed_size);
+
+  bzero ((char *) cfh->huff_words_size, sizeof (cfh->huff_words_size));
+
+  if (fread (cfh->huff_words_size + cfh->hd.mincodelen,
+	     sizeof (*cfh->huff_words_size),
+	     cfh->hd.maxcodelen - cfh->hd.mincodelen + 1, f) !=
+      cfh->hd.maxcodelen - cfh->hd.mincodelen + 1)
+    return -1;
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = cfh->hd.mincodelen; i < cfh->hd.maxcodelen + 1; i++)
+    NTOHUL(cfh->huff_words_size[i]);
+
+  if (disk)
+    (*disk) += sizeof (*cfh->huff_words_size) *
+      (cfh->hd.maxcodelen - cfh->hd.mincodelen + 1);
+  return 0;
+}
+
+
+
+int 
+F_Read_cfh (File * f, comp_frags_header * cfh, u_long * mem, u_long * disk)
+{
+  int i;  /* [RPAP - Jan 97: Endian Ordering] */
+
+  if (F_Read_Huffman_Data (f, &cfh->hd, mem, disk) == -1)
+    return -1;
+  if (Fread (&cfh->uncompressed_size,
+	     sizeof (cfh->uncompressed_size), 1, f) != 1)
+    return -1;
+  NTOHUL(cfh->uncompressed_size);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  if (disk)
+    (*disk) += sizeof (cfh->uncompressed_size);
+
+  bzero ((char *) cfh->huff_words_size, sizeof (cfh->huff_words_size));
+
+  if (Fread (cfh->huff_words_size + cfh->hd.mincodelen,
+	     sizeof (*cfh->huff_words_size),
+	     cfh->hd.maxcodelen - cfh->hd.mincodelen + 1, f) !=
+      cfh->hd.maxcodelen - cfh->hd.mincodelen + 1)
+    return -1;
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = cfh->hd.mincodelen; i < cfh->hd.maxcodelen + 1; i++)
+    NTOHUL(cfh->huff_words_size[i]);
+
+  if (disk)
+    (*disk) += sizeof (*cfh->huff_words_size) *
+      (cfh->hd.maxcodelen - cfh->hd.mincodelen + 1);
+
+  return 0;
+}
Index: /indexers/branches/3.03a/mg/src/text/locallib.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/locallib.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/locallib.h	(revision 14757)
@@ -0,0 +1,52 @@
+/**************************************************************************
+ *
+ * locallib.h -- Misc functions
+ * Copyright (C) 1994  Gary Eddy, Alistair Moffat and Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef LOCALLIB_H
+#define LOCALLIB_H
+
+#include "sysfuncs.h"
+
+#include "text.h"
+
+#define NUMOF(a) (sizeof(a)/sizeof((a)[0]))
+
+int vecentropy (int *A, int n);
+
+int huffcodebits (unsigned long *A, int n);
+
+int modelbits (unsigned long *A, int n);
+
+int prime (int p);
+
+
+int Read_cdh (FILE * f, compression_dict_header * cdh, u_long * mem, u_long * disk);
+
+int Read_cfh (FILE * f, comp_frags_header * cfh, u_long * mem, u_long * disk);
+
+int F_Read_cdh (File * f, compression_dict_header * cdh, u_long * mem,
+		u_long * disk);
+
+int F_Read_cfh (File * f, comp_frags_header * cfh, u_long * mem, u_long * disk);
+
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/mg.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg.h	(revision 14757)
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * mg.h -- General header file
+ * Copyright (C) 1994  Neil Sharman, Alistair Moffat and Lachlan Andrew
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#ifndef H_MG
+#define H_MG
+
+
+#define COMPALLOK	(0)
+#define COMPERROR	(-1)
+
+#define MAXSTRING       3000000
+#define BUFFERSIZE      (MAXSTRING+30000)
+
+
+
+
+#define	MAXLN	65536
+#define WORDS           1
+#define NONWORDS        0
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/mg.special.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg.special.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg.special.c	(revision 14757)
@@ -0,0 +1,118 @@
+/**************************************************************************
+ *
+ * mg.special.c -- Special pass for mg_passes
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "mg.h"
+#include "build.h"
+
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:03  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:34:51  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:56:53  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:44  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+
+FILE *fp;
+
+
+int 
+init_special (char *FileName)
+{
+  char FName[200];
+  sprintf (FName, "%s%s", FileName, ".docnums");
+  if (!(fp = fopen (FName, "w")))
+    return (COMPERROR);
+  return (COMPALLOK);
+}
+
+
+
+
+int 
+process_special (u_char * s_in, int l_in)
+{
+  static int un = 1;
+  char *s_done = (char *) (s_in + l_in);
+  for (; (char *) s_in != s_done; s_in++)
+    if (*s_in == '<')
+      {
+	if (strncmp ((char *) s_in, "<DOCNO>", 7) == 0)
+	  {
+	    char *s_end = (char *) (s_in + 1);
+	    for (; s_end != s_done; s_end++)
+	      if (*s_end == '<')
+		if (strncmp (s_end, "</DOCNO>", 8) == 0)
+		  break;
+	    if (s_end == s_done)
+	      {
+		fprintf (fp, "NO DOC ID %d\n", un++);
+		return COMPALLOK;
+	      }
+	    s_in += 7;
+	    while (s_end != (char *) s_in &&
+		   (*(s_end - 1) == ' ' || *(s_end - 1) == '\n'))
+	      s_end--;
+	    while ((char *) s_in != s_end &&
+		   (*s_in == ' ' || *s_in == '\n'))
+	      s_in++;
+	    for (; (char *) s_in != s_end; s_in++)
+	      putc (*s_in, fp);
+	    putc ('\n', fp);
+	    return (COMPALLOK);
+	  }
+      }
+  fprintf (fp, "NO DOC ID %d\n", un++);
+  return (COMPALLOK);
+}
+
+
+
+
+
+
+
+
+int 
+done_special (char *FileName)
+{
+  fclose (fp);
+  return COMPALLOK;
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_compression_dict.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_compression_dict.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_compression_dict.1	(revision 14757)
@@ -0,0 +1,219 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_compression_dict 1 \*(Dt CITRI
+.SH NAME
+mg_compression_dict \- build a compression dictionary.
+.SH SYNOPSIS
+.B mg_compression_dict
+[
+.B \-h
+]
+[
+.BR \-C " |"
+.BR \-P " |"
+.B  \-S
+]
+.if n .ti +9n
+[
+.BR \-0 " |"
+.BR \-1 " |"
+.BR \-2 " |"
+.B  \-3
+]
+[
+.BR \-H " |"
+.BR \-B " |"
+.BR \-D " |"
+.BR \-Y " |"
+.B  \-M
+]
+.if n .ti +9n
+.if t .ti +.5i
+[
+.BI \-l " lookback"
+]
+[
+.BI \-k " mem"
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_compression_dict
+builds a compression dictionary based on the statistics gathered
+during the first pass over the text.  The options to the program are
+mainly concerned with limiting the amount of memory the dictionary
+will use and with how the text compressor will cope with any novel
+words found during the compression phase.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-C
+Build a complete dictionary from the statistics file.  If during the
+text compression phase a novel word is found, then the compressor will
+produce an error message and stop.
+.TP
+.B \-P
+Build a partial dictionary from the statistics file.  This dictionary
+assumes that the statistics file are based on the entire text.  The
+statistics of words not includes in the dictionary are used to
+calculate the escape probability.  If novel words are being coded
+character by character, then there may not be a Huffman code for every
+possible character.  This means that the compressor may fail if a novel
+word contains a novel character.
+.TP
+.B \-S
+Build a seed dictionary from the statistics file.  This dictionary
+assumes that the statistics file is based on only a portion of the
+text to be compressed.  The probability of a novel word is based on the
+number of words that have only occurred once.  If novel words are being
+coded character by character, then the Huffman codes for characters are
+based on the frequency of characters in the dictionary.
+.TP
+.B \-0
+All words from the statistics file are included in the built
+dictionary.
+.TP
+.B \-1
+Words are included in the dictionary until the dictionary reaches the
+desired size.  Words are selected for the dictionary based on the order
+they occurred in the source text.
+.TP
+.B \-2
+Words are included in the dictionary until the dictionary reaches the
+desired size.  The most frequent words are included in the dictionary
+first; where there is a tie for frequency, the shortest word is
+included first.
+.TP
+.B \-3
+Words are included in the dictionary until the dictionary reaches the
+desired size.  The most frequent words are included in the dictionary
+first; where there is a tie for frequency, the shortest word is
+included first.  Words are the shuffled back and forth between the
+`keep' and `discard' lists to find the `optimal' set of words that
+should be in the dictionary.
+.TP
+.B \-H
+This specifies that novel words will be coded character by character
+using Huffman codes.
+.TP
+.B \-B
+This specifies that an auxiliary dictionary will be built by the
+compressor.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using binary codes.  The binary code represents their occurrence
+position in the auxiliary dictionary.
+.TP
+.B \-D
+This specifies that an auxiliary dictionary will be built by the
+compressor.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using delta codes.  The delta code represents their occurrence position
+in the auxiliary dictionary.
+.TP
+.B \-Y
+This specifies that an auxiliary dictionary will be built by the
+compressor.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using a combination of gamma and binary codes.  The code represents
+their occurrence position in the auxiliary dictionary.  This generally
+produces better compression than
+.B \-B
+or
+.BR \-D .
+.TP
+.B \-M
+This specifies that an auxiliary dictionary will be built by the
+compressor.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using a combination of gamma and binary codes.  The code represents
+their occurrence position in the auxiliary dictionary.  This method is
+adaptive within documents, and generally produces better compression
+than
+.BR \-B ,
+.B \-D
+or
+.BR \-Y .
+.TP
+.BI \-l " lookback"
+The generated dictionary is designed to be front coded when it is
+loaded into memory.  Under normal circumstances, a front-coded
+dictionary would require scanning from the beginning in order to find
+any particular word.  However, every
+.I lookback
+words in the dictionary, the whole word is stored and a pointer to that
+word maintained.  E.g., if
+.I lookback
+is 4, then every fourth word is stored in its entirety.
+.TP
+.BI \-k " mem"
+This limits the amount of memory to use for the generated
+dictionary.  Words are selected for the dictionary based of the text
+statistics, and whether
+.BR \-0 , " \-1" , " \-2"
+or
+.B \-3
+is specified.  The memory is calculated assuming a lookback of 0,
+irrespective of what actual lookback is specified.  This means that if
+a non-zero lookback is given, the dictionary will actually occupy
+less space than specified by
+.BR \-k .
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.text.stats
+Statistics about the source text.
+.TP
+.B *.text.dict
+Compression dictionary for the source text.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_compression_dict.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_compression_dict.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_compression_dict.c	(revision 14757)
@@ -0,0 +1,1087 @@
+/**************************************************************************
+ *
+ * mg_compression_dict.c -- Routines for reading the compression dictionary
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "messages.h"
+#include "local_strings.h"
+#include "bitio_gen.h"
+#include "bitio_m.h"
+#include "bitio_m_stdio.h"
+#include "timing.h"
+#include "mgheap.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "locallib.h"
+#include "invf.h"
+#include "text.h"
+#include "words.h"
+#include "mg.h"
+
+#define MAXBITS (sizeof(unsigned long) * 8)
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.2  1999/12/10 15:04:25  cs025
+   Incorrect use of NTOHUL on a double value (num_bytes).
+
+   Revision 1.1  1999/08/10 21:18:04  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.4  1999/01/15 03:05:51  rjmcnab
+
+   Renamed lib/heap to be lib/mgheap (it was causing some problems with
+   some versions of the STL libraries which contained a heap.h)
+
+   Revision 1.3  1998/12/17 09:12:52  rjmcnab
+
+   Altered mg to process utf-8 encoded Unicode. The main changes
+   are in the parsing of the input, the casefolding, and the stemming.
+
+   Revision 1.2  1998/11/25 07:55:44  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:34:52  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:56:54  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:45  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+/* #define DEBUG1 */
+
+/* #define DEBUG */
+
+#define is_power_of_two(a) ((a) != 0 && (((a) & ((a)-1)) == 0))
+
+#define MAX_RECALCULATIONS 100
+
+typedef struct WordData
+  {
+    u_long freq, occur_num;
+    float saving;
+    float char_bit_cost;
+    u_long num_trans;
+    u_char *word;
+  }
+WordData;
+
+static WordData *Words[2];
+static u_long Num[2];
+static u_long chars[2];
+
+#define KIND(p) (((p) >= Words[0] && (p) < Words[0] + Num[0]) ? 0 : 1)
+#define IsWord(p) (((p) >= Words[1] && (p) < Words[1] + Num[1]) ? 1 : 0)
+#define IsNonWord(p) (((p) >= Words[0] && (p) < Words[0] + Num[0]) ? 1 : 0)
+
+
+typedef struct DictData
+  {
+    WordData **wd;
+    u_long num_wds;
+    u_long chars;
+  }
+DictData;
+
+typedef DictData DictInfo[2];
+
+static DictInfo keep, discard, all;
+static compression_stats_header csh;
+
+static char *file_name = "";
+static u_long novel_method = MG_NOVEL_HUFFMAN_CHARS;
+
+
+static void ReadInWords (char *);
+static void Select_on (int k, heap_comp hc);
+static void Method3 (int k);
+static void Select_all (void);
+static u_long WriteOutWords (char *, u_long, int);
+static int DecFreqIncWL (void *a, void *b);
+static int OccuranceOrder (void *a, void *b);
+
+
+
+int main (int argc, char **argv)
+{
+  ProgTime StartTime;
+  int ch;
+  char type = 'C';
+  char mode = '0';
+  int lookback = 2;
+  double k = 0;
+  u_long mem_reqd;
+  opterr = 0;
+  msg_prefix = argv[0];
+  while ((ch = getopt (argc, argv, "0123CPSf:d:l:hk:HBDYM")) != -1)
+    switch (ch)
+      {
+      case 'H':
+	novel_method = MG_NOVEL_HUFFMAN_CHARS;
+	break;
+      case 'B':
+	novel_method = MG_NOVEL_BINARY;
+	break;
+      case 'D':
+	novel_method = MG_NOVEL_DELTA;
+	break;
+      case 'Y':
+	novel_method = MG_NOVEL_HYBRID;
+	break;
+      case 'M':
+	novel_method = MG_NOVEL_HYBRID_MTF;
+	break;
+      case 'f':		/* input file */
+	file_name = optarg;
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 'C':
+      case 'P':
+      case 'S':
+	type = ch;
+	break;
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+	mode = ch;
+	break;
+      case 'l':
+	lookback = atoi (optarg);
+	if (!is_power_of_two (lookback))
+	  FatalError (1, "The lookback value must be a power of 2");
+	lookback = floorlog_2 (lookback);
+	break;
+      case 'k':
+	k = atof (optarg) * 1024;
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-l lookback] [-f input_file]"
+	"[-d data directory] [-h] [-0|-1|-2|-3] [-C|-P|-S] [-k mem (Kb)]\n",
+		 argv[0]);
+	exit (1);
+      }
+  GetTime (&StartTime);
+
+  ReadInWords (file_name);
+
+  if (type == 'C')
+    {
+      Select_all ();
+      mem_reqd = WriteOutWords (file_name, MG_COMPLETE_DICTIONARY, lookback);
+    }
+  else
+    {
+      switch (mode)
+	{
+	case '0':
+	  Select_all ();
+	  break;
+	case '1':
+	  Message ("Dictionary limit of %.2f Kb", k / 1024);
+	  Select_on ((int) k, OccuranceOrder);
+	  break;
+	case '2':
+	  Message ("Dictionary limit of %.2f Kb", k / 1024);
+	  Select_on ((int) k, DecFreqIncWL);
+	  break;
+	case '3':
+	  Message ("Dictionary limit of %.2f Kb", k / 1024);
+	  Method3 ((int) k);
+	  break;
+	}
+      if (type == 'P')
+	{
+	  mem_reqd = WriteOutWords (file_name, MG_PARTIAL_DICTIONARY, lookback);
+	}
+      else
+	{
+	  mem_reqd = WriteOutWords (file_name, MG_SEED_DICTIONARY, lookback);
+	}
+    }
+
+  Message ("Num words           : %8u -> %8u\n", Num[1], keep[1].num_wds);
+  Message ("Num non-words       : %8u -> %8u\n", Num[0], keep[0].num_wds);
+  Message ("Chars of words      : %8u -> %8u\n", chars[1], keep[1].chars);
+  Message ("Chars of non-words  : %8u -> %8u\n", chars[0], keep[0].chars);
+  Message ("Mem usage           : %8u -> %8u\n",
+	   (Num[0] + Num[1]) * sizeof (char *) + chars[0] + chars[1],
+	     (keep[0].num_wds + keep[1].num_wds) * sizeof (char *) +
+	   keep[0].chars + keep[1].chars);
+  Message ("Actual mem required : %8u\n", mem_reqd);
+
+  Message ("%s", ElapsedTime (&StartTime, NULL));
+  return 0;
+}
+
+
+
+
+static void 
+ReadInWords (char *filename)
+{
+  FILE *f;
+  unsigned long i;
+  f = open_file (filename, TEXT_STATS_DICT_SUFFIX, "rb",
+		 MAGIC_STATS_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  fread (&csh, sizeof (csh), 1, f);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(csh.num_docs);
+  NTOHD(csh.num_bytes);
+
+  for (i = 0; i < 2; i++)
+    {
+      frags_stats_header fsh;
+      char *buf;
+      WordData *wd;
+      int j;
+      chars[i] = 0;
+
+      fread (&fsh, sizeof (fsh), 1, f);
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(fsh.num_frags);
+      NTOHUL(fsh.mem_for_frags);
+
+      Num[i] = all[i].num_wds = fsh.num_frags;
+
+      /* The +1 on the following line is to leave room for the esc code. */
+      all[i].wd = Xmalloc (sizeof (WordData *) * Num[i] + 1);
+
+      buf = Xmalloc (fsh.mem_for_frags);
+      wd = Words[i] = Xmalloc (sizeof (WordData) * Num[i]);
+      for (j = 0; j < Num[i]; j++, wd++)
+	{
+	  int len;
+	  fread (&wd->freq, sizeof (wd->freq), 1, f);
+	  NTOHUL(wd->freq);  /* [RPAP - Jan 97: Endian Ordering] */
+	  fread (&wd->occur_num, sizeof (wd->occur_num), 1, f);
+	  NTOHUL(wd->occur_num);  /* [RPAP - Jan 97: Endian Ordering] */
+	  len = fgetc (f);
+	  wd->word = (u_char *) buf;
+	  *buf++ = len;
+	  fread (buf, len, 1, f);
+	  buf += len;
+	  all[i].wd[j] = wd;
+	}
+      chars[i] = fsh.mem_for_frags - fsh.num_frags;
+    }
+  fclose (f);
+}
+
+
+static void 
+Alloc_keep_discard (void)
+{
+  keep[0].num_wds = 0;
+  keep[0].wd = Xmalloc ((Num[0] + 1) * sizeof (WordData *));
+  keep[1].num_wds = 0;
+  keep[1].wd = Xmalloc ((Num[1] + 1) * sizeof (WordData *));
+  discard[0].num_wds = 0;
+  discard[0].wd = Xmalloc ((Num[0] + 1) * sizeof (WordData *));
+  discard[1].num_wds = 0;
+  discard[1].wd = Xmalloc ((Num[1] + 1) * sizeof (WordData *));
+}
+
+
+static int 
+sort_comp (const void *a, const void *b)
+{
+  WordData *aa = *(WordData **) a;
+  WordData *bb = *(WordData **) b;
+  return casecompare (aa->word, bb->word);  /* [RPAP - Jan 97: Stem Index Change] */
+}
+
+
+
+static void 
+SortAndCount_DictData (DictData * dd)
+{
+  int i;
+  WordData **wd;
+  qsort (dd->wd, dd->num_wds, sizeof (WordData *), sort_comp);
+  dd->chars = 0;
+  wd = dd->wd;
+  for (i = 0; i < dd->num_wds; i++, wd++)
+    dd->chars += (*wd)->word[0];
+}
+
+
+static void 
+Select_all (void)
+{
+  int i;
+  Alloc_keep_discard ();
+  keep[0].num_wds = Num[0];
+  for (i = 0; i < Num[0]; i++)
+    keep[0].wd[i] = Words[0] + i;
+  keep[1].num_wds = Num[1];
+  for (i = 0; i < Num[1]; i++)
+    keep[1].wd[i] = Words[1] + i;
+  SortAndCount_DictData (&keep[0]);
+  SortAndCount_DictData (&keep[1]);
+}
+
+
+
+
+static int 
+DecFreqIncWL (void *a, void *b)
+{
+  WordData *aa = *(WordData **) a;
+  WordData *bb = *(WordData **) b;
+  if (aa->freq > bb->freq)
+    return -1;
+  else if (aa->freq < bb->freq)
+    return 1;
+  else
+    return bb->word[0] - aa->word[0];
+}
+
+
+static int 
+OccuranceOrder (void *a, void *b)
+{
+  WordData *aa = *(WordData **) a;
+  WordData *bb = *(WordData **) b;
+  if (aa->occur_num > bb->occur_num)
+    return 1;
+  else if (aa->occur_num < bb->occur_num)
+    return -1;
+  else
+    return 0;
+}
+
+
+static void 
+Select_on (int k, heap_comp hc)
+{
+  int i, num, mem;
+  WordData **wd;
+
+  Alloc_keep_discard ();
+
+  num = Num[0] + Num[1];
+  wd = Xmalloc (num * sizeof (WordData *));
+  for (i = 0; i < Num[0]; i++)
+    wd[i] = Words[0] + i;
+  for (i = 0; i < Num[1]; i++)
+    wd[i + Num[0]] = Words[1] + i;
+
+  heap_build (wd, sizeof (*wd), num, hc);
+
+  mem = 0;
+  while (k > mem && num)
+    {
+      int idx;
+      WordData *word = wd[0];
+#ifdef DEBUG
+      fprintf (stderr, "%4d:%4d:%8d :%8d :%8d : \"%s\"\n",
+	       keep[0].num_wds, keep[1].num_wds,
+	       mem, word->freq, word->occur_num, word2str (word->word));
+#endif
+      mem += sizeof (u_char *) + word->word[0];
+      heap_deletehead (wd, sizeof (*wd), &num, hc);
+      idx = KIND (word);
+      keep[idx].wd[keep[idx].num_wds++] = word;
+    }
+
+  for (i = 0; i < num; i++)
+    {
+      WordData *word = wd[i];
+      int idx = KIND (word);
+      discard[idx].wd[discard[idx].num_wds++] = word;
+    }
+  SortAndCount_DictData (&keep[0]);
+  SortAndCount_DictData (&keep[1]);
+  SortAndCount_DictData (&discard[0]);
+  SortAndCount_DictData (&discard[1]);
+
+  assert (keep[0].num_wds + discard[0].num_wds == Num[0]);
+  assert (keep[1].num_wds + discard[1].num_wds == Num[1]);
+
+}
+
+
+
+static int 
+BigSaving (void *a, void *b)
+{
+  WordData *aa = *(WordData **) a;
+  WordData *bb = *(WordData **) b;
+  return (aa->saving > bb->saving) ? -1 : (aa->saving < bb->saving);
+}
+
+static int 
+SmallSaving (void *a, void *b)
+{
+  WordData *aa = *(WordData **) a;
+  WordData *bb = *(WordData **) b;
+  return (aa->saving < bb->saving) ? -1 : (aa->saving > bb->saving);
+}
+
+
+static void 
+CalcCharCounts (WordData ** wd, int num,
+		char *char_lens[2], char *len_lens[2],
+		u_long escape[2])
+{
+  long char_freqs[2][256];
+  long len_freqs[2][16];
+  huff_data hd;
+  int i;
+  escape[0] = 0;
+  escape[1] = 0;
+  bzero ((char *) char_freqs, sizeof (char_freqs));
+  bzero ((char *) len_freqs, sizeof (len_freqs));
+  for (i = 0; i < num; i++, wd++)
+    {
+      u_long freq = (*wd)->freq;
+      u_char *buf = (*wd)->word;
+      int len = *buf++;
+      int idx = KIND (*wd);
+      len_freqs[idx][len] += freq;
+      escape[idx] += freq;
+      for (; len; len--, buf++)
+	char_freqs[idx][(u_long) (*buf)] += freq;
+    }
+  Generate_Huffman_Data (256, char_freqs[0], &hd, NULL);
+  char_lens[0] = hd.clens;
+  Generate_Huffman_Data (256, char_freqs[1], &hd, NULL);
+  char_lens[1] = hd.clens;
+
+  Generate_Huffman_Data (16, len_freqs[0], &hd, NULL);
+  len_lens[0] = hd.clens;
+  Generate_Huffman_Data (16, len_freqs[1], &hd, NULL);
+  len_lens[1] = hd.clens;
+}
+
+
+
+
+
+
+
+
+
+void 
+CalcBitCost (WordData ** discard_word, int discard_num,
+	     WordData ** keep_word, int keep_num, double freqs_trans[2],
+	     u_long escape[2], int num_trans)
+{
+  char *char_lens[2];
+  char *len_lens[2];
+  double esc[2];
+  int j;
+  CalcCharCounts (discard_word, discard_num, char_lens, len_lens, escape);
+  esc[0] = -log2 (escape[0] / (freqs_trans[0] + escape[0]));
+  esc[1] = -log2 (escape[1] / (freqs_trans[1] + escape[1]));
+  for (j = 0; j < discard_num; j++, discard_word++)
+    {
+      float cbc, wbc;
+      u_char *buf = (*discard_word)->word;
+      int len = *buf++;
+      u_long freq = (*discard_word)->freq;
+      int idx = KIND (*discard_word);
+
+      cbc = len_lens[idx][len];
+      for (; len; len--, buf++)
+	cbc += char_lens[idx][(u_long) (*buf)];
+
+      (*discard_word)->char_bit_cost = (cbc + esc[idx]) * freq;
+
+      wbc = -log2 (freq / (freqs_trans[idx] + escape[idx])) * freq;
+
+      (*discard_word)->saving = ((*discard_word)->char_bit_cost - wbc) /
+	(sizeof (char *) + (*discard_word)->word[0]);
+
+      (*discard_word)->num_trans = num_trans;
+    }
+  for (j = 0; j < keep_num; j++, keep_word++)
+    {
+      float cbc, wbc;
+      u_char *buf = (*keep_word)->word;
+      int len = *buf++;
+      u_long freq = (*keep_word)->freq;
+      int idx = KIND (*keep_word);
+
+      cbc = len_lens[idx][len];
+      for (; len; len--, buf++)
+	cbc += char_lens[idx][(u_long) (*buf)];
+
+      (*keep_word)->char_bit_cost = (cbc + esc[idx]) * freq;
+
+      wbc = -log2 (freq / (freqs_trans[idx] + escape[idx])) * freq;
+
+      (*keep_word)->saving = ((*keep_word)->char_bit_cost - wbc) /
+	(sizeof (char *) + (*keep_word)->word[0]);
+
+      (*keep_word)->num_trans = num_trans;
+    }
+  Xfree (char_lens[0]);
+  Xfree (char_lens[1]);
+  Xfree (len_lens[0]);
+  Xfree (len_lens[1]);
+}
+
+
+
+static void 
+Method3 (int k)
+{
+  int i, keep_num, discard_num, mem, num_trans, recalc_reqd;
+  int keep_to_discard = 0;
+  int discard_to_keep = 0;
+  int recalcs = 0;
+  double freqs_trans[2], total;
+  u_long escape[2];
+  WordData **keep_heap, **discard_heap;
+
+  freqs_trans[0] = freqs_trans[1] = 0;
+  num_trans = 0;
+
+  discard_num = Num[0] + Num[1];
+  discard_heap = Xmalloc (discard_num * sizeof (WordData *));
+
+  keep_num = 0;
+  keep_heap = Xmalloc (discard_num * sizeof (WordData *));
+
+
+  for (i = 0; i < Num[0]; i++)
+    discard_heap[i] = Words[0] + i;
+  for (i = 0; i < Num[1]; i++)
+    discard_heap[i + Num[0]] = Words[1] + i;
+
+  heap_build (discard_heap, sizeof (*discard_heap), discard_num, DecFreqIncWL);
+
+  mem = 0;
+  while (k > mem && discard_num)
+    {
+      WordData *word = discard_heap[0];
+      mem += sizeof (u_char *) + word->word[0];
+      heap_deletehead (discard_heap, sizeof (word), &discard_num, DecFreqIncWL);
+      keep_heap[keep_num++] = word;
+      freqs_trans[KIND (word)] += word->freq;
+      num_trans++;
+    }
+
+  CalcBitCost (discard_heap, discard_num, keep_heap, keep_num,
+	       freqs_trans, escape, num_trans);
+  heap_build (discard_heap, sizeof (*discard_heap), discard_num, BigSaving);
+  heap_build (keep_heap, sizeof (*keep_heap), keep_num, SmallSaving);
+
+  total = 0;
+  recalc_reqd = 0;
+  while (keep_num && discard_num)
+    {
+      if ((keep_num && keep_heap[0]->num_trans < num_trans) ||
+	  (discard_num && discard_heap[0]->num_trans < num_trans))
+	{
+	  if (keep_num && keep_heap[0]->num_trans < num_trans)
+	    {
+	      WordData *word = keep_heap[0];
+	      int idx = KIND (word);
+	      float wbc;
+#ifdef DEBUG1
+	      fprintf (stderr, "KEEP \"%s\" %.2f ->", word2str (word->word),
+		       word->saving);
+#endif
+	      wbc = -log2 (word->freq / (freqs_trans[idx] + escape[idx])) *
+		word->freq;
+	      word->saving = (word->char_bit_cost - wbc) /
+		(sizeof (char *) + word->word[0]);
+#ifdef DEBUG1
+	      fprintf (stderr, " %.2f\n", word->saving);
+#endif
+	      word->num_trans = num_trans;
+	      heap_changedhead (keep_heap, sizeof (word), keep_num, SmallSaving);
+	    }
+
+	  if (discard_num && discard_heap[0]->num_trans < num_trans)
+	    {
+	      WordData *word = discard_heap[0];
+	      int idx = KIND (word);
+	      float wbc;
+#ifdef DEBUG1
+	      fprintf (stderr, "DISCARD \"%s\" %.2f ->", word2str (word->word),
+		       word->saving);
+#endif
+	      wbc = -log2 (word->freq / (freqs_trans[idx] + escape[idx])) *
+		word->freq;
+	      word->saving = (word->char_bit_cost - wbc) /
+		(sizeof (char *) + word->word[0]);
+#ifdef DEBUG1
+	      fprintf (stderr, " %.2f\n", word->saving);
+#endif
+	      word->num_trans = num_trans;
+	      heap_changedhead (discard_heap, sizeof (word),
+				discard_num, BigSaving);
+	    }
+	}
+      else if (keep_heap[0]->saving < discard_heap[0]->saving)
+	{
+	  assert (keep_num && discard_num);
+	  if (keep_num && mem + sizeof (char *) + discard_heap[0]->word[0] > k)
+	    {
+	      /* Transfer the word at the top of the keep heap to the
+	         discard heap. */
+	      WordData *word = keep_heap[0];
+	      int idx = KIND (word);
+	      heap_deletehead (keep_heap, sizeof (word), &keep_num, SmallSaving);
+	      discard_heap[discard_num] = word;
+	      heap_additem (discard_heap, sizeof (word), &discard_num,
+			    BigSaving);
+	      freqs_trans[idx] -= word->freq;
+	      mem -= sizeof (u_char *) + word->word[0];
+	      num_trans++;
+	      total += word->saving;
+	      keep_to_discard++;
+#ifdef DEBUG
+	      fprintf (stderr,
+		       "KEEP -> DISCARD %8d :%8d :%8.0f :%8.0f : \"%s\"\n",
+		       mem, word->freq, word->char_bit_cost,
+		       word->saving, word2str (word->word));
+#endif
+	    }
+	  else
+	    {
+	      /* Transfer the word at the top of the discard heap to the
+	         keep heap. */
+	      WordData *word = discard_heap[0];
+	      int idx = KIND (word);
+	      heap_deletehead (discard_heap, sizeof (word),
+			       &discard_num, BigSaving);
+	      keep_heap[keep_num] = word;
+	      heap_additem (keep_heap, sizeof (word), &keep_num, SmallSaving);
+	      freqs_trans[idx] += word->freq;
+	      mem += sizeof (u_char *) + word->word[0];
+	      num_trans++;
+	      total += word->saving;
+	      discard_to_keep++;
+#ifdef DEBUG
+	      fprintf (stderr,
+		       "DISCARD -> KEEP %8d :%8d :%8.0f :%8.0f : \"%s\"\n",
+		       mem, word->freq, word->char_bit_cost,
+		       word->saving, word2str (word->word));
+#endif
+	    }
+
+	  recalc_reqd = 1;
+
+	}
+      else
+	{
+	  if (recalc_reqd == 0)
+	    break;
+#ifdef DEBUG1
+	  fprintf (stderr, "--------------\n");
+#endif
+	  if (recalcs == MAX_RECALCULATIONS)
+	    break;
+	  CalcBitCost (discard_heap, discard_num, keep_heap, keep_num,
+		       freqs_trans, escape, num_trans);
+	  heap_build (discard_heap, sizeof (*discard_heap),
+		      discard_num, BigSaving);
+	  heap_build (keep_heap, sizeof (keep_heap), keep_num, SmallSaving);
+	  recalc_reqd = 0;
+	  recalcs++;
+	}
+    }
+
+  Alloc_keep_discard ();
+
+  for (i = 0; i < discard_num; i++)
+    {
+      WordData *word = discard_heap[i];
+      int idx = KIND (word);
+      assert (IsWord (word) || IsNonWord (word));
+      discard[idx].wd[discard[idx].num_wds++] = word;
+    }
+  for (i = 0; i < keep_num; i++)
+    {
+      WordData *word = keep_heap[i];
+      int idx = KIND (word);
+      assert (IsWord (word) || IsNonWord (word));
+      keep[idx].wd[keep[idx].num_wds++] = word;
+    }
+  SortAndCount_DictData (&keep[0]);
+  SortAndCount_DictData (&keep[1]);
+  SortAndCount_DictData (&discard[0]);
+  SortAndCount_DictData (&discard[1]);
+
+  assert (keep[0].num_wds + discard[0].num_wds == Num[0]);
+  assert (keep[1].num_wds + discard[1].num_wds == Num[1]);
+  Message ("Keep -> Discard        : %8d", keep_to_discard);
+  Message ("Discard -> Keep        : %8d", discard_to_keep);
+  Message ("Huffman Recalculations : %8d", recalcs);
+  if (recalcs == MAX_RECALCULATIONS)
+    Message ("WARNING: The number of recalculations == %d", MAX_RECALCULATIONS);
+}
+
+
+
+
+
+
+
+
+
+
+/****************************************************************************
+ *****									*****
+ *****			Dictionary saving code				*****
+ *****									*****
+ ****************************************************************************/
+
+
+
+static void 
+Write_cdh (FILE * f, compression_dict_header * cdh)
+{
+  /* [RPAP - Jan 97: Endian Ordering] */
+  int i;
+  compression_dict_header tmp = *cdh;
+  HTONUL(tmp.dict_type);
+  HTONUL(tmp.novel_method);
+  for (i = 0; i < TEXT_PARAMS; i++)
+    HTONUL(tmp.params[i]);
+  HTONUL(tmp.num_words[0]);
+  HTONUL(tmp.num_words[1]);
+  HTONUL(tmp.num_word_chars[0]);
+  HTONUL(tmp.num_word_chars[1]);
+  HTONUL(tmp.lookback);
+
+  fwrite (&tmp, sizeof (tmp), 1, f);
+}
+
+
+static void 
+Write_words (FILE * f, DictData * dd)
+{
+  int i;
+  u_char *curr, *prev = NULL;
+  for (i = 0; i < dd->num_wds; i++)
+    {
+      int len;
+      curr = dd->wd[i]->word;
+      if (prev)
+	/* look for prefix match with prev string */
+	len = prefixlen (prev, curr);
+      else
+	len = 0;
+      fputc ((len << 4) + (curr[0] - len), f);
+      fwrite (curr + len + 1, sizeof (u_char), curr[0] - len, f);
+      prev = curr;
+    }
+
+}
+
+
+static int 
+Uncompressed_size (DictData * dd)
+{
+  int i, us;
+  for (us = i = 0; i < dd->num_wds; i++)
+    us += dd->wd[i]->word[0];
+  return us;
+}
+
+
+static u_long 
+Write_data (FILE * f, DictData * dd, int lookback)
+{
+  u_long mem_reqd;
+  huff_data *hd;
+  int i; 
+  u_long us = dd->num_wds;
+  long *freqs;
+  u_long huff_words_size[MAX_HUFFCODE_LEN + 1];
+  u_long lencounts[MAX_HUFFCODE_LEN + 1];
+  u_char *lastword[MAX_HUFFCODE_LEN + 1];
+
+  if (!(freqs = Xmalloc ((dd->num_wds) * sizeof (*freqs))))
+    FatalError (1, "Unable to allocate memory for freqs");
+
+  for (i = 0; i < dd->num_wds; i++)
+    {
+      freqs[i] = dd->wd[i]->freq;
+      us += dd->wd[i]->word[0];
+    }
+
+  if (!(hd = Generate_Huffman_Data (dd->num_wds, freqs, NULL, NULL)))
+    FatalError (1, "Unable to allocate memory for huffman data");
+
+  Xfree (freqs), freqs = NULL;
+
+  if (Write_Huffman_Data (f, hd) == -1)
+    FatalError (1, "Unable to write huffman data");
+
+  HTONUL(us);  /* [RPAP - Jan 97: Endian Ordering] */
+  fwrite (&us, sizeof (us), 1, f);
+  NTOHUL(us);  /* [RPAP - Jan 97: Endian Ordering] */
+
+
+/* Calculate the amount of memory that will be required to store the text for
+   each different huffman code len. Every 1<<lookback words for each different
+   codelen length will not be prefixed by previous strings. */
+
+
+  bzero ((char *) &huff_words_size, sizeof (huff_words_size));
+  bzero ((char *) &lencounts, sizeof (lencounts));
+
+  mem_reqd = 0;
+
+  for (i = 0; i < dd->num_wds; i++)
+    {
+      int codelen = hd->clens[i];
+      u_char *word = dd->wd[i]->word;
+
+      if (!codelen)
+	FatalError (1, "The length of a code for a word was zero");
+
+      huff_words_size[codelen] += word[0] + 1;
+      mem_reqd += word[0] + (lookback != 0);
+#if 0
+      if ((lencounts[codelen] & ((1 << lookback) - 1)) == 0)
+	lastword[codelen] = word;
+      else
+	huff_words_size[codelen] -= prefixlen (lastword[codelen], word);
+#else
+      if ((lencounts[codelen] & ((1 << lookback) - 1)) != 0)
+	{
+	  int save = prefixlen (lastword[codelen], word);
+	  mem_reqd -= save;
+	  huff_words_size[codelen] -= save;
+	}
+      else
+	{
+	  mem_reqd += sizeof (u_char *);
+	}
+      lastword[codelen] = word;
+#endif
+      lencounts[codelen]++;
+    }
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = hd->mincodelen; i < hd->maxcodelen + 1; i++)
+    HTONUL(huff_words_size[i]);
+
+  fwrite (huff_words_size + hd->mincodelen, sizeof (*huff_words_size),
+	  hd->maxcodelen - hd->mincodelen + 1, f);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = hd->mincodelen; i < hd->maxcodelen + 1; i++)
+    NTOHUL(huff_words_size[i]);
+
+  Write_words (f, dd);
+
+  Xfree (hd->clens);
+  Xfree (hd);
+
+  return mem_reqd;
+}
+
+
+
+static void 
+Write_charfreqs (FILE * f, DictData * dd, int words,
+		 int zero_freq_permitted)
+{
+  int j;
+  long freqs[256];
+  WordData **wd = dd->wd;
+  huff_data *hd;
+
+  bzero ((char *) freqs, sizeof (freqs));
+
+  for (j = 0; j < dd->num_wds; j++, wd++)
+    {
+      u_char *buf = (*wd)->word;
+      int len = *buf++;
+      for (; len; len--, buf++)
+	freqs[(u_long) (*buf)] += (*wd)->freq;
+    }
+
+  if (!zero_freq_permitted)
+    for (j = 0; j < 256; j++)
+      if (!freqs[j] && PESINAWORD (j) == words)
+	freqs[j] = 1;
+
+  if (!(hd = Generate_Huffman_Data (256, freqs, NULL, NULL)))
+    FatalError (1, "Unable to allocate memory for huffman data");
+
+  if (Write_Huffman_Data (f, hd) == -1)
+    FatalError (1, "Unable to write huffman data");
+
+  Xfree (hd->clens);
+  Xfree (hd);
+}
+
+
+
+
+static void 
+Write_wordlens (FILE * f, DictData * dd, int zero_freq_permitted)
+{
+  int j;
+  long freqs[16];
+  WordData **wd = dd->wd;
+  huff_data *hd;
+
+  bzero ((char *) freqs, sizeof (freqs));
+
+  for (j = 0; j < dd->num_wds; j++, wd++)
+    freqs[(*wd)->word[0]] += (*wd)->freq;
+
+  if (!zero_freq_permitted)
+    for (j = 0; j < 16; j++)
+      if (!freqs[j])
+	freqs[j] = 1;
+
+  if (!(hd = Generate_Huffman_Data (16, freqs, NULL, NULL)))
+    FatalError (1, "Unable to allocate memory for huffman data");
+
+  if (Write_Huffman_Data (f, hd) == -1)
+    FatalError (1, "Unable to write huffman data");
+
+
+  Xfree (hd->clens);
+  Xfree (hd);
+}
+
+
+
+static u_long 
+WriteOutWords (char *file_name, u_long type, int lookback)
+{
+  FILE *f;
+  int i;
+  u_long mem_reqd = 0;
+
+  compression_dict_header cdh;
+  f = create_file (file_name, TEXT_DICT_SUFFIX, "w+b",
+		   MAGIC_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  bzero((char *) &cdh, sizeof(cdh));
+
+  cdh.dict_type = type;
+  cdh.novel_method = (type == MG_SEED_DICTIONARY) ? novel_method :
+    MG_NOVEL_HUFFMAN_CHARS;
+
+  cdh.num_words[1] = keep[1].num_wds;
+  cdh.num_words[0] = keep[0].num_wds;
+  cdh.num_word_chars[1] = Uncompressed_size (&keep[1]);
+  cdh.num_word_chars[0] = Uncompressed_size (&keep[0]);
+  cdh.lookback = lookback;
+
+  Write_cdh (f, &cdh);
+
+  for (i = 0; i < 2; i++)
+    switch (type)
+      {
+      case MG_COMPLETE_DICTIONARY:
+	{
+	  mem_reqd += Write_data (f, &keep[i], lookback);
+	}
+	break;
+      case MG_PARTIAL_DICTIONARY:
+	{
+	  if (keep[i].num_wds)
+	    {
+	      int j;
+	      WordData esc;
+	      esc.freq = 0;
+	      esc.word = (u_char *) "";
+	      keep[i].wd[keep[i].num_wds++] = &esc;
+	      for (j = 0; j < discard[i].num_wds; j++)
+		esc.freq += discard[i].wd[j]->freq;
+	      if (!esc.freq)
+		esc.freq++;
+	      mem_reqd += Write_data (f, &keep[i], lookback);
+	    }
+	  Write_charfreqs (f, &discard[i], i, 1);
+	  Write_wordlens (f, &discard[i], 1);
+	}
+	break;
+      case MG_SEED_DICTIONARY:
+	{
+	  if (keep[i].num_wds)
+	    {
+	      int j;
+	      WordData esc;
+	      esc.freq = 0;
+	      esc.word = (u_char *) "";
+	      keep[i].wd[keep[i].num_wds++] = &esc;
+	      for (j = 0; j < all[i].num_wds; j++)
+		if (all[i].wd[j]->freq == 1)
+		  esc.freq++;
+	      if (!esc.freq)
+		esc.freq++;
+	      mem_reqd += Write_data (f, &keep[i], lookback);
+	    }
+	  switch (novel_method)
+	    {
+	    case MG_NOVEL_HUFFMAN_CHARS:
+	      Write_charfreqs (f, &all[i], i, 0);
+	      Write_wordlens (f, &all[i], 0);
+	      break;
+	    case MG_NOVEL_BINARY:
+	      break;
+	    case MG_NOVEL_DELTA:
+	      break;
+	    case MG_NOVEL_HYBRID:
+	      break;
+	    case MG_NOVEL_HYBRID_MTF:
+	      break;
+	    default:
+	      FatalError (1, "Bad novel method");
+	    }
+	}
+	break;
+      }
+  fclose (f);
+  return mem_reqd;
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_decompress_text.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_decompress_text.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_decompress_text.1	(revision 14757)
@@ -0,0 +1,78 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_decompress_text 1 \*(Dt CITRI
+.SH NAME
+mg_decompress_text \- decompresses the compressed text of a collection
+.SH SYNOPSIS
+.B mg_decompress_text
+[
+.B \-h
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_decompress_text
+decompresses the compressed text of a collection, inserts paragraph and
+document markers, writing the output to
+.IR stdout ".  "
+This program was created
+to be used as a type of
+.BR mg_get (1).
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 25
+.B *.text
+Compressed documents.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.text.dict.aux
+Auxiliary compression dictionary.
+.TP
+.B *.text.dict.fast
+Fast loading compression dictionary.
+.TP
+.B *.invf.paragraph
+Paragraph counts for documents.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_passes (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_decompress_text.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_decompress_text.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_decompress_text.c	(revision 14757)
@@ -0,0 +1,167 @@
+#include "sysfuncs.h"
+
+#include "filestats.h"
+#include "netorder.h"
+#include "memlib.h"
+#include "messages.h"
+#include "huffman.h"
+#include "bitio_m_mem.h"
+#include "bitio_m.h"
+#include "bitio_stdio.h"
+#include "huffman_stdio.h"
+
+#include "mg_files.h"
+#include "mg.h"
+#include "backend.h"  /* compressed_dict struct */
+#include "text_get.h"
+#include "words.h"
+
+#define EOD         '\002'
+#define EOP         '\003'
+
+/* These are defined in mgquery, and they need to be here for backend.o */
+/* Messy I know but this was meant to be a quick hack :-) */
+#if defined(PARADOCNUM) || defined(NZDL)
+int *Paragraph = NULL;
+int Documents = 0;
+#endif
+
+int
+main (int argc, char **argv)
+{
+  FILE *text, *text_idx, *para;
+  File *text_comp_dict = NULL, *text_aux_dict = NULL, *text_fast_comp_dict = NULL;
+
+  int ch;
+  unsigned long start, finish, len;
+  u_long total_chars = 0;
+  u_char *c_buffer = 0;
+  int buf_len = -1;
+  u_char *uc_buffer = 0;
+  int ULen;
+  compression_dict *cd = NULL;
+  compressed_text_header cth;
+  u_long doc;
+  int count;
+  char *filename = "";
+  char path[512];
+  opterr = 0;
+  msg_prefix = argv[0];
+
+  while ((ch = getopt (argc, argv, "f:d:h")) != -1)
+    switch (ch)
+      {
+      case 'f':		/* input file */
+	filename = optarg;
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-h] [-d directory] -f name\n",
+		 argv[0]);
+	exit (1);
+      }
+
+  /* Open files */
+  text = open_file (filename, TEXT_SUFFIX, "rb", MAGIC_TEXT, MG_ABORT);
+  fread ((char *)&cth, sizeof (cth), 1, text);
+
+  text_idx = open_file (filename, TEXT_IDX_SUFFIX, "rb", MAGIC_TEXI, MG_ABORT);
+  fread ((char *)&cth, sizeof (cth), 1, text_idx);
+
+  NTOHUL(cth.num_of_docs);
+  NTOHD(cth.num_of_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(cth.num_of_words);
+  NTOHUL(cth.length_of_longest_doc);
+  NTOHD(cth.ratio);
+
+  para = open_file (filename, INVF_PARAGRAPH_SUFFIX, "rb", MAGIC_PARAGRAPH, MG_CONTINUE);
+
+  sprintf (path, FILE_NAME_FORMAT, get_basepath(), filename, TEXT_DICT_FAST_SUFFIX);  /* [RPAP - Feb 97: WIN32 Port] */
+  if (!(text_fast_comp_dict = Fopen (path, "rb", MAGIC_FAST_DICT)))
+    {
+      sprintf (path, FILE_NAME_FORMAT, get_basepath(), filename, TEXT_DICT_SUFFIX);  /* [RPAP - Feb 97: WIN32 Port] */
+      text_comp_dict = Fopen (path, "rb", MAGIC_DICT);
+      if (!text_comp_dict)
+	FatalError (1, "Could not open compressed dictionary");
+      sprintf (path, FILE_NAME_FORMAT, get_basepath(), filename, TEXT_DICT_AUX_SUFFIX);  /* [RPAP - Feb 97: WIN32 Port] */
+      text_aux_dict = Fopen (path, "rb", MAGIC_AUX_DICT);
+    }
+
+  cd = LoadCompDict (text_comp_dict, text_aux_dict, text_fast_comp_dict);
+
+
+  /* Uncompress text */
+
+  doc = 1;
+  fread ((char *)&start, sizeof (start), 1, text_idx);
+  if (para)
+    fread ((char *)&count, sizeof (count), 1, para);
+  else
+    count = 1;
+
+  for (;;)
+    {
+      fread ((char *) &finish, sizeof (finish), 1, text_idx);
+      len = finish - start;
+      
+      if ((int) len > buf_len)
+	{
+	  if (c_buffer)
+	    {
+	      Xfree (c_buffer);
+	      Xfree (uc_buffer);
+	    }
+	  if (!(c_buffer = Xmalloc (len)))
+	    FatalError (1, "Cannot allocate memory for compressed buffer");
+	  if (!(uc_buffer = Xmalloc ((int) (cth.ratio * 1.01 * len) + 100)))
+	    FatalError (1, "Cannot allocate memory for uncompressed buffer");
+	  buf_len = len;
+	}
+
+      fread (c_buffer, 1, len, text);
+      DecodeText (cd, c_buffer, len, uc_buffer, &ULen);
+      fwrite (uc_buffer, ULen, sizeof (u_char), stdout);
+      fflush (stdout);
+
+      total_chars += ULen;
+
+      if (++doc > cth.num_of_docs)
+	{
+	  if (para)
+	    fputc (EOP, stdout);
+	  fputc (EOD, stdout);
+	  fflush (stdout);
+	  break;
+	}
+
+      if (!--count)
+	{
+	  /* End of document */
+	  fputc (EOD, stdout);
+	  if (para)
+	    fread ((char *)&count, sizeof (count), 1, para);
+	  else
+	    count = 1;
+	}
+      else
+	fputc (EOP, stdout);
+      fflush (stdout);
+      start = finish;
+    }
+
+  /* Close files */
+
+  fclose (text);
+  fclose (text_idx);
+  if (para)
+    fclose (para);
+
+#if 0
+  printf ("\n#Total chars output = %lu\n", total_chars);
+#endif
+
+  return 0;
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_errors.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_errors.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_errors.c	(revision 14757)
@@ -0,0 +1,73 @@
+/**************************************************************************
+ *
+ * mg_errors.c -- Error related stuff for mgquery
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "memlib.h"
+
+#include "mg_errors.h"
+
+
+
+int mg_errno = MG_NOERROR;
+
+char *mg_errorstrs[] =
+{
+  "No error",
+  "Out of memory",
+  "File \"%s\" not found",
+  "Bad magic number in \"%s\"",
+  "Error reading \"%s\"",
+  "MG_BUFTOOSMALL",
+  "Files required for level 2 and 3 inversion are missing"};
+
+
+/* [RJM 07/98: Memory Leak] -- rest of file */
+
+static char null_data[] = "";
+char *mg_error_data = null_data;
+
+
+void MgErrorData (char *s)
+{
+  /* free the current error string, unless it is the null string */
+  if ((mg_error_data != NULL) && (mg_error_data != null_data)) {
+    Xfree (mg_error_data);
+    mg_error_data = null_data;
+  }
+
+  /* make a copy of the string */
+  mg_error_data = Xstrdup (s);
+
+  /* if the alloc failed set the error to the null string */
+  if (!mg_error_data) mg_error_data = null_data;
+}
+
+
+void MgErrorDeinit (void)
+{
+  /* free the current error string, unless it is the null string */
+  if ((mg_error_data != NULL) && (mg_error_data != null_data)) {
+    Xfree (mg_error_data);
+    mg_error_data = null_data;
+  }
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_errors.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_errors.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_errors.h	(revision 14757)
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * mg_errors.h -- Error related stuff for mgquery
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+extern int mg_errno;
+extern char *mg_error_data;
+extern char *mg_errorstrs[];
+
+
+#define MG_NOERROR 0
+#define MG_NOMEM 1
+#define MG_NOFILE 2
+#define MG_BADMAGIC 3
+#define MG_READERR 4
+#define MG_BUFTOOSMALL 5
+#define MG_INVERSION 6
+
+void MgErrorData (char *s);
+void MgErrorDeinit (void);
Index: /indexers/branches/3.03a/mg/src/text/mg_fast_comp_dict.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_fast_comp_dict.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_fast_comp_dict.1	(revision 14757)
@@ -0,0 +1,86 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_fast_comp_dict 1 \*(Dt CITRI
+.SH NAME
+mg_fast_comp_dict \- build a fast loading compression dictionary
+.SH SYNOPSIS
+.B mg_fast_comp_dict
+[
+.B \-h
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_fast_comp_dict
+builds a fast-loading compression dictionary from the standard
+compression dictionary.  The new dictionary has the property that
+.BR mgquery (1)
+can load it in very quickly, making the startup time for
+.BR mgquery (1)
+much shorter.  The new dictionary is larger on disk than the original,
+but they are no different when it comes to memory usage.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.text.dict
+Compression dictionary.
+.TP
+.B *.text.dict.fast
+Fast loading compression dictionary.
+.TP
+.B *.text.dict.aux
+Auxiliary compression dictionary.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_fast_comp_dict.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_fast_comp_dict.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_fast_comp_dict.c	(revision 14757)
@@ -0,0 +1,801 @@
+/**************************************************************************
+ *
+ * mg_fast_comp_dict.c -- Program to generate a fast compression dictionary
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:06  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:44  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:34:57  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:56:55  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:47  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+#include "sysfuncs.h"
+
+#include "filestats.h"
+#include "huffman.h"
+#include "timing.h"
+#include "messages.h"
+#include "memlib.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "local_strings.h"
+#include "mg.h"
+#include "text.h"
+#include "invf.h"
+#include "lists.h"
+#include "backend.h"
+#include "mg_files.h"
+#include "locallib.h"
+#include "words.h"
+
+
+
+#define ALIGN_SIZE(p,t) (((p) + (sizeof(t)-1)) & (~(sizeof(t)-1)))
+
+#define WORDNO(p, base) ((((char*)(p))-((char*)(base)))/sizeof(u_char*))
+#define FIXUP(p) (fixup[WORDNO(p,buffer)/8] |= (1<<(WORDNO(p, buffer) & 7)))
+
+#define IS_FIXUP(p) ((fixup[WORDNO(p,buffer)/8] & (1<<(WORDNO(p, buffer) & 7))) != 0)
+
+#define FIXUP_VALS(vals) do {						\
+	int i;								\
+	for (i=0; i < MAX_HUFFCODE_LEN+1; i++)				\
+	  FIXUP(&vals[i]);						\
+      } while(0)
+
+
+
+static u_long mem_for_comp_dict (char *filename);
+static void load_comp_dict (char *filename);
+static void save_fast_dict (char *filename);
+static void unfixup_buffer (void);
+
+
+static void *buffer;
+static void *cur;
+static u_char *fixup;
+static u_long mem, fixup_mem;
+
+int main (int argc, char **argv)
+{
+  ProgTime StartTime;
+  int ch;
+  char *filename = "";
+  opterr = 0;
+  msg_prefix = argv[0];
+  while ((ch = getopt (argc, argv, "f:d:h")) != -1)
+    switch (ch)
+      {
+      case 'f':		/* input file */
+	filename = optarg;
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-f input_file] [-d data directory] [-h]\n",
+		 argv[0]);
+	exit (1);
+      }
+  GetTime (&StartTime);
+
+  mem = mem_for_comp_dict (filename);
+
+  fixup_mem = (ALIGN_SIZE (mem, u_char *) / sizeof (u_char *) + 7) / 8;
+
+  cur = buffer = Xmalloc (mem);
+  bzero (buffer, mem);
+  fixup = Xmalloc (fixup_mem);
+  bzero (fixup, fixup_mem);
+
+  Message ("Estimated memory for fast_dict %u", mem);
+  Message ("Estimated memory for fixups %u", fixup_mem);
+
+  load_comp_dict (filename);
+
+  Message ("Actual memory for fast_dict %u", (char *) cur - (char *) buffer);
+
+  if ((u_long) cur > (u_long) buffer + mem)
+    FatalError (1, "The buffer was not big enough for the dictionary");
+
+  {
+    /* [RPAP - Jan 97: Endian Ordering] */
+    compression_dict *cd = (compression_dict *) buffer;
+    int i, which;
+
+    /* cfh */
+    for (which = 0; which <= 1; which++)
+      {
+	int j;
+	
+	HTONSI(cd->cfh[which]->hd.num_codes);
+	HTONSI(cd->cfh[which]->hd.mincodelen);
+	HTONSI(cd->cfh[which]->hd.maxcodelen);
+	for (j = 0; j < MAX_HUFFCODE_LEN + 1; j++)
+	  {
+	    HTONSI(cd->cfh[which]->hd.lencount[j]);
+	    HTONUL(cd->cfh[which]->hd.min_code[j]);
+	  }
+	HTONUL(cd->cfh[which]->uncompressed_size);
+	for (j = 0; j < MAX_HUFFCODE_LEN + 1; j++)
+	  HTONUL(cd->cfh[which]->huff_words_size[j]);
+      }
+    HTONUL(cd->MemForCompDict);
+    /* ad */
+    if (cd->cdh.novel_method == MG_NOVEL_BINARY ||
+	cd->cdh.novel_method == MG_NOVEL_DELTA ||
+	cd->cdh.novel_method == MG_NOVEL_HYBRID ||
+	cd->cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+      for (which = 0; which <= 1; which++)
+	{
+	  int j;
+	  
+	  HTONUL(cd->ad->afh[which].num_frags);
+	  HTONUL(cd->ad->afh[which].mem_for_frags);
+	  for (j = 0; j < 33; j++)
+	    {
+	      HTONSI(cd->ad->blk_start[which][j]);
+	      HTONSI(cd->ad->blk_end[which][j]);
+	    }
+	}
+    /* cdh */
+    HTONUL(cd->cdh.dict_type);
+    HTONUL(cd->cdh.novel_method);
+    for (i = 0; i < TEXT_PARAMS; i++)
+      HTONUL(cd->cdh.params[which]);
+    HTONUL(cd->cdh.num_words[0]);
+    HTONUL(cd->cdh.num_words[1]);
+    HTONUL(cd->cdh.num_word_chars[0]);
+    HTONUL(cd->cdh.num_word_chars[1]);
+    HTONUL(cd->cdh.lookback);
+    HTONSI(cd->fast_loaded);
+  }
+
+  unfixup_buffer ();
+
+  save_fast_dict (filename);
+
+  Message ("%s", ElapsedTime (&StartTime, NULL));
+  return 0;
+}
+
+
+
+static void 
+unfixup_buffer ()
+{
+  u_long *p;
+  for (p = buffer; (u_long) p < (u_long) cur; p++)
+    {
+      if (IS_FIXUP (p))
+	*p = *p - (u_long) buffer;
+    }
+}
+
+
+
+
+static u_long 
+mem_for_aux_dict (compression_dict_header * cdh, char *filename)
+{
+  int i;
+  u_long mem = sizeof (auxiliary_dict);
+  FILE *aux;
+
+  aux = open_file (filename, TEXT_DICT_AUX_SUFFIX, "rb",
+		   MAGIC_AUX_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  for (i = 0; i <= 1; i++)
+    {
+      aux_frags_header afh;
+      fread (&afh, sizeof (afh), 1, aux);
+      NTOHUL(afh.num_frags);  /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(afh.mem_for_frags);  /* [RPAP - Jan 97: Endian Ordering] */
+      mem += afh.num_frags * sizeof (u_char *);
+      mem = ALIGN_SIZE (mem + afh.mem_for_frags, u_char *);
+      fseek (aux, afh.mem_for_frags, SEEK_CUR);
+    }
+  fclose (aux);
+
+  return mem;
+}
+
+
+
+static u_long 
+mem_for_words (FILE * dict, compression_dict_header * cdh,
+	       comp_frags_header * cfh)
+{
+  u_long mem = 0;
+  u_long i, lookback;
+  int ptrs_reqd = 0;
+  int mem_reqd = 0;
+
+  lookback = cdh->lookback;
+
+  for (i = cfh->hd.mincodelen; i <= cfh->hd.maxcodelen; i++)
+    {
+      ptrs_reqd += (cfh->hd.lencount[i] + ((1 << lookback) - 1)) >> lookback;
+      mem_reqd += cfh->huff_words_size[i];
+    }
+
+  mem += ptrs_reqd * sizeof (u_char *);
+  mem += (MAX_HUFFCODE_LEN + 1) * sizeof (u_char **);
+  mem += mem_reqd;
+
+  for (i = 0; i < cfh->hd.num_codes; i++)
+    {
+      register int val;
+      for (val = getc (dict) & 0xf; val; val--)
+	getc (dict);
+    }
+  return ALIGN_SIZE (mem, u_char *);
+}
+
+
+
+
+static u_long 
+mem_for_comp_dict (char *filename)
+{
+  u_long mem = sizeof (compression_dict);
+  compression_dict_header cdh;
+  comp_frags_header cfh;
+  FILE *dict;
+  int which;
+  int i;  /* [RPAP - Jan 97: Endian Ordering] */
+
+  dict = open_file (filename, TEXT_DICT_SUFFIX, "rb",
+		    MAGIC_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  fread (&cdh, sizeof (cdh), 1, dict);
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(cdh.dict_type);
+  NTOHUL(cdh.novel_method);
+  for (i = 0; i < TEXT_PARAMS; i++)
+    NTOHUL(cdh.params[i]);
+  NTOHUL(cdh.num_words[0]);
+  NTOHUL(cdh.num_words[1]);
+  NTOHUL(cdh.num_word_chars[0]);
+  NTOHUL(cdh.num_word_chars[1]);
+  NTOHUL(cdh.lookback);
+
+  for (which = 0; which < 2; which++)
+    switch (cdh.dict_type)
+      {
+      case MG_COMPLETE_DICTIONARY:
+	{
+	  mem += sizeof (comp_frags_header);
+	  Read_cfh (dict, &cfh, NULL, NULL);
+
+	  /* Don't need to count the space for the clens of the huffman data */
+
+	  mem += mem_for_words (dict, &cdh, &cfh);
+	  if (cfh.hd.clens)
+	    Xfree (cfh.hd.clens);
+	}
+	break;
+      case MG_PARTIAL_DICTIONARY:
+	{
+	  huff_data hd;
+	  if (cdh.num_words[which])
+	    {
+	      mem += sizeof (comp_frags_header);
+	      Read_cfh (dict, &cfh, NULL, NULL);
+
+	      /* Don't need to count the space for the clens of the
+	         huffman data */
+
+	      mem += mem_for_words (dict, &cdh, &cfh);
+	      if (cfh.hd.clens)
+		Xfree (cfh.hd.clens);
+
+	    }
+
+	  mem += sizeof (hd);
+	  Read_Huffman_Data (dict, &hd, NULL, NULL);
+	  if (hd.clens)
+	    Xfree (hd.clens);
+	  mem += hd.num_codes * sizeof (unsigned long);
+	  mem += (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *);
+
+	  mem += sizeof (hd);
+	  Read_Huffman_Data (dict, &hd, NULL, NULL);
+	  if (hd.clens)
+	    Xfree (hd.clens);
+	  mem += hd.num_codes * sizeof (unsigned long);
+	  mem += (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *);
+	}
+	break;
+      case MG_SEED_DICTIONARY:
+	{
+	  huff_data hd;
+	  if (cdh.num_words[which])
+	    {
+	      mem += sizeof (comp_frags_header);
+	      Read_cfh (dict, &cfh, NULL, NULL);
+
+	      /* Don't need to count the space for the clens of the
+	         huffman data */
+
+	      mem += mem_for_words (dict, &cdh, &cfh);
+	      if (cfh.hd.clens)
+		Xfree (cfh.hd.clens);
+
+	    }
+	  switch (cdh.novel_method)
+	    {
+	    case MG_NOVEL_HUFFMAN_CHARS:
+	      mem += sizeof (hd);
+	      Read_Huffman_Data (dict, &hd, NULL, NULL);
+	      if (hd.clens)
+		Xfree (hd.clens);
+	      mem += hd.num_codes * sizeof (unsigned long);
+	      mem += (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *);
+
+	      mem += sizeof (hd);
+	      Read_Huffman_Data (dict, &hd, NULL, NULL);
+	      if (hd.clens)
+		Xfree (hd.clens);
+	      mem += hd.num_codes * sizeof (unsigned long);
+	      mem += (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *);
+	      break;
+	    case MG_NOVEL_BINARY:
+	      break;
+	    case MG_NOVEL_DELTA:
+	      break;
+	    case MG_NOVEL_HYBRID:
+	      break;
+	    case MG_NOVEL_HYBRID_MTF:
+	      break;
+	    }
+	  break;
+	}
+      }
+  fclose (dict);
+
+  if (cdh.novel_method == MG_NOVEL_BINARY ||
+      cdh.novel_method == MG_NOVEL_DELTA ||
+      cdh.novel_method == MG_NOVEL_HYBRID ||
+      cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+    mem += mem_for_aux_dict (&cdh, filename);
+
+  return ALIGN_SIZE (mem, u_char *);
+}
+
+
+
+void *
+getmem (u_long size, int align)
+{
+  void *res;
+  cur = (void *) (((u_long) cur + (align - 1)) & (~(align - 1)));
+  res = cur;
+  cur = (char *) cur + size;
+  if ((long) cur > (long) buffer + mem)
+    FatalError (1, "The buffer was not big enough for the dictionary");
+  return res;
+}
+
+
+
+
+
+
+
+
+
+
+
+static auxiliary_dict *
+LoadAuxDict (compression_dict_header * cdh,
+	     char *filename)
+{
+  auxiliary_dict *ad;
+  int i;
+  FILE *aux;
+
+  aux = open_file (filename, TEXT_DICT_AUX_SUFFIX, "rb",
+		   MAGIC_AUX_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  ad = getmem (sizeof (auxiliary_dict), sizeof (u_char *));
+
+  for (i = 0; i <= 1; i++)
+    {
+      int j;
+      u_char *pos;
+
+      fread (&ad->afh[i], sizeof (aux_frags_header), 1, aux);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(ad->afh[i].num_frags);
+      NTOHUL(ad->afh[i].mem_for_frags);
+
+      ad->word_data[i] = getmem (ad->afh[i].mem_for_frags, 1);
+      FIXUP (&ad->word_data[i]);
+
+      ad->words[i] = getmem (ad->afh[i].num_frags * sizeof (u_char *),
+			     sizeof (u_char *));
+      FIXUP (&ad->words[i]);
+
+      fread (ad->word_data[i], ad->afh[i].mem_for_frags, sizeof (u_char), aux);
+
+      pos = ad->word_data[i];
+      for (j = 0; j < ad->afh[i].num_frags; j++)
+	{
+	  ad->words[i][j] = pos;
+	  FIXUP (&ad->words[i][j]);
+	  pos += *pos + 1;
+	}
+      if (cdh->novel_method == MG_NOVEL_HYBRID ||
+	  cdh->novel_method == MG_NOVEL_HYBRID_MTF)
+	{
+	  int num;
+	  num = 1;
+	  ad->blk_start[i][0] = 0;
+	  ad->blk_end[i][0] = cdh->num_words[i] - 1;
+	  while (num < 33)
+	    {
+	      ad->blk_start[i][num] = ad->blk_end[i][num - 1] + 1;
+	      ad->blk_end[i][num] = ad->blk_start[i][num] +
+		(ad->blk_end[i][num - 1] - ad->blk_start[i][num - 1]) * 2;
+	      num++;
+	    }
+	}
+    }
+  fclose (aux);
+  return (ad);
+}
+
+
+
+
+
+static u_char ***
+ReadInWords (FILE * dict, compression_dict * cd,
+	     comp_frags_header * cfh, u_char ** escape)
+{
+  int i, lookback;
+  int ptrs_reqd = 0;
+  int mem_reqd = 0;
+  int num_set[MAX_HUFFCODE_LEN + 1];
+  u_char *next_word[MAX_HUFFCODE_LEN + 1];
+  u_char **vals;
+  u_char ***values;
+  u_char word[MAXWORDLEN + 1];
+  u_char last_word[MAX_HUFFCODE_LEN + 1][MAXWORDLEN + 1];
+
+  lookback = cd->cdh.lookback;
+
+  for (i = cfh->hd.mincodelen; i <= cfh->hd.maxcodelen; i++)
+    {
+      ptrs_reqd += (cfh->hd.lencount[i] + ((1 << lookback) - 1)) >> lookback;
+      mem_reqd += cfh->huff_words_size[i];
+    }
+
+  vals = getmem (ptrs_reqd * sizeof (*vals), sizeof (u_char *));
+
+  values = getmem ((MAX_HUFFCODE_LEN + 1) * sizeof (u_char **), sizeof (u_char **));
+
+  next_word[0] = getmem (mem_reqd, sizeof (char));
+
+  cd->MemForCompDict += ptrs_reqd * sizeof (*vals) +
+    (MAX_HUFFCODE_LEN + 1) * sizeof (u_char **) +
+    mem_reqd;
+
+  values[0] = vals;
+  FIXUP (&values[0]);
+  values[0][0] = next_word[0];
+  FIXUP (&values[0][0]);
+  for (i = 1; i <= cfh->hd.maxcodelen; i++)
+    {
+      int next_start = (values[i - 1] - vals) +
+      ((cfh->hd.lencount[i - 1] + ((1 << lookback) - 1)) >> lookback);
+      values[i] = &vals[next_start];
+      FIXUP (&values[i]);
+      next_word[i] = next_word[i - 1] + cfh->huff_words_size[i - 1];
+      values[i][0] = next_word[i];
+      FIXUP (&values[i][0]);
+    }
+
+  bzero ((char *) num_set, sizeof (num_set));
+
+  for (i = 0; i < cfh->hd.num_codes; i++)
+    {
+      register int val, copy;
+      register int len = cfh->hd.clens[i];
+      val = getc (dict);
+      copy = (val >> 4) & 0xf;
+      val &= 0xf;
+
+      fread (word + copy + 1, sizeof (u_char), val, dict);
+      *word = val + copy;
+
+      if ((num_set[len] & ((1 << lookback) - 1)) == 0)
+	{
+	  values[len][num_set[len] >> lookback] = next_word[len];
+	  FIXUP (&values[len][num_set[len] >> lookback]);
+	  memcpy (next_word[len], word, *word + 1);
+	  if (escape && i == cfh->hd.num_codes - 1)
+	    {
+	      *escape = next_word[len];
+	      FIXUP (escape);
+	    }
+	  next_word[len] += *word + 1;
+	}
+      else
+	{
+	  copy = prefixlen (last_word[len], word);
+	  memcpy (next_word[len] + 1, word + copy + 1, *word - copy);
+	  *next_word[len] = (copy << 4) + (*word - copy);
+	  if (escape && i == cfh->hd.num_codes - 1)
+	    {
+	      *escape = next_word[len];
+	      FIXUP (escape);
+	    }
+	  next_word[len] += (*word - copy) + 1;
+	}
+      memcpy (last_word[len], word, *word + 1);
+      num_set[len]++;
+    }
+  if (cfh->hd.clens)
+    Xfree (cfh->hd.clens);
+  cfh->hd.clens = NULL;
+  return values;
+}
+
+
+static unsigned long **
+Generate_Fast_Huffman_Vals (huff_data * data, u_long * mem)
+{
+  int i;
+  unsigned long *fcode[MAX_HUFFCODE_LEN + 1];
+  unsigned long **values;
+  unsigned long *vals;
+
+  if (!data)
+    return (NULL);
+  vals = getmem (data->num_codes * sizeof (*vals), sizeof (long *));
+  values = getmem ((MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *),
+		   sizeof (long *));
+
+  bzero ((char *) values, (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *));
+
+  if (mem)
+    *mem += data->num_codes * sizeof (*vals) +
+      (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *);
+
+  fcode[0] = values[0] = &vals[0];
+  FIXUP (&values[0]);
+  for (i = 1; i <= data->maxcodelen; i++)
+    {
+      fcode[i] = values[i] = &vals[(values[i - 1] - vals) + data->lencount[i - 1]];
+      FIXUP (&values[i]);
+    }
+
+  for (i = 0; i < data->num_codes; i++)
+    if (data->clens[i])
+      *fcode[(int) (data->clens[i])]++ = i;
+  return (values);
+}
+
+
+
+static void 
+load_comp_dict (char *filename)
+{
+  FILE *dict;
+  int which;
+  compression_dict *cd;
+
+  cd = getmem (sizeof (compression_dict), sizeof (u_char *));
+  cd->fast_loaded = 1;
+
+  dict = open_file (filename, TEXT_DICT_SUFFIX, "rb",
+		    MAGIC_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  Read_cdh (dict, &cd->cdh, NULL, NULL);
+
+  for (which = 0; which < 2; which++)
+    switch (cd->cdh.dict_type)
+      {
+      case MG_COMPLETE_DICTIONARY:
+	{
+	  cd->cfh[which] = getmem (sizeof (*cd->cfh[which]), sizeof (u_char *));
+	  cd->MemForCompDict += sizeof (*cd->cfh[which]);
+	  Read_cfh (dict, cd->cfh[which], &cd->MemForCompDict, NULL);
+
+	  cd->values[which] = ReadInWords (dict, cd, cd->cfh[which], NULL);
+	  FIXUP (&cd->cfh[which]);
+	  FIXUP (&cd->values[which]);
+	  cd->escape[which] = NULL;
+	}
+	break;
+      case MG_PARTIAL_DICTIONARY:
+	{
+	  huff_data *hd;
+	  u_long **vals;
+	  if (cd->cdh.num_words[which])
+	    {
+	      cd->cfh[which] = getmem (sizeof (*cd->cfh[which]), sizeof (u_char *));
+	      cd->MemForCompDict += sizeof (*cd->cfh[which]);
+	      Read_cfh (dict, cd->cfh[which], &cd->MemForCompDict, NULL);
+	      cd->values[which] = ReadInWords (dict, cd, cd->cfh[which],
+					       &cd->escape[which]);
+	      FIXUP (&cd->cfh[which]);
+	      FIXUP (&cd->values[which]);
+	      FIXUP (&cd->escape[which]);
+	    }
+
+	  hd = getmem (sizeof (huff_data), sizeof (char *));
+	  cd->MemForCompDict += sizeof (huff_data);
+	  Read_Huffman_Data (dict, hd, &cd->MemForCompDict, NULL);
+	  vals = Generate_Fast_Huffman_Vals (hd, &cd->MemForCompDict);
+	  cd->chars_huff[which] = hd;
+	  FIXUP (&cd->chars_huff[which]);
+	  cd->chars_vals[which] = vals;
+	  FIXUP (&cd->chars_vals[which]);
+	  if (hd->clens)
+	    Xfree (hd->clens);
+	  hd->clens = NULL;
+
+	  hd = getmem (sizeof (huff_data), sizeof (char *));
+	  cd->MemForCompDict += sizeof (huff_data);
+	  Read_Huffman_Data (dict, hd, &cd->MemForCompDict, NULL);
+	  vals = Generate_Fast_Huffman_Vals (hd, &cd->MemForCompDict);
+	  cd->lens_huff[which] = hd;
+	  FIXUP (&cd->lens_huff[which]);
+	  cd->lens_vals[which] = vals;
+	  FIXUP (&cd->lens_vals[which]);
+	  if (hd->clens)
+	    Xfree (hd->clens);
+	  hd->clens = NULL;
+	}
+	break;
+      case MG_SEED_DICTIONARY:
+	{
+	  huff_data *hd;
+	  u_long **vals;
+	  if (cd->cdh.num_words[which])
+	    {
+	      cd->cfh[which] = getmem (sizeof (*cd->cfh[which]), sizeof (u_char *));
+	      cd->MemForCompDict += sizeof (*cd->cfh[which]);
+	      Read_cfh (dict, cd->cfh[which], &cd->MemForCompDict, NULL);
+	      cd->values[which] = ReadInWords (dict, cd, cd->cfh[which],
+					       &cd->escape[which]);
+	      FIXUP (&cd->cfh[which]);
+	      FIXUP (&cd->values[which]);
+	      FIXUP (&cd->escape[which]);
+	    }
+	  switch (cd->cdh.novel_method)
+	    {
+	    case MG_NOVEL_HUFFMAN_CHARS:
+	      hd = getmem (sizeof (huff_data), sizeof (char *));
+	      cd->MemForCompDict += sizeof (huff_data);
+	      Read_Huffman_Data (dict, hd, &cd->MemForCompDict, NULL);
+	      vals = Generate_Fast_Huffman_Vals (hd, &cd->MemForCompDict);
+	      cd->chars_huff[which] = hd;
+	      FIXUP (&cd->chars_huff[which]);
+	      cd->chars_vals[which] = vals;
+	      FIXUP (&cd->chars_vals[which]);
+	      if (hd->clens)
+		Xfree (hd->clens);
+	      hd->clens = NULL;
+
+	      hd = getmem (sizeof (huff_data), sizeof (char *));
+	      cd->MemForCompDict += sizeof (huff_data);
+	      Read_Huffman_Data (dict, hd, &cd->MemForCompDict, NULL);
+	      vals = Generate_Fast_Huffman_Vals (hd, &cd->MemForCompDict);
+	      cd->lens_huff[which] = hd;
+	      FIXUP (&cd->lens_huff[which]);
+	      cd->lens_vals[which] = vals;
+	      FIXUP (&cd->lens_vals[which]);
+	      if (hd->clens)
+		Xfree (hd->clens);
+	      hd->clens = NULL;
+	      break;
+	    case MG_NOVEL_BINARY:
+	      break;
+	    case MG_NOVEL_DELTA:
+	      break;
+	    case MG_NOVEL_HYBRID:
+	      break;
+	    case MG_NOVEL_HYBRID_MTF:
+	      break;
+	    }
+	  break;
+	}
+      }
+  fclose (dict);
+
+
+  if (cd->cdh.novel_method == MG_NOVEL_BINARY ||
+      cd->cdh.novel_method == MG_NOVEL_DELTA ||
+      cd->cdh.novel_method == MG_NOVEL_HYBRID ||
+      cd->cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+    {
+      cd->ad = LoadAuxDict (&cd->cdh, filename);
+      FIXUP (&cd->ad);
+    }
+}
+
+
+static void 
+save_fast_dict (char *filename)
+{
+  FILE *fdict;
+
+  fdict = create_file (filename, TEXT_DICT_FAST_SUFFIX, "wb",
+		       MAGIC_FAST_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  {
+    u_long *p;
+    for (p = buffer; (u_long) p < (u_long) cur; p++)
+      {
+	if (IS_FIXUP (p))
+	  HTONUL(*p);
+      }
+  }
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(mem);
+  HTONUL(fixup_mem);
+
+  fwrite (&mem, sizeof (mem), 1, fdict);
+  fwrite (&fixup_mem, sizeof (fixup_mem), 1, fdict);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(mem);
+  NTOHUL(fixup_mem);
+
+  fwrite (buffer, sizeof (u_char), mem, fdict);
+  fwrite (fixup, sizeof (u_char), fixup_mem, fdict);
+
+  fclose (fdict);
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_files.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_files.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_files.c	(revision 14757)
@@ -0,0 +1,261 @@
+/**************************************************************************
+ *
+ * mg_files.c -- Routines for handling files for the auxillary programs
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "messages.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+
+
+/* This must contain a valid path without a trailing slash */
+static char *basepath = NULL;
+
+
+
+/* This sets the base path for all file operations */
+void 
+set_basepath (const char *bp)
+{
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+  basepath = "";
+#else
+  char *s;
+  /* Free the memory for the base path if it has already been allocated */
+  if (basepath)
+    {
+      Xfree (basepath);
+      basepath = NULL;
+    }
+
+  if (!bp || *bp == '\0')
+    bp = ".";
+
+  s = strrchr (bp, '/');
+  if (s && *(s + 1) == '\0')
+    {
+      basepath = Xmalloc (strlen (bp) + 2);
+      if (!basepath)
+	return;
+      strcpy (basepath, bp);
+      strcat (basepath, ".");
+    }
+  else
+    basepath = Xstrdup (bp);
+#endif
+}
+
+
+
+/* return the currently defined basepath */
+char *
+get_basepath (void)
+{
+  if (!basepath)
+    set_basepath (getenv ("MGDATA"));
+  return basepath;
+}
+
+
+
+/* This generates the name of a file. It places the name in the buffer
+   specified or if that is NULL it uses a static buffer. */
+char *
+make_name (const char *name, const char *suffix, char *buffer)
+{
+  static char path[512];
+  if (!buffer)
+    buffer = path;
+  if (!basepath)
+    set_basepath (getenv ("MGDATA"));
+  sprintf (buffer, FILE_NAME_FORMAT, basepath, name, suffix);  /* [RPAP - Feb 97: WIN32 Port] */
+  return buffer;
+}
+
+
+
+/* This will open the specified file and check its magic number.
+   Mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *
+open_named_file (const char *name, const char *mode,
+		 u_long magic_num, int err_mode)
+{
+  unsigned long magic;
+  FILE *f = NULL;
+  char *err;
+  f = fopen (name, mode);
+
+  if (!f)
+    {
+      err = "Unable to open \"%s\"";
+      goto error;
+    }
+
+  if (magic_num)
+    {
+      if (fread (&magic, sizeof (magic), 1, f) != 1)
+	{
+	  err = "No magic number \"%s\"";
+	  goto error;
+	}
+
+      NTOHUL(magic);  /* [RPAP - Jan 97: Endian Ordering] */
+
+      if (!IS_MAGIC (magic))
+	{
+	  err = "No MG magic number \"%s\"";
+	  goto error;
+	}
+
+      if (magic != magic_num)
+	{
+	  err = "Wrong MG magic number \"%s\"";
+	  goto error;
+	}
+    }
+  return f;
+
+error:
+  if (f)
+    fclose (f);
+  if (err_mode == MG_ABORT)
+    FatalError (1, err, name);
+  if (err_mode == MG_MESSAGE)
+    Message (err, name);
+  return NULL;
+}
+
+
+
+/* This will open the specified file and check its magic number.
+   Mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *
+open_file (const char *name, const char *suffix, const char *mode,
+	   u_long magic_num, int err_mode)
+{
+  char path[512];
+  if (!basepath)
+    set_basepath (getenv ("MGDATA"));
+  sprintf (path, FILE_NAME_FORMAT, basepath, name, suffix);  /* [RPAP - Feb 97: WIN32 Port] */
+  return open_named_file (path, mode, magic_num, err_mode);
+}
+
+
+
+
+
+
+/* This will create the specified file and set its magic number.
+
+   Mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *
+create_named_file (const char *name, const char *mode,
+		   u_long magic_num, int err_mode)
+{
+  FILE *f = NULL;
+  char *err;
+  f = fopen (name, mode);
+
+  if (!f)
+    {
+      err = "Unable to open \"%s\"";
+      goto error;
+    }
+
+  if (magic_num)
+    HTONUL(magic_num);  /* [RPAP - Jan 97: Endian Ordering] */
+    if (fwrite (&magic_num, sizeof (magic_num), 1, f) != 1)
+      {
+	err = "Couldn't write magic number \"%s\"";
+	goto error;
+      }
+
+  return f;
+
+error:
+  if (f)
+    fclose (f);
+  if (err_mode == MG_ABORT)
+    FatalError (1, err, name);
+  if (err_mode == MG_MESSAGE)
+    Message (err, name);
+  return NULL;
+}
+
+
+
+
+
+
+
+/* This will create the specified file and set its magic number.
+
+   Mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *
+create_file (const char *name, const char *suffix, const char *mode,
+	     u_long magic_num, int err_mode)
+{
+  char path[512];
+  if (!basepath)
+    set_basepath (getenv ("MGDATA"));
+  sprintf (path, FILE_NAME_FORMAT, basepath, name, suffix);  /* [RPAP - Feb 97: WIN32 Port] */
+  return create_named_file (path, mode, magic_num, err_mode);
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_files.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_files.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_files.h	(revision 14757)
@@ -0,0 +1,329 @@
+/**************************************************************************
+ *
+ * mg_files.h -- Routines for handling files for the auxillary programs
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef MG_FILES_H
+#define MG_FILES_H
+
+#include "sysfuncs.h"
+
+/* Magic numbers for the different types of files */
+
+#define GEN_MAGIC(a,b,c,d) ((unsigned long)(((a)<<24) + ((b)<<16) + \
+					    ((c)<<8) + (d)))
+
+#define MAGIC_XXXX		GEN_MAGIC('M','G', 0 , 0)
+#define MAGIC_STATS_DICT	GEN_MAGIC('M','G','S','D')
+#define MAGIC_AUX_DICT		GEN_MAGIC('M','G','A','D')
+#define MAGIC_FAST_DICT		GEN_MAGIC('M','G','F','D')
+#define MAGIC_DICT		GEN_MAGIC('M','G','D', 0 )
+#define MAGIC_STEM_BUILD	GEN_MAGIC('M','G','S', 0 )
+#define MAGIC_HASH		GEN_MAGIC('M','G','H', 0 )
+#define MAGIC_STEM		GEN_MAGIC('M','G','s', 0 )
+#define MAGIC_CHUNK		GEN_MAGIC('M','G','C', 0 )
+#define MAGIC_CHUNK_TRANS	GEN_MAGIC('M','G','c', 0 )
+#define MAGIC_TEXT		GEN_MAGIC('M','G','T', 0 )
+#define MAGIC_TEXI		GEN_MAGIC('M','G','t', 0 )
+#define MAGIC_TEXI_WGT		GEN_MAGIC('M','G','t','W')
+#define MAGIC_INVF		GEN_MAGIC('M','G','I', 0 )
+#define MAGIC_INVI		GEN_MAGIC('M','G','i', 0 )
+#define MAGIC_WGHT		GEN_MAGIC('M','G','W', 0 )
+#define MAGIC_WGHT_APPROX	GEN_MAGIC('M','G','w', 0 )
+#define MAGIC_PARAGRAPH		GEN_MAGIC('M','G','P', 0 )
+/* [RPAP - Jan 97: Stem Index Change] */
+#define MAGIC_STEM_1            GEN_MAGIC('M','G','s','1')
+#define MAGIC_STEM_2            GEN_MAGIC('M','G','s','2')
+#define MAGIC_STEM_3            GEN_MAGIC('M','G','s','3')
+
+#define IS_MAGIC(a) ((((u_long)(a)) & 0xffff0000) == MAGIC_XXXX)
+
+
+/* err_mode values for open_file and create_file */
+#define MG_ABORT 0
+#define MG_MESSAGE 1
+#define MG_CONTINUE 2
+
+
+
+
+
+/* File suffixes */
+
+
+/* The compression dictionary built by txt.pass1 */
+#ifdef SHORT_SUFFIX
+# define TEXT_STATS_DICT_SUFFIX	 ".tsd"
+#else
+# define TEXT_STATS_DICT_SUFFIX	 ".text.stats"
+#endif
+
+/* The compression dictionary built by text.pass1 and comp_dict.process */
+#ifdef SHORT_SUFFIX
+# define TEXT_DICT_SUFFIX	 ".td"
+#else
+# define TEXT_DICT_SUFFIX	 ".text.dict"
+#endif
+
+/* The compression dictionary built by mg_make_fast_dict */
+#ifdef SHORT_SUFFIX
+# define TEXT_DICT_FAST_SUFFIX	 ".tdf"
+#else
+# define TEXT_DICT_FAST_SUFFIX	 ".text.dict.fast"
+#endif
+
+/* The auxilary dictionary built by text.pass2 */
+#ifdef SHORT_SUFFIX
+# define TEXT_DICT_AUX_SUFFIX	 ".tda"
+#else
+# define TEXT_DICT_AUX_SUFFIX	 ".text.dict.aux"
+#endif
+
+/* The compressed text build by text.pass2 */
+#ifdef SHORT_SUFFIX
+# define TEXT_SUFFIX		 ".t"
+#else
+# define TEXT_SUFFIX		 ".text"
+#endif
+
+/* The combined compressed text index and document weight file */
+#ifdef SHORT_SUFFIX
+# define TEXT_IDX_WGT_SUFFIX	 ".tiw"
+#else
+# define TEXT_IDX_WGT_SUFFIX	 ".text.idx.wgt"
+#endif
+
+/* The compressed text index file */
+#ifdef SHORT_SUFFIX
+# define TEXT_IDX_SUFFIX	 	".ti"
+#else
+# define TEXT_IDX_SUFFIX	 	".text.idx"
+#endif
+
+/* The dictionary of stemmed words build by invf.pass1 and ivf.pass1 */
+#ifdef SHORT_SUFFIX
+# define INVF_DICT_SUFFIX         ".id"
+#else
+# define INVF_DICT_SUFFIX         ".invf.dict"
+#endif
+
+/* The dictionary of stemmed words build by stem.process */
+#ifdef SHORT_SUFFIX
+# define INVF_DICT_BLOCKED_SUFFIX ".idb"
+#else
+# define INVF_DICT_BLOCKED_SUFFIX ".invf.dict.blocked"
+#endif
+
+/* The exact document weights file build by make.weights, invf.pass2,
+   or ivf.pass2 */
+#ifdef SHORT_SUFFIX
+# define WEIGHTS_SUFFIX           ".w"
+#else
+# define WEIGHTS_SUFFIX           ".weight"
+#endif
+
+/* The approximate weights file built by make.weights */
+#ifdef SHORT_SUFFIX
+# define APPROX_WEIGHTS_SUFFIX    ".wa"
+#else
+# define APPROX_WEIGHTS_SUFFIX    ".weight.approx"
+#endif
+
+/* The inverted file build by invf.pass2 or ivf.pass2 */
+#ifdef SHORT_SUFFIX
+# define INVF_SUFFIX              ".i"
+#else
+# define INVF_SUFFIX              ".invf"
+#endif
+
+/* The inverted file index build by invf.pass2 or ivf.pass2 */
+#ifdef SHORT_SUFFIX
+# define INVF_IDX_SUFFIX          ".ii"
+#else
+# define INVF_IDX_SUFFIX          ".invf.idx"
+#endif
+
+/* The inverted file chunk descriptor built by ivf.pass1 */
+#ifdef SHORT_SUFFIX
+# define INVF_CHUNK_SUFFIX        ".ic"
+#else
+# define INVF_CHUNK_SUFFIX        ".invf.chunk"
+#endif
+
+/* The word index translation file built by ivf.pass1 */
+#ifdef SHORT_SUFFIX
+# define INVF_CHUNK_TRANS_SUFFIX  ".ict"
+#else
+# define INVF_CHUNK_TRANS_SUFFIX  ".invf.chunk.trans"
+#endif
+
+/* The hashed stemmed dictionary built by make.perf_hash */
+#ifdef SHORT_SUFFIX
+# define INVF_DICT_HASH_SUFFIX    ".idh"
+#else
+# define INVF_DICT_HASH_SUFFIX    ".invf.dict.hash"
+#endif
+
+/* The paragraph descriptior file built by invf.pass1 or ivf.pass1 */
+#ifdef SHORT_SUFFIX
+# define INVF_PARAGRAPH_SUFFIX    ".ip"
+#else
+# define INVF_PARAGRAPH_SUFFIX    ".invf.paragraph"
+#endif
+
+/* The trace file build by mg.builder. */
+#ifdef SHORT_SUFFIX
+# define TRACE_SUFFIX             ".trc"
+#else
+# define TRACE_SUFFIX             ".trace"
+#endif
+
+/* The compression stats file build by mg.builder. */
+#ifdef SHORT_SUFFIX
+# define COMPRESSION_STATS_SUFFIX ".cs"
+#else
+# define COMPRESSION_STATS_SUFFIX ".compression.stats"
+#endif
+
+/* [RPAP - Jan 97: Stem Index Change] */
+/* The casefolded index into the stemmed dictionary */
+#ifdef SHORT_SUFFIX
+# define INVF_DICT_BLOCKED_1_SUFFIX ".ib1"
+#else
+# define INVF_DICT_BLOCKED_1_SUFFIX ".invf.dict.blocked.1"
+#endif
+
+/* [RPAP - Jan 97: Stem Index Change] */
+/* The stemmed index into the stemmed dictionary */
+#ifdef SHORT_SUFFIX
+# define INVF_DICT_BLOCKED_2_SUFFIX ".ib2"
+#else
+# define INVF_DICT_BLOCKED_2_SUFFIX ".invf.dict.blocked.2"
+#endif
+
+/* [RPAP - Jan 97: Stem Index Change] */
+/* The casefolded and stemmed  index into the stemmed dictionary */
+#ifdef SHORT_SUFFIX
+# define INVF_DICT_BLOCKED_3_SUFFIX ".ib3"
+#else
+# define INVF_DICT_BLOCKED_3_SUFFIX ".invf.dict.blocked.3"
+#endif
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+#define FILE_NAME_FORMAT "%s%s%s"
+#else
+#define FILE_NAME_FORMAT "%s/%s%s"
+#endif
+
+
+/* This sets the base path for all file operations */
+void set_basepath (const char *bp);
+
+
+/* return the currently defined basepath */
+char *get_basepath (void);
+
+
+
+
+/* This generates the name of a file. It places the name in the buffer
+   specified or if that is NULL it uses a static buffer. */
+char *make_name (const char *name, const char *suffix, char *buffer);
+
+
+
+
+
+
+
+/* This will open the specified file and check its magic number.
+   Mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *open_named_file (const char *name, const char *mode,
+		       u_long magic_num, int err_mode);
+
+
+
+
+/* This will open the specified file and check its magic number.
+
+   err_mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *open_file (const char *name, const char *suffix, const char *mode,
+		 u_long magic_num, int err_mode);
+
+
+
+
+
+/* This will create the specified file and set its magic number.
+
+   Mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *create_named_file (const char *name, const char *mode,
+			 u_long magic_num, int err_mode);
+
+
+
+/* This will create the specified file and set its magic number.
+
+   err_mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *create_file (const char *name, const char *suffix, const char *mode,
+		   u_long magic_num, int err_mode);
+
+
+
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/mg_hilite_words.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_hilite_words.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_hilite_words.1	(revision 14757)
@@ -0,0 +1,95 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_hilite_words 1 \*(Dt CITRI
+.SH NAME
+mg_hilite_words \- display text and highlight particular words which it contains
+.SH SYNOPSIS
+.B mg_hilite_words
+.if n .ti +9n
+[
+.B --stem_method [0-3]
+]
+.if n .ti +9n
+[
+.B --stemmer [english|lovin|french|simplefrench]
+]
+.if n .ti +9n
+[
+.B --style [bold|underline|italic|emphasis|strong]
+]
+.if n .ti +9n
+[
+.B --pager [less|more|html|???]
+]
+.if n .ti +9n
+.I list-of-words-to-highlight
+
+.SH DESCRIPTION
+.B mg_hilite_words
+reads text from stdin and outputs it into a pager such as
+less. It's command arguments include a list of stemmed words
+which if extracted from the text will be highlighted on the output
+using a highlighting style.
+
+It has been extended to output the highlighted text using html
+straight to stdout.
+
+.SH OPTIONS
+Options may appear in any order, but the
+.IR list-of-words-to-highlight ,
+must be last.
+.TP
+.B --stem_method [0-3]
+This option allows one to set the stemming method for the extraction of
+the words from the incoming text.
+This should match the way the inverted file index was created.
+The default is 3, which is fold and stem.
+.TP
+.B --stemmer [english|lovin|french|simplefrench]
+This option allows you to select the stemmer to use.  The
+default is the English stemmer.
+.TP
+.B --style [bold|underline|italic|emphasis|strong]
+This option sets the highlighting style.
+.IR Bold 
+and 
+.IR underline
+are utilised by the pager or for html output.
+.IR Italic,
+.IR emphasis,
+and
+.IR strong
+can only be used for html output.
+.TP
+.B --pager [less|more|html|???]
+One can use the standard 
+.IR less
+or
+.IR more
+pages for displaying the highlighted text.
+Or one can generate highlighted html using the paging setting of
+.IR html.
+One can also specify a custom pager of their own choosing (i.e. ???).
+.TP
+.B list-of-words-to-highlight
+Each word is taken as a command line argument.
+Each word should already be stemmed and folded according to
+the stem option.
+.SH USAGE
+This program was written primarily to be called by 
+.IR mgquery(1)
+.
+When the user selects the mode of "hilite" then this program
+is called for displaying the query-result documents instead of
+just the pager.
+.SH "SEE ALSO"
+.na
+.BR mgquery (1).
+
+
Index: /indexers/branches/3.03a/mg/src/text/mg_hilite_words.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_hilite_words.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_hilite_words.c	(revision 14757)
@@ -0,0 +1,693 @@
+/**************************************************************************
+ *
+ * mg_hilite_words -- display text and highlight particular words which 
+ *                    it contains
+ * Copyright (C) 1994 Tim Shimmin
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+static char *RCSID = "$Id$";
+
+#include "sysfuncs.h"
+
+#include "getopt.h"
+#include "messages.h"
+#include "local_strings.h"
+#include "stemmer.h"
+#include "words.h"
+
+
+/*
+ * Description
+ * -----------
+ *   Hilite_words reads text from stdin and outputs it into a pager such as
+ *   less. It's command arguments include a list of stemmed words 
+ *   which if extracted from the text will be highlighted on the output.
+ *
+ * Implementation
+ * --------------
+ *   Extracting of words - using PARSE_STEM_WORD & stemmer
+ *   
+ *   Highlighting of words - for standard pager:
+ *                             using back-space character code
+ *                             e.g. bolded a = "a\ba", underlined a = "_\ba"
+ *                         - for pager==html:
+ *                             use some of the standard html character 
+ *                             formatting tags
+ *
+ *   Storage of words - using hashtable (set) of size equalling a constant
+ *                      times the number of words
+ * 
+ * Usage
+ * -----
+ *   mg_hilite_words --stem_method [0-3] 
+ *                   --style [bold|underline|italic|emphasis|strong]
+ *                   --pager [less|more|html|???]
+ *                   --terminator [terminator-string]
+ *                   list-of-words-to-highlight
+ */
+
+/*
+ * Modifications:
+ *
+ * 21/Apr/95: To handle outputting html tags to stdout
+ *
+ */
+
+/* --- constants --- */
+
+/* highlighting styles */
+#define HILITE_MAX      5	/* the number of styles */
+#define BOLD 		0
+#define UNDERLINE	1
+#define ITALIC     	2
+#define EMPHASIS     	3
+#define STRONG     	4
+
+/* maximum length of line buffer */
+#define MAX_LINE_BUFFER 200
+
+/* set pager to this to get html hilited text to stdout */
+#define HTML_OUT "html"
+
+/* output types */
+#define PAGER 0
+#define HTML  1
+
+/* --- types --- */
+
+typedef u_char *Word;
+
+/* --- globals --- */
+
+/* keep in synch with constants */
+static char *hilite_names[] =
+{"bold", "underline", "italic", "emphasis", "strong"};
+static char *hilite_tags[] =
+{"B", "", "I", "EM", "STRONG"};
+static short hilite_style = BOLD;
+static char *pager = "less";
+static int stemmer_num = 0;	/* Lovin's stemmer */
+static int stem_method = 3;	/* fold & stem */
+static char **word_list;
+static int num_of_words = 0;
+static int output_type = PAGER;
+static char *terminator = NULL;
+
+/* --- prototypes --- */
+
+static Word copy_c_word (char *w);
+static void process_words (char **words, int num_of_words);
+static int get_line (u_char * line, int n, FILE * stream);
+static void process_text (FILE * input_file, FILE * output_file);
+static void copy_word (u_char * w1, u_char * w2);
+static void process_buffer (u_char * s_in, int len, FILE * output_file);
+static void output_word (u_char * s_start, u_char * s_finish, FILE * output_file);
+static void output_hilite_word (u_char * s_start, u_char * s_finish,
+				FILE * output_file);
+static void process_args (int argc, char *argv[]);
+static void print_line (u_char * line, int n, FILE * stream);
+
+
+/******************************** word set ************************************/
+
+#include "hash.h"
+#include "locallib.h"
+
+#define SIZE_FACTOR 2
+
+typedef Word *WordSet;
+static WordSet set_of_words = NULL;
+static int hash_size = 0;
+
+/* prototypes - set routines */
+static void set_create (int num_of_words);
+static void set_add (Word word);
+static int set_member (Word word);
+static void set_print (void);
+
+/* =========================================================================
+ * Function: set_print
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+set_print (void)
+{
+  int i = 0;
+
+  for (i = 0; i < hash_size; i++)
+    {
+      Word word = set_of_words[i];
+
+      if (word)
+	{
+	  int len = *word++;
+
+	  fprintf (stderr, "[%d] = ", i);
+	  while (len--)
+	    fputc (*word++, stderr);
+	  fputc ('\n', stderr);
+	}
+    }
+
+}
+
+
+/* =========================================================================
+ * Function: set_create
+ * Description: 
+ *      Allocate memory for the set
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+set_create (int num_of_words)
+{
+  WordSet set;
+
+  hash_size = prime (num_of_words * SIZE_FACTOR);
+  set = (WordSet) malloc (hash_size * sizeof (Word));
+  if (!set)
+    FatalError (1, "Runout of memory for word hashtable");
+  bzero ((char *) set, hash_size * sizeof (Word));  /* [RPAP - Feb 97: WIN32 Port] */
+
+  set_of_words = set;
+
+}
+
+/* =========================================================================
+ * Function: set_add
+ * Description: 
+ *      Add a string element to the set.
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+set_add (Word word)
+{
+  int hash_val;
+  int hash_step;
+
+  HASH (hash_val, hash_step, word, hash_size);
+
+  /* loop around in case of collisions and need to step */
+  while (1)
+    {
+
+      Word entry = set_of_words[hash_val];
+
+      /* if doesn't exist then */
+      if (!entry)
+	{
+	  set_of_words[hash_val] = word;
+	  break;
+	}
+
+      /* if we have a matching word */
+      if (compare (entry, word) == 0)
+	break;
+
+      /* if collides with a different word */
+      hash_val = (hash_val + hash_step) % hash_size;
+
+    }
+}
+
+
+/* =========================================================================
+ * Function: set_member
+ * Description: 
+ *      Tests whether a string is a member of the set
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static int
+set_member (Word word)
+{
+  int hash_val;
+  int hash_step;
+
+  HASH (hash_val, hash_step, word, hash_size);
+
+  /* loop around in case of collisions and need to step */
+  while (1)
+    {
+
+      Word entry = set_of_words[hash_val];
+
+      /* if doesn't exist then */
+      if (!entry)
+	return 0;
+
+      /* if we have a matching word */
+      if (compare (entry, word) == 0)
+	return 1;
+
+      /* if collides with a different word */
+      hash_val = (hash_val + hash_step) % hash_size;
+
+    }
+}
+
+/******************************** end of word set ******************************/
+
+
+
+/* =========================================================================
+ * Function: copy_c_word
+ * Description: 
+ *      Allocate enough memory and copy word over
+ * Input: 
+ *      w = null terminated string (c_word)
+ * Output: 
+ *      word with length in 1st byte
+ * ========================================================================= */
+
+static Word
+copy_c_word (char *w)
+{
+  int len = strlen (w);
+  Word w_copy = (Word) malloc (len + 1);
+  Word w_ptr = NULL;
+  int j = 0;
+
+  if (!w_copy)
+    FatalError (1, "Not enough memory to copy a word");
+
+  w_copy[0] = len;
+  w_ptr = w_copy + 1;
+  for (j = 0; j < len; j++)
+    *w_ptr++ = *w++;
+
+  return w_copy;
+}
+
+/* =========================================================================
+ * Function: process_words
+ * Description: 
+ *      Go through the stemmed words and add to word set
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+process_words (char **words, int num_of_words)
+{
+  int i = 0;
+
+  set_create (num_of_words);
+
+  for (i = 0; i < num_of_words; i++)
+    {
+      Word word = copy_c_word (words[i]);
+      set_add (word);
+    }
+
+}
+
+/* =========================================================================
+ * Function: get_line
+ * Description: 
+ *      Equivalent of fgets for u_char*.
+ *      But returns length of read-in line.
+ *      Expects to see a '\n' before an EOF
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static int
+get_line (u_char * line, int n, FILE * stream)
+{
+  int i = 0;
+  int ch = '\0';
+
+  while (1)
+    {
+      if (i == n)
+	return i;
+
+      ch = fgetc (stream);
+
+      if (ch == EOF)
+	{
+	  if (!feof (stream))
+	    FatalError (1, "Error on reading a line from stdin");
+	  return EOF;
+	}
+
+      if (ch == '\n')
+	return i;
+
+      *line++ = ch;
+      i++;
+    }
+
+}
+
+/* =========================================================================
+ * Function: print_line
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+print_line (u_char * line, int n, FILE * stream)
+{
+
+  while (n--)
+    {
+      fputc (*line++, stream);
+    }
+  fputc ('\n', stream);
+
+}
+
+/* =========================================================================
+ * Function: process_text
+ * Description: 
+ *      Go through the text from input_file and highlight to output_file 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+process_text (FILE * input_file, FILE * output_file)
+{
+  static u_char line_buffer[MAX_LINE_BUFFER];
+
+
+  while (1)
+    {
+      int len = get_line (line_buffer, MAX_LINE_BUFFER, input_file);
+
+      if (len == EOF)
+	break;
+      process_buffer (line_buffer, len, output_file);
+
+    }
+}
+
+/* =========================================================================
+ * Function: copy_word
+ * Description: 
+ *      Copies w2 into w1. Assumes both have storage allocated.
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+copy_word (u_char * w1, u_char * w2)
+{
+  int i;
+  int len = w2[0];
+
+  for (i = 0; i <= len; i++)
+    *w1++ = *w2++;
+
+}
+
+/* =========================================================================
+ * Function: process_buffer
+ * Description: 
+ *      Parse & stem words of line buffer
+ *      Based on the usage of PARSEing in other mg files.
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+static void
+process_buffer (u_char * s_in, int len, FILE * output_file)
+{
+  u_char *end = s_in + len - 1;
+  u_char *s_start = NULL;
+
+  if (!inaword (s_in, end))
+    {
+      s_start = s_in;
+      PARSE_NON_STEM_WORD (s_in, end);
+      output_word (s_start, s_in - 1, output_file);
+    }
+
+  while (s_in <= end)
+    {
+      u_char word[MAXSTEMLEN + 1];
+
+      s_start = s_in;
+      PARSE_STEM_WORD (word, s_in, end);
+
+      stemmer (stem_method, stemmer_num, word);
+
+      if (set_member (word))	/* output with highlighting */
+	{
+	  output_hilite_word (s_start, s_start + word[0] - 1, output_file);
+	  s_start += word[0];	/* step over hilited output */
+	}
+      output_word (s_start, s_in - 1, output_file);
+
+      s_start = s_in;
+      PARSE_NON_STEM_WORD (s_in, end);
+      output_word (s_start, s_in - 1, output_file);
+
+    }				/*while */
+
+  fputc ('\n', output_file);
+  fflush (output_file);
+
+}				/*process_buffer */
+
+/* =========================================================================
+ * Function: output_word
+ * Description: 
+ *      Output a word which lies from s_start to s_finish in buffer
+ * Input: 
+ *      s_start = ptr to 1st char
+ *      s_finish = ptr to last char
+ * Output: 
+ * ========================================================================= */
+
+static void
+output_word (u_char * s_start, u_char * s_finish, FILE * output_file)
+{
+  while (s_start <= s_finish)
+    {
+      fputc (*s_start++, output_file);
+    }
+}
+
+
+/* =========================================================================
+ * Function: output_hilite_word
+ * Description: 
+ *      Highlight a word (with length in 1st byte)
+ *      Pager highlighting:
+ *        Highlighting is either by bolding or underlining using
+ *        the method used by UNIX utilities More(1) and Less(1)
+ *      HTML highlighting:
+ *        use the appropriate start and end tags around the word
+ * ========================================================================= */
+
+static void
+output_hilite_word (u_char * s_start, u_char * s_finish, FILE * output_file)
+{
+
+  if (output_type == HTML)
+    {
+      char *hilite_tag = hilite_tags[hilite_style];
+
+      /* print start tag */
+      fprintf (output_file, "<%s>", hilite_tag);
+
+      output_word (s_start, s_finish, output_file);
+
+      /* print end tag */
+      fprintf (output_file, "</%s>", hilite_tag);
+    }
+
+  else
+    /* PAGER */
+    {
+      /* use backspaces around each letter */
+      while (s_start <= s_finish)
+	{
+	  switch (hilite_style)
+	    {
+	    case BOLD:
+	      fputc (*s_start, output_file);
+	      fputc ('\b', output_file);
+	      fputc (*s_start, output_file);
+	      break;
+	    case UNDERLINE:
+	      fputc ('_', output_file);
+	      fputc ('\b', output_file);
+	      fputc (*s_start, output_file);
+	      break;
+	    default:
+	      fputc (*s_start, output_file);
+	    }
+	  s_start++;
+	}			/*while */
+    }
+}
+
+/* =========================================================================
+ * Function: process_args
+ * Description: 
+ *      sets the global variables:
+ *              hilite_style, pager, num_of_words, word_list
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+struct option long_opts[] =
+{
+  {"style", required_argument, 0, 's'},
+  {"terminator", required_argument, 0, 't'},
+  {"pager", required_argument, 0, 'p'},
+  {"stem_method", required_argument, 0, 'm'},
+  {"stemmer", required_argument, 0, 'a'},
+  {0, 0, 0, 0}
+};
+
+static void
+process_args (int argc, char *argv[])
+{
+  int ch;
+
+
+  opterr = 0;
+  while ((ch = getopt_long (argc, argv, "s:p:t:m:a:", long_opts, (int *) 0)) != -1)
+    {
+      switch (ch)
+	{
+	case 's':
+	  {
+	    int i;
+	    for (i = 0; i < HILITE_MAX; i++)
+	      if (strcmp (optarg, hilite_names[i]) == 0)
+		break;
+
+	    if (i < HILITE_MAX)
+	      hilite_style = i;
+	  }
+	  break;
+	case 'a':
+	  stemmer_num = stemmernumber (optarg);
+	  break;
+	case 't':
+	  terminator = optarg;
+	  break;
+	case 'm':
+	  stem_method = atoi (optarg);
+	  break;
+	case 'p':
+	  pager = optarg;
+	  break;
+	default:
+	  FatalError (1, "Usage: \n"
+		      "mg_hilite_words --stem_method [0-3]\n"
+	  "                --stemmer [english|lovin|french|simplefrench]\n"
+	  "                --style [bold|underline|italic|emphasis|strong]\n"
+		      "                --pager [less|more|html|???]\n");
+	}
+    }
+
+  num_of_words = argc - optind;
+
+  word_list = &argv[optind];
+
+  /* fix up output type */
+  if (strcmp (pager, HTML_OUT) == 0)
+    output_type = HTML;
+  else
+    output_type = PAGER;
+
+}
+
+/* =========================================================================
+ * Function: main
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+int
+main (int argc, char *argv[])
+{
+  FILE *output = NULL;
+
+  process_args (argc, argv);
+
+  /* set output file */
+  if (output_type == PAGER)
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+    output = _popen (pager, "w");
+#else
+    output = popen (pager, "w");
+#endif
+  else
+    output = stdout;
+
+  if (!output)
+    FatalError (1, "Unable to run \"%s\"\n", pager);
+
+  if (num_of_words < 1)
+    {
+      int ch;
+
+      /* just echo the input */
+      /* better not to call this program at all ;-) */
+      while ((ch = fgetc (stdin)) != EOF)
+	{
+	  fputc (ch, output);
+	}
+    }
+  else
+    {
+      /* set up hash table for words */
+      process_words (word_list, num_of_words);
+
+
+      /* Go thru lines of text from stdin and 
+       * output words with hilite info if
+       * words parse into existence in the hash table 
+       */
+      process_text (stdin, output);
+    }
+
+  if (terminator)
+    fprintf (output, "%s\n", terminator);
+
+  if (output != stdout)
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+    _pclose (output);
+#else
+    pclose (output);
+#endif
+
+  return 0;
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_invf_dict.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_invf_dict.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_invf_dict.1	(revision 14757)
@@ -0,0 +1,104 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_invf_dict 1 \*(Dt CITRI
+.SH NAME
+mg_invf_dict \- build an `on-disk' stemmed dictionary
+.SH SYNOPSIS
+.B mg_invf_dict
+[
+.B \-h
+]
+[
+.B \-F
+]
+[
+.BI \-b " num"
+]
+[
+.BI \-d " directory"
+]
+.if n .ti +9n
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_invf_dict
+builds an `on-disk' stemmed dictionary from the
+compressed stemmed dictionary that the
+.BR mgquery (1)
+program can access.  Each entry in the dictionary contains the disk
+pointer to the associated inverted file entry, and various other pieces
+of information about the stemmed word.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-b " num"
+The dictionary is stored in blocks on disk; this option is used to set
+the block size.  The default is 4-KB blocks.
+.TP
+.B \-F
+This option causes the disk blocks to be aligned on the appropriate
+boundaries.  For example, if 4-KB blocks are used, they will be aligned
+in the file on 4-KB boundaries.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.dict.build
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict
+The `on-disk' stemmed dictionary.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_invf_dict.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_invf_dict.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_invf_dict.c	(revision 14757)
@@ -0,0 +1,347 @@
+/**************************************************************************
+ *
+ * mg_invf_dict.c -- Program to build the blocked stemmed dictionary
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "messages.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "invf.h"
+#include "locallib.h"
+#include "words.h"
+#include "mg.h"
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:08  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:45  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:03  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.4  1994/11/29  00:32:00  tes
+   * Committing the new merged files and changes.
+   *
+   * Revision 1.3  1994/10/20  03:56:56  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:49  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+int block_size = 1024 * 4;
+
+int force = 0;
+
+static void process_files (char *filename);
+
+int main (int argc, char **argv)
+{
+  char *file_name = "";
+  int ch;
+  msg_prefix = argv[0];
+  opterr = 0;
+  msg_prefix = argv[0];
+  while ((ch = getopt (argc, argv, "f:d:b:Fh")) != -1)
+    switch (ch)
+      {
+      case 'f':		/* input file */
+	file_name = optarg;
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 'b':
+	block_size = atoi (optarg);
+	break;
+      case 'F':
+	force = 1;
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-f input_file]"
+		 "[-d data directory] [-b num] [-F] [-h]\n", argv[0]);
+	exit (1);
+      }
+
+  process_files (file_name);
+  return 0;
+}
+
+
+
+
+static void 
+process_files (char *filename)
+{
+  FILE *id, *idb, *tmp, *ii;
+  unsigned long i, pos, num, First_word, invf_ptr, invf_len;
+  unsigned long last_ptr = 0;
+  char *FName;
+  struct invf_dict_header idh;
+  struct stem_dict_header sdh;
+  u_char prev[MAXSTEMLEN + 1];
+  u_char *buffer;
+  unsigned short *pointers;
+  int buf_in_use;
+  unsigned short ptrs_in_use, word_num;
+
+  id = open_file (filename, INVF_DICT_SUFFIX, "rb", MAGIC_STEM_BUILD, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  ii = open_file (filename, INVF_IDX_SUFFIX, "rb", MAGIC_INVI, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  idb = create_file (filename, INVF_DICT_BLOCKED_SUFFIX, "w+b", MAGIC_STEM,
+		     MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  FName = make_name (filename, ".tmp", NULL);
+  if (!(tmp = fopen (FName, "w+b")))  /* [RPAP - Feb 97: WIN32 Port] */
+    FatalError (1, "Unable to open \"%s\".\n", FName);
+
+  /* Delete the file now */
+  unlink (FName);
+
+  fread (&idh, sizeof (idh), 1, id);
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(idh.lookback);
+  NTOHUL(idh.dict_size);
+  NTOHUL(idh.total_bytes);
+  NTOHUL(idh.index_string_bytes);
+  NTOHD(idh.input_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(idh.num_of_docs);
+  NTOHUL(idh.static_num_of_docs);
+  NTOHUL(idh.num_of_words);
+  NTOHUL(idh.stemmer_num);
+  NTOHUL(idh.stem_method);
+
+  sdh.lookback = idh.lookback;
+  sdh.block_size = block_size;
+  sdh.num_blocks = 0;
+  sdh.index_chars = 0;
+  sdh.blocks_start = 0;
+  sdh.num_of_docs = idh.num_of_docs;
+  sdh.static_num_of_docs = idh.static_num_of_docs;
+  sdh.num_of_words = idh.num_of_words;
+  sdh.stemmer_num = idh.stemmer_num;
+  sdh.stem_method = idh.stem_method;
+  sdh.indexed = 0;  /* [RPAP - Jan 97: Stem Index Change] */
+
+  fwrite (&sdh, sizeof (sdh), 1, idb);
+
+  if (!(buffer = Xmalloc (block_size + 512)))
+    FatalError (1, "Unable to allocate memory for \"buffer\"\n");
+  if (!(pointers = Xmalloc (block_size + 512)))
+    FatalError (1, "Unable to allocate memory for \"buffer\"\n");
+
+  buf_in_use = 0;
+  pos = 0;
+  word_num = 0;
+  ptrs_in_use = 0;
+  First_word = 0;
+  for (i = 0; i < idh.dict_size; i++)
+    {
+      register unsigned long extra, copy, suff;
+      unsigned long wcnt, fcnt;
+
+      /* build a new word on top of prev */
+      copy = getc (id);
+      suff = getc (id);
+      *prev = copy + suff;
+      fread (prev + copy + 1, sizeof (u_char), suff, id);
+
+      /* read other data, but no need to store it */
+      fread (&fcnt, sizeof (fcnt), 1, id);
+      fread (&wcnt, sizeof (wcnt), 1, id);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(fcnt);
+      NTOHUL(wcnt);
+
+      /* read in the inverted file position */
+      fread (&invf_ptr, sizeof (invf_ptr), 1, ii);
+      NTOHUL(invf_ptr);  /* [RPAP - Jan 97: Endian Ordering] */
+      if (word_num % idh.lookback == 0)
+	extra = copy + sizeof (*pointers);
+      else
+	extra = 0;
+      if ((ptrs_in_use + 1) * sizeof (*pointers) + sizeof (ptrs_in_use) + extra +
+	  buf_in_use + suff + 1 + sizeof (fcnt) + sizeof (wcnt) +
+	  sizeof (First_word) + sizeof (invf_ptr) + sizeof (invf_len) > block_size)
+	{
+	  int chunk;
+	  invf_len = invf_ptr - last_ptr;
+
+	  /* [RPAP - Jan 97: Endian Ordering] */
+	  HTONUL(First_word);
+	  HTONUL(invf_len);
+	  HTONUS(word_num);
+
+	  fwrite (&First_word, sizeof (First_word), 1, tmp);
+	  fwrite (&invf_len, sizeof (invf_len), 1, tmp);
+	  fwrite (&word_num, sizeof (word_num), 1, tmp);
+	  fwrite (pointers, sizeof (*pointers), ptrs_in_use, tmp);
+	  fwrite (buffer, sizeof (u_char), buf_in_use, tmp);
+	  bzero ((char *) buffer, block_size);
+	  chunk = buf_in_use + ptrs_in_use * sizeof (*pointers) +
+	    sizeof (ptrs_in_use) + sizeof (First_word) + sizeof (invf_len);
+	  if (force && chunk < block_size)
+	    {
+	      fwrite (buffer, sizeof (u_char), block_size - chunk, tmp);
+	      chunk = block_size;
+	    }
+
+	  pos += chunk;
+
+	  buf_in_use = 0;
+	  word_num = 0;
+	  ptrs_in_use = 0;
+	  sdh.num_blocks++;
+	}
+
+      if (word_num % idh.lookback == 0)
+	{
+	  HTONUS2(buf_in_use, pointers[ptrs_in_use++]);  /* [RPAP - Jan 97: Endian Ordering] */
+	  suff += copy;
+	  copy = 0;
+	}
+      buffer[buf_in_use++] = copy;
+      buffer[buf_in_use++] = suff;
+      bcopy ((char *) (prev + copy + 1), (char *) (buffer + buf_in_use), suff);
+      buf_in_use += suff;
+      HTONUL(fcnt);  /* [RPAP - Jan 97: Endian Ordering] */
+      bcopy ((char *) &fcnt, (char *) (buffer + buf_in_use), sizeof (fcnt));
+      buf_in_use += sizeof (fcnt);
+      HTONUL(wcnt);  /* [RPAP - Jan 97: Endian Ordering] */
+      bcopy ((char *) &wcnt, (char *) (buffer + buf_in_use), sizeof (wcnt));
+      buf_in_use += sizeof (wcnt);
+      last_ptr = invf_ptr;
+      HTONUL(invf_ptr);  /* [RPAP - Jan 97: Endian Ordering] */
+      bcopy ((char *) &invf_ptr, (char *) (buffer + buf_in_use), sizeof (invf_ptr));
+      NTOHUL(invf_ptr);  /* [RPAP - Jan 97: Endian Ordering] */
+      buf_in_use += sizeof (invf_ptr);
+      if (buf_in_use + ptrs_in_use * sizeof (*pointers) +
+	  sizeof (ptrs_in_use) > block_size)
+	FatalError (1, "Fatal Internal Error # 34876234\n");
+      if (word_num == 0)
+	{
+	  fwrite (prev, sizeof (u_char), *prev + 1, idb);
+	  HTONUL(pos);  /* [RPAP - Jan 97: Endian Ordering] */
+	  fwrite (&pos, sizeof (pos), 1, idb);
+	  NTOHUL(pos);  /* [RPAP - Jan 97: Endian Ordering] */
+	  sdh.index_chars += *prev + 1;
+	  First_word = i;
+	}
+      word_num++;
+    }
+  if (buf_in_use)
+    {
+      int chunk;
+      fread (&invf_ptr, sizeof (invf_ptr), 1, ii);
+      NTOHUL(invf_ptr);  /* [RPAP - Jan 97: Endian Ordering] */
+      invf_len = invf_ptr - last_ptr;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      HTONUL(First_word);
+      HTONUL(invf_len);
+      HTONUS(word_num);
+
+      fwrite (&First_word, sizeof (First_word), 1, tmp);
+      fwrite (&invf_len, sizeof (invf_len), 1, tmp);
+      fwrite (&word_num, sizeof (word_num), 1, tmp);
+      fwrite (pointers, sizeof (*pointers), ptrs_in_use, tmp);
+      fwrite (buffer, sizeof (u_char), buf_in_use, tmp);
+      bzero ((char *) buffer, block_size);
+      chunk = buf_in_use + ptrs_in_use * sizeof (*pointers) +
+	sizeof (ptrs_in_use) + sizeof (First_word) + sizeof (invf_len);
+      if (force && chunk < block_size)
+	{
+	  fwrite (buffer, sizeof (u_char), block_size - chunk, tmp);
+	  chunk = block_size;
+	}
+
+      sdh.num_blocks++;
+    }
+  fclose (id);
+  fclose (ii);
+
+  rewind (tmp);
+  sdh.blocks_start = sdh.index_chars + sizeof (u_long) + sizeof (sdh) +
+    sdh.num_blocks * sizeof (pos);
+  if (force)
+    {
+      int amount;
+      amount = sdh.blocks_start % block_size;
+      if (amount != 0)
+	{
+	  bzero ((char *) buffer, block_size);
+	  fwrite (buffer, sizeof (u_char), block_size - amount, idb);
+	  sdh.blocks_start += block_size - amount;
+	}
+    }
+
+  while ((num = fread (buffer, sizeof (u_char), block_size, tmp)) != 0)
+    fwrite (buffer, sizeof (u_char), num, idb);
+  fclose (tmp);
+
+  /* skip over the magic number */
+  fseek (idb, sizeof (u_long), 0);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(sdh.lookback);
+  HTONUL(sdh.block_size);
+  HTONUL(sdh.num_blocks);
+  HTONUL(sdh.blocks_start);
+  HTONUL(sdh.index_chars);
+  HTONUL(sdh.num_of_docs);
+  HTONUL(sdh.static_num_of_docs);
+  HTONUL(sdh.num_of_words);
+  HTONUL(sdh.stemmer_num);
+  HTONUL(sdh.stem_method);
+  HTONUL(sdh.indexed);
+
+  fwrite (&sdh, sizeof (sdh), 1, idb);
+  fclose (idb);
+
+
+  Message ("Block size = %d\n", block_size);
+  Message ("Number of blocks written = %d\n", NTOHUL(sdh.num_blocks));
+
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_invf_dump.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_invf_dump.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_invf_dump.1	(revision 14757)
@@ -0,0 +1,142 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_invf_dump 1 \*(Dt CITRI
+.SH NAME
+mg_invf_dump \- Dump out an inverted file in ASCII
+.SH SYNOPSIS
+.B mg_invf_dump
+[
+.B \-h
+]
+[
+.B \-b
+]
+[
+.B \-w
+]
+[
+.B \-t
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+This program dumps out an inverted file produced by the
+.BR mg (1)
+system as ASCII numbers.  This program could be used in conjunction
+with
+.BR mgdictlist (1)
+to write simple shell programs that work with the inverted files.  The
+output from the program looks something like this:
+.LP
+.RS
+.ft 3
+.nf
+6 337
+1
+ 1 1
+1
+ 5 1
+1
+ 2 1
+1
+ 1 1
+4
+ 1 3
+ 2 7
+ 3 2
+ 5 2
+1
+ 1 1
+ . . .
+.fi
+.ft
+.RE
+The first number (6) is the number of documents in the collection.  It
+is followed by the number of different terms in the collection.  For
+each term, the number of different documents it occurs in follows. The
+document numbers that the term occurs in are listed next.  If
+.B \-w
+is specified, then the number of times the term occurred in the
+document is printed alongside the document number.
+If
+.B \-t
+is specified, the term itself is also displayed in quotes.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-b
+This option will cause the output from the program to be in fixed-size
+binary numbers, rather than in ASCII.
+.TP
+.B \-w
+If the inverted file is a level-2 or level-3 inverted file, this causes
+the word counts per document to be output.
+.TP
+.B \-t
+This option causes each term to be displayed along with the number of
+documents it appears in. The term is printed in quotes,
+as in "the".
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf.dict
+The compressed stemmed dictionary.
+.TP
+.B *.invf.ORG
+The original inverted file saved by
+.BR mg_invf_rebuild .
+.TP
+.B *.invf
+The inverted file.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_invf_dump.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_invf_dump.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_invf_dump.c	(revision 14757)
@@ -0,0 +1,229 @@
+/**************************************************************************
+ *
+ * mg_invf_dump.c -- Program to dump uot an inverted fil
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "messages.h"
+#include "timing.h"
+#include "bitio_m.h"
+#include "bitio_m_stdio.h"
+#include "bitio_gen.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "locallib.h"
+#include "words.h"
+#include "invf.h"
+
+extern unsigned long S_btg;
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.2  2001/06/12 01:41:39  kjm18
+   changed the help message
+
+   Revision 1.1  1999/08/10 21:18:09  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:46  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:05  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/11/29  00:32:01  tes
+   * Committing the new merged files and changes.
+   *
+   * Revision 1.2  1994/09/20  04:41:50  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+
+
+static void process_files (char *filename);
+
+int binary = 0;
+int word_counts = 0;
+int term_dump = 0;
+
+
+int main (int argc, char **argv)
+{
+  ProgTime start;
+  char *dir_name, *file_name = "";
+  int ch;
+  msg_prefix = argv[0];
+  dir_name = getenv ("MGDATA");
+  opterr = 0;
+  msg_prefix = argv[0];
+  while ((ch = getopt (argc, argv, "hbwtf:d:")) != -1)
+    switch (ch)
+      {
+      case 'f':		/* input file */
+	file_name = optarg;
+	break;
+      case 'd':
+        set_basepath(optarg);
+	break;
+      case 'b':
+	binary = 1;
+	break;
+      case 'w':
+	word_counts = 1;
+	break;
+      case 't':
+	term_dump = 1;
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-h] [-b] [-w] [-t] [-f input_file]"
+		 "[-d data directory]\n"
+		 "(b - binary mode, w - wordcount, t - term dump)\n", argv[0]);
+	exit (1);
+      }
+  GetTime (&start);
+  process_files (file_name);
+  Message ("%s\n", ElapsedTime (&start, NULL));
+  return 0;
+}
+
+static void 
+process_files (char *name)
+{
+  unsigned long N, Nstatic, k;
+  FILE *dict;
+  FILE *invf;
+  struct invf_dict_header idh;
+  struct invf_file_header ifh;
+  int i;  /* [RPAP - Jan 97: Endian Ordering] */
+
+  dict = open_file (name, INVF_DICT_SUFFIX, "rb", MAGIC_STEM_BUILD, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  fread ((char *) &idh, sizeof (idh), 1, dict);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(idh.lookback);
+  NTOHUL(idh.dict_size);
+  NTOHUL(idh.total_bytes);
+  NTOHUL(idh.index_string_bytes);
+  NTOHD(idh.input_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(idh.num_of_docs);
+  NTOHUL(idh.static_num_of_docs);
+  NTOHUL(idh.num_of_words);
+  NTOHUL(idh.stemmer_num);
+  NTOHUL(idh.stem_method);
+
+  if (!(invf = open_file (name, INVF_SUFFIX ".ORG", "rb", MAGIC_INVF, MG_CONTINUE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    invf = open_file (name, INVF_SUFFIX, "rb", MAGIC_INVF, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  fread ((char *) &ifh, sizeof (ifh), 1, invf);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(ifh.no_of_words);
+  NTOHUL(ifh.no_of_ptrs);
+  NTOHUL(ifh.skip_mode);
+  for (i = 0; i < 16; i++)
+    NTOHUL(ifh.params[i]);
+  NTOHUL(ifh.InvfLevel);
+
+  if (ifh.skip_mode != 0)
+    FatalError (1, "The invf file contains skips. Unable to dump.");
+
+  DECODE_START (invf)
+    N = idh.num_of_docs;
+  Nstatic = idh.static_num_of_docs;
+  if (binary)
+    {
+      fwrite ((char *) &N, sizeof (N), 1, stdout);
+      fwrite ((char *) &ifh.no_of_words, sizeof (ifh.no_of_words), 1, stdout);
+    }
+  else
+    printf ("%ld %ld\n", N, ifh.no_of_words);
+  for (k = 0; k < ifh.no_of_words; k++)
+    {
+      int i, blk, doc;
+      register unsigned long suff, prefix;
+      unsigned long fcnt, wcnt;
+      char term[MAXSTEMLEN + 1];
+
+      prefix = fgetc (dict);
+      suff = fgetc (dict);
+      fread (&term[prefix], sizeof (char), suff, dict);
+      fread ((char *) &fcnt, sizeof (fcnt), 1, dict);
+      fread ((char *) &wcnt, sizeof (wcnt), 1, dict);
+      term[prefix + suff] = '\0';
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(fcnt);
+      NTOHUL(wcnt);
+
+      if (binary)
+	fwrite ((char *) &fcnt, sizeof (fcnt), 1, stdout);
+      else
+	{
+	  if (term_dump)
+	    printf ("%ld    \"%s\"\n", fcnt, term);
+	  else
+	    printf ("%ld\n", fcnt);
+	}
+      blk = BIO_Bblock_Init (Nstatic, fcnt);
+      for (doc = i = 0; i < fcnt; i++)
+	{
+	  int num;
+	  BBLOCK_DECODE (num, blk);
+	  doc += num;
+	  if (binary)
+	    fwrite ((char *) &doc, sizeof (doc), 1, stdout);
+	  else
+	    printf (" %d", doc);
+	  if (ifh.InvfLevel >= 2)
+	    {
+	      int count;
+	      GAMMA_DECODE (count);
+	      if (word_counts)
+		if (binary)
+		  fwrite ((char *) &count, sizeof (count), 1, stdout);
+		else
+		  printf (" %d", count);
+	    }
+	  if (!binary)
+	    putchar ('\n');
+	}
+      while (__btg)
+	DECODE_BIT;
+    }
+  DECODE_DONE
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_invf_merge.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_invf_merge.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_invf_merge.1	(revision 14757)
@@ -0,0 +1,112 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_invf_merge 1 \*(Dt CITRI
+.SH NAME
+mg_invf_merge \- Merge two inverted files and stemmed dictionaries
+.SH SYNOPSIS
+.B mg_invf_merge
+[
+.B \-h
+]
+[
+.B \-s
+]
+[
+.B \-w
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+This program takes two
+.BR mg (1)
+database compressed text files and appends the second to
+the first.
+It is part of the
+.BR mgmerge (1)
+addition to the
+.BR mg (1)
+package.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-s
+This option will cause a slow merge to be performed on the inverted files,
+where each inverted file entry is decoded and recoded.
+The default is a fast merge. Accumulated fast merges slowly degrade
+compression performance on the resulting inverted file so
+a periodic slow merge is recommended.
+.TP
+.B \-w
+By default the database .weights file is updated with
+new weights for the new documents in
+.B mg_text_merge.
+The
+.B -w
+option turns this step off.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.old.invf.dict
+The old compressed stemmed dictionary.
+.TP
+.B *.new.invf.dict
+The new compressed stemmed dictionary.
+.TP
+.B *.invf.dict
+The resulting merged compressed stemmed dictionary.
+.TP
+.B *.old.invf.ORG
+The original inverted file saved by
+.BR mg_invf_rebuild .
+.TP
+.B *.old.invf
+The old inverted file.
+.TP
+.B *.new.invf
+The new inverted file.
+.TP
+.B *.invf
+The resulting merged inverted file.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mgmerge (1),
+.BR mg_get_merge (1),
+.BR mg_text_merge (1),
+.BR mg_invf_rebuild (1),
+.BR mg_invf_dict (1),
+.BR mg_weights_build (1),
+.BR mgquery (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_invf_merge.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_invf_merge.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_invf_merge.c	(revision 14757)
@@ -0,0 +1,852 @@
+/**************************************************************************
+ *
+ * mg_invf_merge.c -- description
+ * Copyright (C) 1995  Shane Hudson (shane@cosc.canterbury.ac.nz)
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Last edited:  31 March, 1995 
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "locallib.h"
+#include "local_strings.h"
+#include "messages.h"
+#include "timing.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "bitio_m.h"
+#include "bitio_gen.h"
+#include "bitio_stdio.h"
+
+#include "mg.h"
+#include "mg_merge.h"
+#include "mg_files.h"
+#include "invf.h"
+#include "words.h"
+
+typedef char FileName[256];
+
+
+/*
+ *  The merge_info struct contains all the data for an inverted file and
+ *  lexicon. We declare 3 merge_info variables, m[OLD] m[NEW] and m[MERGE].
+ */
+typedef struct merge_info_type
+  {
+    FileName fname;
+    FILE *invf;
+    FILE *dict;
+    FILE *idx;
+    FILE *para;  /* [RPAP - Feb 97: Level 3 Merge] */
+    struct invf_dict_header idh;
+    struct invf_file_header ifh;
+    u_long nDocs;
+
+    /* Lexicon processing variables */
+    u_long fcnt, wcnt;
+    int suff, pref;
+    unsigned char term[MAXSTEMLEN + 1];
+    u_long term_count;
+    int done;
+
+    /* Variables used for merging */
+    struct stdio_bitio_state sbs;	/* for bit-based I/O on inverted files */
+    u_long nTerms;		/* = number of invf entries */
+    int *fcntlist;		/* store fcnt values read in from the lexicons */
+
+  }
+merge_info;
+
+
+/***************************************************
+ **** GLOBALS ****
+ ***************************************************/
+
+merge_info m[3];		/*  m[OLD], m[NEW] and m[MERGE] */
+u_long magicsize;		/* how big is magic number? currently always 4 */
+u_long Nstatic;			/* static # of documents in file */
+
+float *DocWeightBuffer;
+int weightOption = 0;		/* true if weights file is to be appended */
+
+/*** Globals for processing the lexicons -- see readTerm() and writeTerm() 
+ ***/
+ProgTime start;			/* for printing elapsed time */
+unsigned char prevTerm[MAXSTEMLEN + 1];
+
+/*** Globals for merging -- see processEntry() 
+ ***/
+char *mergedata;		/* stores value OLD/NEW/MERGE for each term */
+int fastMerge = 1;		/* True if fast merge selected. Default = true */
+
+u_long oldIdxValue;		/* stores last read value from m[OLD].idx
+				   Used to calculate entry lengths */
+u_long bytes_output;		/* for writing .invf.idx file */
+u_long oldOnlyBits = 0;		/* entries in old only */
+u_long oldMergeBits = 0;	/* entries in old that are merged with 
+				   a new entry */
+
+/**************************************************************************/
+
+
+/*=======================================================================
+ * init_merge_invf(): open files, initialise globals, etc
+ *=======================================================================*/
+int 
+init_merge_invf ()
+{
+  prevTerm[0] = prevTerm[1] = 0;
+
+    /***
+     *  open .dict files
+     ***/
+  m[OLD].dict = open_file (m[OLD].fname, INVF_DICT_SUFFIX, "rb",
+			   MAGIC_STEM_BUILD, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+  magicsize = ftell (m[OLD].dict);
+  fread (&(m[OLD].idh), sizeof (m[OLD].idh), 1, m[OLD].dict);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(m[OLD].idh.lookback);
+  NTOHUL(m[OLD].idh.dict_size);
+  NTOHUL(m[OLD].idh.total_bytes);
+  NTOHUL(m[OLD].idh.index_string_bytes);
+  NTOHD(m[OLD].idh.input_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(m[OLD].idh.num_of_docs);
+  NTOHUL(m[OLD].idh.static_num_of_docs);
+  NTOHUL(m[OLD].idh.num_of_words);
+  NTOHUL(m[OLD].idh.stemmer_num);
+  NTOHUL(m[OLD].idh.stem_method);
+
+  m[NEW].dict = open_file (m[NEW].fname, INVF_DICT_SUFFIX, "rb",
+			   MAGIC_STEM_BUILD, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+  fread (&(m[NEW].idh), sizeof (m[NEW].idh), 1, m[NEW].dict);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(m[NEW].idh.lookback);
+  NTOHUL(m[NEW].idh.dict_size);
+  NTOHUL(m[NEW].idh.total_bytes);
+  NTOHUL(m[NEW].idh.index_string_bytes);
+  NTOHD(m[NEW].idh.input_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(m[NEW].idh.num_of_docs);
+  NTOHUL(m[NEW].idh.static_num_of_docs);
+  NTOHUL(m[NEW].idh.num_of_words);
+  NTOHUL(m[NEW].idh.stemmer_num);
+  NTOHUL(m[NEW].idh.stem_method);
+
+  m[MERGE].dict = create_file (m[MERGE].fname, INVF_DICT_SUFFIX, "wb",
+			       MAGIC_STEM_BUILD, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  /* write space for header */
+  fwrite ((char *) &(m[OLD].idh), sizeof (m[OLD].idh), 1, m[MERGE].dict);
+
+  m[OLD].nDocs = m[OLD].idh.num_of_docs;
+  m[NEW].nDocs = m[NEW].idh.num_of_docs;
+  Nstatic = m[OLD].idh.static_num_of_docs;
+  m[OLD].nTerms = m[OLD].idh.dict_size;
+  m[NEW].nTerms = m[NEW].idh.dict_size;
+  m[MERGE].nDocs = m[OLD].nDocs + m[NEW].nDocs;
+  m[MERGE].nTerms = 0;
+
+  /* Set up weight buffer for weights of new documents */
+  if (!(DocWeightBuffer = Xmalloc (m[NEW].nDocs * sizeof (*DocWeightBuffer))))
+    {
+      Message ("Insufficient memory\n");
+      return COMPERROR;
+    }
+  bzero ((char *) DocWeightBuffer, m[NEW].nDocs * sizeof (*DocWeightBuffer));
+
+    /***
+     *  open .invf files
+     *  Try ".ORG" extension first for m[OLD].invf since an inverted file
+     *  with skips may have been created.
+     ****/
+  if (!(m[OLD].invf = open_file (m[OLD].fname, INVF_SUFFIX ".ORG", "rb",
+				 MAGIC_INVF, MG_CONTINUE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    m[OLD].invf = open_file (m[OLD].fname, INVF_SUFFIX, "rb",
+			     MAGIC_INVF, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+  fread (&(m[OLD].ifh), sizeof (m[OLD].ifh), 1, m[OLD].invf);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(m[OLD].ifh.no_of_words);
+  NTOHUL(m[OLD].ifh.no_of_ptrs);
+  NTOHUL(m[OLD].ifh.skip_mode);
+  {
+    int i;
+    for (i = 0; i < 16; i++)
+      NTOHUL(m[OLD].ifh.params[i]);
+  }
+  NTOHUL(m[OLD].ifh.InvfLevel);
+
+  m[NEW].invf = open_file (m[NEW].fname, INVF_SUFFIX, "rb",
+			   MAGIC_INVF, MG_ABORT);
+  fread (&(m[NEW].ifh), sizeof (m[NEW].ifh), 1, m[NEW].invf);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(m[NEW].ifh.no_of_words);
+  NTOHUL(m[NEW].ifh.no_of_ptrs);
+  NTOHUL(m[NEW].ifh.skip_mode);
+  {
+    int i;
+    for (i = 0; i < 16; i++)
+      NTOHUL(m[NEW].ifh.params[i]);
+  }
+  NTOHUL(m[NEW].ifh.InvfLevel);
+
+  if (m[OLD].ifh.skip_mode != 0)
+    FatalError (1, "The old invf file contains skips. Unable to merge.");
+
+  if (m[OLD].ifh.InvfLevel != m[NEW].ifh.InvfLevel)
+    FatalError (1, "The two invf files have different inversion levels!");
+
+  /********** [RPAP - Feb 97: Level 3 Merge]
+
+  if ((m[OLD].ifh.InvfLevel > 2) || (m[NEW].ifh.InvfLevel > 2))
+    FatalError (1, "mgmerge cannot handle level 3 inverted files!");
+
+    *************/
+
+  m[MERGE].invf = create_file (m[MERGE].fname, INVF_SUFFIX, "wb",
+			       MAGIC_INVF, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  /* write space for header in inverted file */
+  m[MERGE].ifh.no_of_words = m[MERGE].ifh.no_of_ptrs = 0;
+  m[MERGE].ifh.skip_mode = 0;
+  m[MERGE].ifh.InvfLevel = 2;
+  {
+    int i;
+    for (i = 0; i < 16; i++)
+      m[MERGE].ifh.params[i] = 0;
+  }
+  fwrite ((char *) &(m[MERGE].ifh), sizeof (m[MERGE].ifh), 1, m[MERGE].invf);
+
+    /***
+     *  open .invf.idx files
+     ***/
+  m[OLD].idx = open_file (m[OLD].fname, INVF_IDX_SUFFIX, "rb",
+			  MAGIC_INVI, MG_ABORT);
+  fread (&oldIdxValue, sizeof (u_long), 1, m[OLD].idx);
+  NTOHUL(oldIdxValue);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  m[NEW].idx = open_file (m[NEW].fname, INVF_IDX_SUFFIX, "rb",
+			  MAGIC_INVI, MG_ABORT);
+
+  m[MERGE].idx = create_file (m[MERGE].fname, INVF_IDX_SUFFIX, "wb",
+			      MAGIC_INVI, MG_ABORT);
+
+
+  /* [RPAP - Feb 97: Level 3 Merge] */
+
+    /***
+     *  open .invf.parargraph files
+     ***/
+  if (m[OLD].ifh.InvfLevel == 3)
+    {
+      m[OLD].para = NULL;
+      m[NEW].para = open_file (m[NEW].fname, INVF_PARAGRAPH_SUFFIX, "rb",
+			       MAGIC_PARAGRAPH, MG_ABORT);
+      m[MERGE].para = open_file (m[MERGE].fname, INVF_PARAGRAPH_SUFFIX, "rb+",
+				 MAGIC_PARAGRAPH, MG_ABORT);
+    }
+  else
+    {
+      m[OLD].para = NULL;
+      m[NEW].para = NULL;
+      m[MERGE].para = NULL;
+    }
+
+  return OK;
+}
+
+
+/*=======================================================================
+ * procEntry_slow(): merge an entry, slow method
+ *=======================================================================*/
+void 
+procEntry_slow (int tnum, int type, u_long oldN, u_long newN, u_long mergeN)
+/* 
+ *  Process an invf entry. 
+ *  Slow Merge. (Always decode/re-encode).
+ *
+ *  tnum is the entry number, type = OLD or NEW or MERGE.
+ *  oldN, newN and mergeN are the N parameters for Bblock coding.
+ *  They are passed so other procEntry_fast can call this one
+ *  when a decode/recode is needed to save repeating code.
+ */
+{
+  int doc = 0;
+  int fcntOLD = m[OLD].fcntlist[tnum];
+  int fcntNEW = m[NEW].fcntlist[tnum];
+  int inblk, outblk;
+  u_long inbits = 0, outbits = 0;
+
+  /* write .invf.idx pointer */
+  HTONUL(bytes_output);  /* [RPAP - Jan 97: Endian Ordering] */
+  fwrite (&bytes_output, sizeof (u_long), 1, m[MERGE].idx);
+  NTOHUL(bytes_output);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  outblk = BIO_Bblock_Init (mergeN, (fcntOLD + fcntNEW));
+
+/*** OLD entry -> merge entry ***/
+  if (type != NEW)
+    {
+      int i;
+      inblk = BIO_Bblock_Init (oldN, fcntOLD);
+      for (i = 0; i < fcntOLD; i++)
+	{
+	  int num;
+	  num = BIO_Stdio_Bblock_Decode (inblk, &(m[OLD].sbs), &inbits);
+	  doc += num;
+	  BIO_Stdio_Bblock_Encode (num, outblk, &(m[MERGE].sbs), &outbits);
+	  if (m[OLD].ifh.InvfLevel >= 2)	/* frequencies */
+	    {
+	      num = BIO_Stdio_Gamma_Decode (&(m[OLD].sbs), &inbits);
+	      BIO_Stdio_Gamma_Encode (num, &(m[MERGE].sbs), &outbits);
+	    }
+	}
+      if (type == OLD)
+	oldOnlyBits += (inbits + m[OLD].sbs.Btg);
+      else
+	oldMergeBits += (inbits + m[OLD].sbs.Btg);
+    }
+
+/*** NEW entry -> merge entry ***/
+  if (type != OLD)
+    {
+      int i;
+      int offset;
+      double logN = log ((double) m[MERGE].nDocs);
+      double idf = logN - log ((double) (fcntOLD + fcntNEW));
+
+      inblk = BIO_Bblock_Init (newN, fcntNEW);
+      offset = (m[OLD].nDocs - doc);	/* amount to be added to 1ST pointer */
+      for (i = 0; i < fcntNEW; i++)
+	{
+	  register int num;
+	  register double weight;
+	  num = BIO_Stdio_Bblock_Decode (inblk, &(m[NEW].sbs), &inbits);
+	  if (i == 0)
+	    num += offset;
+	  doc += num;
+	  BIO_Stdio_Bblock_Encode (num, outblk, &(m[MERGE].sbs), &outbits);
+	  if (m[OLD].ifh.InvfLevel >= 2)	/* frequencies */
+	    {
+	      num = BIO_Stdio_Gamma_Decode (&(m[NEW].sbs), &inbits);
+	      BIO_Stdio_Gamma_Encode (num, &(m[MERGE].sbs), &outbits);
+	      weight = num * idf;
+	      DocWeightBuffer[doc - m[OLD].nDocs - 1] += weight * weight;
+	    }
+	}
+    }
+/*** Now the padding bits ***/
+  while (m[OLD].sbs.Btg)
+    BIO_Stdio_Decode_Bit (&(m[OLD].sbs));
+  while (m[NEW].sbs.Btg)
+    BIO_Stdio_Decode_Bit (&(m[NEW].sbs));
+  while (m[MERGE].sbs.Btg != 8)
+    {
+      BIO_Stdio_Encode_Bit (0, &(m[MERGE].sbs));
+      outbits++;
+    }
+  bytes_output += (outbits >> 3);
+  return;
+}
+
+
+/*=======================================================================
+ * procEntry_fast(): merge an entry, WITHOUT decoding if it's in the
+ *                   old inverted file only
+ *=======================================================================*/
+void 
+procEntry_fast (int tnum, int type)
+/*
+ *  Merge an invf entry. 
+ *  Faster Method : Copy (don't re-code) entries for terms only in IFold.
+ *  The N parameter is Nstatic, from m[OLD].idh.static_num_of_docs.
+ *  If entry type isnt OLD, just call procEntry_slow()
+ */
+{
+  u_long newIdxValue, len = 0;
+
+  /* Calculate IFold entry length in bytes if not NEW type */
+  if (type != NEW)		/* read in an index number from m[OLD].idx */
+    {
+      fread (&newIdxValue, sizeof (u_long), 1, m[OLD].idx);
+      NTOHUL(newIdxValue);  /* [RPAP - Jan 97: Endian Ordering] */
+      len = newIdxValue - oldIdxValue;
+      oldIdxValue = newIdxValue;
+    }
+
+  if (type != OLD)		/* must decode/recode */
+    procEntry_slow (tnum, type, Nstatic, m[NEW].nDocs, Nstatic);
+  else
+    {
+      /* write .invf.idx pointer */
+      HTONUL(bytes_output);  /* [RPAP - Jan 97: Endian Ordering] */
+      fwrite (&bytes_output, sizeof (u_long), 1, m[MERGE].idx);
+      NTOHUL(bytes_output);  /* [RPAP - Jan 97: Endian Ordering] */
+
+      /* copy entry */
+      {
+	int i;
+	char c;
+	for (i = 0; i < len; i++)
+	  {
+	    c = fgetc (m[OLD].invf);
+	    fputc (c, m[MERGE].invf);
+	  }
+      }
+      bytes_output += len;
+      oldOnlyBits += (len * 8);
+    }
+  return;
+}
+
+
+/*=======================================================================
+ * processEntry(): merge an entry. Call either procEntry_slow() or
+ *                 procEntry_fast.
+ *=======================================================================*/
+void 
+processEntry (int tnum, int type)
+/* 
+ *  Read an entry from IFold and/or IFnew, and write to IFmerge.
+ *  tnum is the term number, type is OLD or NEW or MERGE
+ */
+{
+  if (fastMerge)
+    procEntry_fast (tnum, type);
+  else
+    procEntry_slow (tnum, type, Nstatic, m[NEW].nDocs, m[MERGE].nDocs);
+  return;
+}
+
+
+/*=======================================================================
+ * readTerm()
+ *=======================================================================*/
+void 
+readTerm (int x)
+/*
+ *  Read the next term from the appropriate ".invf.dict" file.
+ *  x should be either OLD or NEW.
+ *  Sets m[x].done to true when that lexicon has been completely read.
+ */
+{
+  int i;
+
+  if (m[x].term_count >= m[x].nTerms)
+    {
+      m[x].term[0] = 0;
+      m[x].done = 1;
+      return;
+    }
+  m[x].pref = fgetc (m[x].dict);
+  m[x].suff = fgetc (m[x].dict);
+  m[x].term[0] = m[x].pref + m[x].suff;
+
+  for (i = 0; i < m[x].suff; i++)
+    {
+      m[x].term[m[x].pref + i + 1] = fgetc (m[x].dict);
+    }
+  m[x].term_count = m[x].term_count + 1;
+
+  fread ((char *) &(m[x].fcnt), sizeof (u_long), 1, m[x].dict);
+  fread ((char *) &(m[x].wcnt), sizeof (u_long), 1, m[x].dict);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(m[x].fcnt);
+  NTOHUL(m[x].wcnt);
+
+  return;
+}
+
+
+/*=======================================================================
+ * writeTerm()
+ *=======================================================================*/
+void 
+writeTerm (int x)
+/*
+ *  Write the current term to m[MERGE].dict file.
+ *  x is OLD, NEW or MERGE.
+ */
+{
+  unsigned char i, prefix, suffix;
+  if (x == MERGE)
+    {
+      m[MERGE].fcnt = m[OLD].fcnt + m[NEW].fcnt;
+      m[MERGE].wcnt = m[OLD].wcnt + m[NEW].wcnt;
+      m[MERGE].pref = m[OLD].pref;
+      m[MERGE].suff = m[OLD].suff;
+      memcpy (m[MERGE].term, m[OLD].term, m[OLD].term[0] + 1);
+    }
+  if (x == OLD)
+    {
+      m[MERGE].fcnt = m[OLD].fcnt;
+      m[MERGE].wcnt = m[OLD].wcnt;
+    }
+  if (x == NEW)
+    {
+      m[MERGE].fcnt = m[NEW].fcnt;
+      m[MERGE].wcnt = m[NEW].wcnt;
+    }
+  prefix = prefixlen (prevTerm, m[x].term);
+  suffix = m[x].term[0] - prefix;
+  fputc (prefix, m[MERGE].dict);	/* prefix length */
+  fputc (suffix, m[MERGE].dict);	/* suffix length */
+  for (i = 0; i < suffix; i++)
+    fputc (m[x].term[prefix + i + 1], m[MERGE].dict);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(m[MERGE].fcnt);
+  HTONUL(m[MERGE].wcnt);
+
+  fwrite ((char *) &(m[MERGE].fcnt), sizeof (m[MERGE].fcnt), 1, m[MERGE].dict);
+  fwrite ((char *) &(m[MERGE].wcnt), sizeof (m[MERGE].wcnt), 1, m[MERGE].dict);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(m[MERGE].fcnt);
+  NTOHUL(m[MERGE].wcnt);
+
+  memcpy (prevTerm, m[x].term, prefix + suffix + 1);
+  m[MERGE].idh.total_bytes += m[x].term[0] + 1;
+  m[MERGE].idh.index_string_bytes += m[x].term[0] + 2 - prefix;
+  fflush (m[MERGE].dict);
+}
+
+
+/*=======================================================================
+ * process_merge_invf(): The main loop
+ *=======================================================================*/
+int 
+process_merge_invf (void)
+/*
+ *  The main function to merge the lexicons and inverted files.
+ */
+{
+/*** Some extra Initialisation stuff first ***/
+
+  m[OLD].term[0] = m[NEW].term[0] = '\0';
+  m[OLD].term_count = m[NEW].term_count = 0;
+  m[OLD].done = m[NEW].done = 0;
+  m[MERGE].idh.total_bytes = m[MERGE].idh.index_string_bytes = 0;
+
+/*** malloc arrays: mergedata, m[OLD].fcntlist, m[NEW].fcntlist ***/
+  mergedata = malloc ((m[OLD].nTerms + m[NEW].nTerms) * sizeof (char));
+  if (mergedata == 0)
+    {
+      fprintf (stderr, "MALLOC error!\n");
+      exit (1);
+    }
+  {
+    int i;
+    for (i = 0; i < 2; i++)
+      {
+	m[i].fcntlist = malloc ((m[OLD].nTerms + m[NEW].nTerms) * sizeof (int));
+	if (m[i].fcntlist == 0)
+	  {
+	    fprintf (stderr, "MALLOC error!\n");
+	    exit (1);
+	  }
+      }
+  }
+
+/*========================*/
+/***    LEXICON PASS    ***/
+/*========================*/
+
+/*** read first terms ***/
+  readTerm (OLD);
+  readTerm (NEW);
+
+  m[MERGE].nTerms = 0;
+  while (m[OLD].done == 0 || m[NEW].done == 0)
+    {
+      int i;
+      if (m[OLD].done)
+	i = 1; /* NEW will always be greater */
+      else if (m[NEW].done)
+	i = -1; /* OLD will always be greater */
+      else
+	i = casecompare (m[OLD].term, m[NEW].term);
+
+      if (i < 0)
+	{			/* term in OLD only */
+	  mergedata[m[MERGE].nTerms] = (char) OLD;
+	  m[OLD].fcntlist[m[MERGE].nTerms] = m[OLD].fcnt;
+	  m[NEW].fcntlist[m[MERGE].nTerms] = 0;
+	  m[MERGE].nTerms++;
+	  writeTerm (OLD);
+	  readTerm (OLD);
+	}
+      if (i == 0)
+	{			/* term in both lexions */
+	  mergedata[m[MERGE].nTerms] = (char) MERGE;
+	  m[OLD].fcntlist[m[MERGE].nTerms] = m[OLD].fcnt;
+	  m[NEW].fcntlist[m[MERGE].nTerms] = m[NEW].fcnt;
+	  m[MERGE].nTerms++;
+	  writeTerm (MERGE);
+	  readTerm (OLD);
+	  readTerm (NEW);
+	}
+      if (i > 0)
+	{			/* term in NEW only */
+	  mergedata[m[MERGE].nTerms] = (char) NEW;
+	  m[NEW].fcntlist[m[MERGE].nTerms] = m[NEW].fcnt;
+	  m[OLD].fcntlist[m[MERGE].nTerms] = 0;
+	  m[MERGE].nTerms++;
+	  writeTerm (NEW);
+	  readTerm (NEW);
+	}
+    }/*while*/
+  Message ("%s\n", ElapsedTime (&start, NULL));
+  /* print some results about terms */
+  {
+    fprintf (stderr, "   Terms: OLD = %ld,  NEW = %ld,  MERGE = %ld\n",
+	     m[OLD].nTerms, m[NEW].nTerms, m[MERGE].nTerms);
+    fprintf (stderr, "   In OLD only: %ld,  In NEW only: %ld,  BOTH: %ld\n",
+	     (m[MERGE].nTerms - m[NEW].nTerms),
+	     (m[MERGE].nTerms - m[OLD].nTerms),
+	     (m[OLD].nTerms + m[NEW].nTerms - m[MERGE].nTerms));
+  }
+
+
+/*========================*/
+/***      INVF PASS     ***/
+/*========================*/
+
+  bytes_output = ftell (m[MERGE].invf);
+  BIO_Stdio_Decode_Start (m[OLD].invf, &m[OLD].sbs);
+  BIO_Stdio_Decode_Start (m[NEW].invf, &m[NEW].sbs);
+  BIO_Stdio_Encode_Start (m[MERGE].invf, &m[MERGE].sbs);
+  {
+    int i;
+    for (i = 0; i < m[MERGE].nTerms; i++)
+      {
+	processEntry (i, mergedata[i]);
+      }
+    /* write final .invf.idx pointer */
+    HTONUL(bytes_output);  /* [RPAP - Jan 97: Endian Ordering] */
+    fwrite (&bytes_output, sizeof (u_long), 1, m[MERGE].idx);
+    NTOHUL(bytes_output);  /* [RPAP - Jan 97: Endian Ordering] */
+
+    fprintf (stderr, "Old invf: old only bits: %ld, merged bits: %ld\n",
+	     oldOnlyBits, oldMergeBits);
+  }
+
+  return OK;
+}
+
+
+/*=======================================================================
+ * done_merge_invf(): write headers, close files, append weights to
+ *                     weights file
+ *=======================================================================*/
+int 
+done_merge_invf (void)
+{
+/*** write new lexicon header ***/
+  m[MERGE].idh.dict_size = m[MERGE].nTerms;
+  m[MERGE].idh.lookback = m[OLD].idh.lookback;
+  m[MERGE].idh.input_bytes = m[OLD].idh.input_bytes + m[NEW].idh.input_bytes;
+  m[MERGE].idh.total_bytes = m[OLD].idh.total_bytes + m[NEW].idh.total_bytes;
+  m[MERGE].idh.num_of_docs = m[MERGE].nDocs;
+  m[MERGE].idh.num_of_words = m[OLD].idh.num_of_words + m[NEW].idh.num_of_words;
+  m[MERGE].idh.stemmer_num = m[OLD].idh.stemmer_num;
+  m[MERGE].idh.stem_method = m[OLD].idh.stem_method;
+
+  /* if fastMerge, static num of docs stays the same! */
+  if (fastMerge)
+    m[MERGE].idh.static_num_of_docs = m[OLD].idh.static_num_of_docs;
+  else
+    m[MERGE].idh.static_num_of_docs = m[MERGE].nDocs;
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(m[MERGE].idh.lookback);
+  HTONUL(m[MERGE].idh.dict_size);
+  HTONUL(m[MERGE].idh.total_bytes);
+  HTONUL(m[MERGE].idh.index_string_bytes);
+  HTOND(m[MERGE].idh.input_bytes); /* [RJM 07/97: 4G limit] */
+  HTONUL(m[MERGE].idh.num_of_docs);
+  HTONUL(m[MERGE].idh.static_num_of_docs);
+  HTONUL(m[MERGE].idh.num_of_words);
+  HTONUL(m[MERGE].idh.stemmer_num);
+  HTONUL(m[MERGE].idh.stem_method);
+
+  fseek (m[MERGE].dict, magicsize, 0);
+  fwrite (&(m[MERGE].idh), sizeof (struct invf_dict_header), 1, m[MERGE].dict);
+
+/*** write new inverted file header ***/
+  m[MERGE].ifh.no_of_words = m[MERGE].nTerms;
+  m[MERGE].ifh.no_of_ptrs = m[OLD].ifh.no_of_ptrs + m[NEW].ifh.no_of_ptrs;
+  m[MERGE].ifh.skip_mode = m[OLD].ifh.skip_mode;
+  m[MERGE].ifh.InvfLevel = m[OLD].ifh.InvfLevel;
+
+  /* ifh.params[16] -- I have NO IDEA what these do!!!!! */
+  /* only set if a inverted file is in skipped format, I think */
+  {
+    int i;
+    for (i = 0; i < 16; i++)
+      m[MERGE].ifh.params[i] = m[OLD].ifh.params[i];
+  }
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(m[MERGE].ifh.no_of_words);
+  HTONUL(m[MERGE].ifh.no_of_ptrs);
+  HTONUL(m[MERGE].ifh.skip_mode);
+  {
+    int i;
+    for (i = 0; i < 16; i++)
+      HTONUL(m[MERGE].ifh.params[i]);
+  }
+  HTONUL(m[MERGE].ifh.InvfLevel);
+
+  fseek (m[MERGE].invf, magicsize, 0);	/* go to start of header */
+  fwrite (&(m[MERGE].ifh), sizeof (struct invf_file_header), 1, m[MERGE].invf);
+
+/*** Write new document weights --- leave old weights alone ***/
+  if ((weightOption) && (m[OLD].ifh.InvfLevel >= 2))
+    {
+      FILE *weightfile = open_file (m[MERGE].fname, WEIGHTS_SUFFIX, "r+b",
+				    MAGIC_WGHT, MG_CONTINUE);  /* [RPAP - Feb 97: WIN32 Port] */
+      if (weightfile)
+	{
+	  u_long i;  /* [RPAP - Jan 97: Endian Ordering] */
+
+	  fprintf (stderr, "writing new weights: Nnew = %ld\n", m[NEW].nDocs);
+	  fseek (weightfile, 0, 2);	/* end of file */
+
+	  /* [RPAP - Jan 97: Endian Ordering] */
+	  for (i = 0; i < m[NEW].nDocs; i++)
+	    HTONF(DocWeightBuffer[i]);
+
+	  fwrite ((char *) DocWeightBuffer, sizeof (float), m[NEW].nDocs,
+		  weightfile);
+	}
+      fclose (weightfile);
+    }
+
+
+  /* [RPAP - Feb 97: Level 3 Merge] */
+  if (m[OLD].ifh.InvfLevel == 3)
+    {
+      /* Update paragraph file */
+      int buffer_size = 1000;
+      u_char *buffer;
+      int num;
+
+      if (!(buffer = (u_char *) Xmalloc (buffer_size)))
+	FatalError (1, "Could not allocate memory for paragraph buffer");
+
+      fseek (m[MERGE].para, 0, SEEK_END);
+      while ((num = fread ((char *) buffer, sizeof (*buffer), buffer_size, m[NEW].para)) != 0)
+	fwrite ((char *) buffer, sizeof (*buffer), num, m[MERGE].para);
+
+      Xfree (buffer);
+    }
+
+/*** close files ***/
+  fclose (m[MERGE].invf);
+  fclose (m[OLD].invf);
+  fclose (m[NEW].invf);
+  fclose (m[MERGE].dict);
+  fclose (m[OLD].dict);
+  fclose (m[NEW].dict);
+  fclose (m[MERGE].idx);
+  fclose (m[OLD].idx);
+  fclose (m[NEW].idx);
+
+  /* [RPAP - Feb 97: Level 3 Merge] */
+  if (m[OLD].ifh.InvfLevel == 3)
+    {
+      fclose (m[NEW].para);
+      fclose (m[MERGE].para);
+    }
+
+  return OK;
+}
+
+
+/*=======================================================================
+ * usage()
+ *=======================================================================*/
+void 
+usage (char *progname)
+{
+  fprintf (stderr, "usage:  %s [-s] [-w] [-d directory] -f mg_collection\n",
+	   progname);
+  fprintf (stderr, "  example: %s -s -w -f MERGE/mailfiles\n", progname);
+  exit (1);
+}
+
+
+/*=======================================================================
+ * main()
+ *=======================================================================*/
+int 
+main (int argc, char *argv[])
+{
+  int ch;
+  char *progname;
+  progname = argv[0];
+  m[MERGE].fname[0] = '\0';
+
+  /* message and timing information */
+  msg_prefix = argv[0];
+
+  while ((ch = getopt (argc, argv, "f:d:swh")) != -1)
+    switch (ch)
+      {
+      case 'f':
+	strcpy (m[MERGE].fname, optarg);
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 's':
+	fastMerge = 0;
+	break;
+      case 'w':
+	weightOption = 1;
+	break;
+      case 'h':
+      case '?':
+      default:
+	usage (progname);
+      }
+
+  if (m[MERGE].fname[0] == '\0')
+    usage (progname);
+  strcpy (m[OLD].fname, m[MERGE].fname);
+  strcat (m[OLD].fname, ".old");
+  strcpy (m[NEW].fname, m[MERGE].fname);
+  strcat (m[NEW].fname, ".new");
+
+  GetTime (&start);
+  init_merge_invf ();
+  process_merge_invf ();
+  done_merge_invf ();
+  Message ("%s\n", ElapsedTime (&start, NULL));
+  exit (0);
+}
+
+/*************************************************************************/
+/*   EOF: mg_invf_merge_new.c                                            */
+/*************************************************************************/
Index: /indexers/branches/3.03a/mg/src/text/mg_invf_rebuild.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_invf_rebuild.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_invf_rebuild.1	(revision 14757)
@@ -0,0 +1,156 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_invf_rebuild 1 \*(Dt CITRI
+.SH NAME
+mg_invf_rebuild \- Rebuild an mg inverted file with or without skips.
+.SH SYNOPSIS
+.B mg_invf_rebuild
+.RB [ \-h ]
+.if n .ti +9n
+[
+.BR \-0 " |"
+.B \-1
+[
+.BI \-k " num"
+] |
+.B \-2
+[
+.BI \-s " num"
+]
+[
+.BI \-m " num"
+]
+]
+.if n .ti +9n
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_invf_rebuild
+builds a new inverted file, with or without skipping, from an old
+inverted file.  This file uses
+.I *.invf.ORG
+and
+.I *.invf.idx.ORG
+as the
+source from which it builds
+.I *.invf
+and
+.IR *.invf.idx .
+If
+.I *.invf.ORG
+or
+.I *.invf.idx.ORG
+do not exist, the program renames
+.I *.invf
+or
+.I *.invf.idx
+to
+.I *.invf.ORG
+or
+.I *.invf.idx.ORG
+as appropriate.  The old inverted file may contain skipping.  This
+means that it is possible to delete the
+.I *.ORG
+files
+after the new inverted file is built.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-m\fP \fInum\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-0
+This generates a non-skipped inverted file.  This option is normally
+only needed if the
+.I *.ORG
+files have been deleted.
+.TP
+.B \-1
+This generates a skipped inverted file.  The
+.BI \-k " num"
+argument specifies the number of pointers hopped over with each skip.
+.TP
+.B \-2
+This option generates a skipped inverted file.  The skipped inverted
+file is built so that it is `optimal' for ranking using a specific
+number of accumulators.  Each term in the inverted file has a
+different skip length.  The arguments
+.BR \-s " and " \-m
+control the sizes of the skips.
+.TP
+.BI \-k " num"
+This specifies the number of pointers that should be hopped over with
+each skip.  This option is only valid if
+.B \-1
+is specified.
+.TP
+.BI \-m " num"
+This specifies the intended number of accumulators that will be used
+when ranking queries are done on the collection.
+.TP
+.BI \-s " num"
+This specifies the minimum size for skips.  If the calculation of the
+optimal skip size results in a number smaller than
+.IR num ,
+the skip size is set to
+.IR num .
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.ORG
+Original inverted file.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.TP
+.B *.invf.idx.ORG
+The original index into the inverted file.
+.TP
+.B *.invf.dict.build
+Compressed stemmed dictionary.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_invf_rebuild.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_invf_rebuild.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_invf_rebuild.c	(revision 14757)
@@ -0,0 +1,567 @@
+/**************************************************************************
+ *
+ * mg_invf_rebuild.c -- Program to rebuild an inverted file with skipping
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "messages.h"
+#include "timing.h"
+#include "bitio_m.h"
+#include "bitio_m_stdio.h"
+#include "bitio_gen.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "invf.h"
+#include "locallib.h"
+#include "words.h"
+#include "mg.h"
+
+#define LEN 40
+#define WRD 1
+
+typedef struct invf_info
+  {
+    unsigned long doc_num, count, bits_so_far, count_bits;
+  }
+invf_info;
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:11  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:46  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:10  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.4  1994/11/29  00:32:03  tes
+   * Committing the new merged files and changes.
+   *
+   * Revision 1.3  1994/10/20  03:56:56  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:51  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+static char pathname[256];
+
+static void process_files (char *filename);
+
+static int k = -1;
+static int mode = 0;
+static int max_nodes = -1;
+static int mins = -1;
+
+void 
+usage (char *pgname)
+{
+  fprintf (stderr, "usage: %s [-f input_file]"
+       "[-d data directory] -0|-1|-2 [-k num] [-m num] [-s num]\n", pgname);
+  printf ("Mode 0: (the default)\n");
+  printf ("\tk, m, and s have no meaning and if specified produce an error\n");
+  printf ("Mode 1:\n");
+  printf ("\tm, and s have no meaning and if specified produce an error\n");
+  printf ("\tk The size of skips\n");
+  printf ("Mode 2:\n");
+  printf ("\tk has no meaning and if specified will produce an error\n");
+  printf ("\tm is the the number of accumulators that will be used for the\n");
+  printf ("\t  ranking. The program builds an inverted file that is \n");
+  printf ("\t  \"optimal\" for that number of accumulators.\n");
+  printf ("\ts is the minimum size for skips.\n");
+  exit (1);
+}
+
+
+
+int main (int argc, char **argv)
+{
+  ProgTime start;
+  char *dir_name, *file_name = "";
+  int ch;
+  msg_prefix = argv[0];
+  dir_name = getenv ("MGDATA");
+  strcpy (pathname, dir_name ? dir_name : ".");
+  opterr = 0;
+  msg_prefix = argv[0];
+  while ((ch = getopt (argc, argv, "012hf:d:k:b:s:m:")) != -1)
+    switch (ch)
+      {
+      case '0':
+	mode = 0;
+	break;
+      case '1':
+	mode = 1;
+	break;
+      case '2':
+	mode = 2;
+	break;
+      case 'f':		/* input file */
+	file_name = optarg;
+	break;
+      case 'd':
+	strcpy (pathname, optarg);
+	break;
+      case 'k':
+	k = atoi (optarg);
+	break;
+      case 'm':
+	max_nodes = atoi (optarg);
+	break;
+      case 's':
+	mins = atoi (optarg);
+	if (mins < 1)
+	  FatalError (1, "The number for the -m option must be greater"
+		      " than or equal to 1");
+	break;
+      case 'h':
+      case '?':
+	usage (argv[0]);
+      }
+
+  if ((mode == 0 && (k != -1 || max_nodes != -1 || mins != -1)) ||
+      (mode == 1 && (max_nodes != -1 || mins != -1)) ||
+      (mode == 2 && (k != -1)))
+    {
+      Message ("Illegal parameters for mode");
+      usage (argv[0]);
+    }
+
+  if (mode == 1 && k == -1)
+    {
+      k = 8;
+      Message ("k is required for mode 1: defaulting k to %d", k);
+    }
+  if (mode == 2 && max_nodes == -1)
+    {
+      max_nodes = 1024;
+      Message ("m is required for mode 2: defaulting m to %d", max_nodes);
+    }
+  if (mode == 2 && mins == -1)
+    {
+      mins = 1;
+      Message ("s is required for mode 2: defaulting s to %d", mins);
+    }
+
+
+  GetTime (&start);
+  process_files (file_name);
+  Message ("%s\n", ElapsedTime (&start, NULL));
+  Message ("**** Don\'t forget to rebuild the stemmed dictionary with mg_invf_dict. ****\n");
+  Message ("**** If the collection was built with stem indexes don\'t forget to     ****\n");
+  Message ("**** rebuild them with mg_stem_idx.                                     ****\n");
+
+  return 0;
+}
+
+
+
+
+
+static void 
+process_files (char *filename)
+{
+  FILE *in, *out, *idx, *odx, *dict;
+  unsigned long magic, outmode, N, in_k, out_k;
+  unsigned long bits_out, bytes_out, i, j;
+  stdio_bitio_state out_buf, in_buf;
+  struct invf_dict_header idh;
+  struct invf_file_header ifh_in, ifh_out;
+  char FName[256];
+
+  outmode = mode;
+
+  /* open .invf.ORG, rename .invf if have to */
+  sprintf (FName, FILE_NAME_FORMAT ".ORG", pathname, filename, INVF_SUFFIX);  /* [RPAP - Feb 97: WIN32 Port] */
+  if (!(in = fopen (FName, "rb")))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      char fname[256];
+      sprintf (fname, FILE_NAME_FORMAT, pathname, filename, INVF_SUFFIX);  /* [RPAP - Feb 97: WIN32 Port] */
+      rename (fname, FName);
+      if (!(in = fopen (FName, "rb")))  /* [RPAP - Feb 97: WIN32 Port] */
+	FatalError (1, "Unable to open \"%s\".\n", FName);
+    }
+  else
+    {
+      char fname[256];
+      sprintf (fname, FILE_NAME_FORMAT, pathname, filename, INVF_SUFFIX);  /* [RPAP - Feb 97: WIN32 Port] */
+      unlink (fname);
+    }
+  Message ("Opening \"%s\"\n", FName);
+
+  /* check the magic number for .invf.ORG */
+  if (fread (&magic, sizeof (magic), 1, in) != 1 || NTOHUL(magic) != MAGIC_INVF)  /* [RPAP - Jan 97: Endian Ordering] */
+    FatalError (1, "Bad magic number in \"%s\".\n", FName);
+
+
+  /* open .invf.idx.ORG, rename .invf.idx if have to */
+  sprintf (FName, FILE_NAME_FORMAT ".ORG", pathname, filename, INVF_IDX_SUFFIX);  /* [RPAP - Feb 97: WIN32 Port] */
+  if (!(idx = fopen (FName, "rb")))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      char fname[256];
+      sprintf (fname, FILE_NAME_FORMAT, pathname, filename, INVF_IDX_SUFFIX);
+      rename (fname, FName);
+      if (!(idx = fopen (FName, "rb")))  /* [RPAP - Feb 97: WIN32 Port] */
+	FatalError (1, "Unable to open \"%s\".\n", FName);
+    }
+  else
+    {
+      char fname[256];
+      sprintf (fname, FILE_NAME_FORMAT, pathname, filename, INVF_IDX_SUFFIX);
+      unlink (fname);
+    }
+  Message ("Opening \"%s\"\n", FName);
+
+  /* check the magic number for .invf.idx.ORG */
+  if (fread (&magic, sizeof (magic), 1, idx) != 1 || NTOHUL(magic) != MAGIC_INVI)  /* [RPAP - Jan 97: Endian Ordering] */
+    FatalError (1, "Bad magic number in \"%s\".\n", FName);
+
+  sprintf (FName, FILE_NAME_FORMAT, pathname, filename, INVF_SUFFIX);  /* [RPAP - Feb 97: WIN32 Port] */
+  Message ("Creating \"%s\"\n", FName);
+  if (!(out = fopen (FName, "wb")))  /* [RPAP - Feb 97: WIN32 Port] */
+    FatalError (1, "Unable to open \"%s\".\n", FName);
+
+  sprintf (FName, FILE_NAME_FORMAT, pathname, filename, INVF_IDX_SUFFIX);  /* [RPAP - Feb 97: WIN32 Port] */
+  Message ("Creating \"%s\"\n", FName);
+  if (!(odx = fopen (FName, "wb")))  /* [RPAP - Feb 97: WIN32 Port] */
+    FatalError (1, "Unable to open \"%s\".\n", FName);
+
+  sprintf (FName, FILE_NAME_FORMAT, pathname, filename, INVF_DICT_SUFFIX);  /* [RPAP - Feb 97: WIN32 Port] */
+  Message ("Opening \"%s\"\n", FName);
+  if (!(dict = fopen (FName, "rb")))  /* [RPAP - Feb 97: WIN32 Port] */
+    FatalError (1, "Unable to open \"%s\".\n", FName);
+
+  if (fread (&magic, sizeof (magic), 1, dict) != 1 || NTOHUL(magic) != MAGIC_STEM_BUILD)  /* [RPAP - Jan 97: Endian Ordering] */
+    FatalError (1, "Bad magic number in \"%s\".\n", FName);
+
+  fread ((char *) &idh, sizeof (idh), 1, dict);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(idh.lookback);
+  NTOHUL(idh.dict_size);
+  NTOHUL(idh.total_bytes);
+  NTOHUL(idh.index_string_bytes);
+  NTOHD(idh.input_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(idh.num_of_docs);
+  NTOHUL(idh.static_num_of_docs);
+  NTOHUL(idh.num_of_words);
+  NTOHUL(idh.stemmer_num);
+  NTOHUL(idh.stem_method);
+
+  HTONUL2(MAGIC_INVF, magic);  /* [RPAP - Jan 97: Endian Ordering] */
+  fwrite ((char *) &magic, sizeof (magic), 1, out);
+
+  fread ((char *) &ifh_in, sizeof (ifh_in), 1, in);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(ifh_in.no_of_words);
+  NTOHUL(ifh_in.no_of_ptrs);
+  NTOHUL(ifh_in.skip_mode);
+  for (i = 0; i < 16; i++)
+    NTOHUL(ifh_in.params[i]);
+  NTOHUL(ifh_in.InvfLevel);
+
+  ifh_out = ifh_in;
+  ifh_out.skip_mode = outmode;
+  bzero ((char *) ifh_out.params, sizeof (ifh_out.params));
+  switch (outmode)
+    {
+    case 0:
+      break;
+    case 1:
+      ifh_out.params[0] = k;
+      break;
+    case 2:
+      ifh_out.params[0] = max_nodes;
+      ifh_out.params[1] = mins;
+      break;
+    }
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(ifh_out.no_of_words);
+  HTONUL(ifh_out.no_of_ptrs);
+  HTONUL(ifh_out.skip_mode);
+  for (i = 0; i < 16; i++)
+    HTONUL(ifh_out.params[i]);
+  HTONUL(ifh_out.InvfLevel);
+
+  fwrite ((char *) &ifh_out, sizeof (ifh_out), 1, out);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(ifh_out.no_of_words);
+  NTOHUL(ifh_out.no_of_ptrs);
+  NTOHUL(ifh_out.skip_mode);
+  for (i = 0; i < 16; i++)
+    NTOHUL(ifh_out.params[i]);
+  NTOHUL(ifh_out.InvfLevel);
+
+  Message ("The file is a level %d inverted file.\n", ifh_in.InvfLevel);
+
+  bits_out = ftell (out) * 8;
+
+
+  HTONUL2(MAGIC_INVI, magic);  /* [RPAP - Jan 97: Endian Ordering] */
+  fwrite ((char *) &magic, sizeof (magic), 1, odx);
+
+  DECODE_START (in)
+    DECODE_PAUSE (in_buf)
+
+    ENCODE_START (out)
+    ENCODE_PAUSE (out_buf)
+
+    N = idh.num_of_docs;
+
+  for (i = 0; i < ifh_in.no_of_words; i++)
+    {
+      unsigned long blk, p;
+      unsigned long odn_blk = 0, olen_blk = 0;
+      unsigned long idn_blk = 0, ilen_blk = 0;
+      register unsigned long suff;
+      unsigned long fcnt, wcnt, doc_num, bits_so_far, last_major;
+      unsigned long next_mjr_dn, kd;
+      char dummy2[MAXSTEMLEN + 1];
+      invf_info *ii;
+
+      fgetc (dict);
+      suff = fgetc (dict);
+      fread (dummy2, sizeof (u_char), suff, dict);
+      fread ((char *) &fcnt, sizeof (fcnt), 1, dict);
+      fread ((char *) &wcnt, sizeof (wcnt), 1, dict);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(fcnt);
+      NTOHUL(wcnt);
+
+      HTONUL2(bits_out >> 3, bytes_out);  /* [RPAP - Jan 97: Endian Ordering] */
+      fwrite ((char *) &bytes_out, sizeof (bytes_out), 1, odx);
+      NTOHUL(bytes_out);  /* [RPAP - Jan 97: Endian Ordering] */
+
+      p = fcnt;
+      blk = BIO_Bblock_Init (idh.static_num_of_docs, p);
+      switch (outmode)
+	{
+	case 1:
+	  {
+	    unsigned long len;
+	    if (p <= ifh_out.params[0])
+	      out_k = 0;
+	    else
+	      {
+		out_k = ifh_out.params[0];
+		len = BIO_Bblock_Bound (N, p);
+		if (ifh_in.InvfLevel >= 2)
+		  len += wcnt;
+		odn_blk = BIO_Bblock_Init (idh.num_of_docs, (p + out_k - 1) / out_k);
+		olen_blk = BIO_Bblock_Init (len, (p + out_k - 1) / out_k);
+	      }
+	    break;
+	  }
+	case 2:
+	  {
+	    unsigned long len;
+	    if (p <= mins)
+	      out_k = 0;
+	    else
+	      {
+		out_k = (int) (2 * sqrt ((double) p / max_nodes));
+		if (out_k <= mins)
+		  out_k = mins;
+		len = BIO_Bblock_Bound (N, p);
+		if (ifh_in.InvfLevel >= 2)
+		  len += wcnt;
+		odn_blk = BIO_Bblock_Init (idh.num_of_docs,
+					   (p + out_k - 1) / out_k);
+		olen_blk = BIO_Bblock_Init (len, (p + out_k - 1) / out_k);
+	      }
+	    break;
+	  }
+	default:
+	  out_k = 0;
+	}
+
+      switch (ifh_in.skip_mode)
+	{
+	case 1:
+	  {
+	    unsigned long len;
+	    if (p <= ifh_in.params[0])
+	      in_k = 0;
+	    else
+	      {
+		in_k = ifh_in.params[0];
+		len = BIO_Bblock_Bound (N, p);
+		if (ifh_in.InvfLevel >= 2)
+		  len += wcnt;
+		idn_blk = BIO_Bblock_Init (idh.num_of_docs, (p + in_k - 1) / in_k);
+		ilen_blk = BIO_Bblock_Init (len, (p + in_k - 1) / in_k);
+	      }
+	    break;
+	  }
+	case 2:
+	  {
+	    unsigned long len;
+	    if (p <= ifh_in.params[1])
+	      {
+		in_k = 0;
+	      }
+	    else
+	      {
+		in_k = (int) (2 * sqrt ((double) p / ifh_in.params[0]));
+		if (in_k <= ifh_in.params[1])
+		  in_k = ifh_in.params[1];
+		len = BIO_Bblock_Bound (N, p);
+		if (ifh_in.InvfLevel >= 2)
+		  len += wcnt;
+		idn_blk = BIO_Bblock_Init (idh.num_of_docs,
+					   (p + in_k - 1) / in_k);
+		ilen_blk = BIO_Bblock_Init (len, (p + in_k - 1) / in_k);
+	      }
+	    break;
+	  }
+	default:
+	  in_k = 0;
+	}
+
+      if (!(ii = Xmalloc (sizeof (invf_info) * p)))
+	FatalError (1, "Unable to allocate memory for \"ii\"\n");
+
+      doc_num = bits_so_far = 0;
+      next_mjr_dn = 0;
+      kd = 0;
+      DECODE_CONTINUE (in_buf)
+	for (j = 0; j < p; j++, kd++)
+	{
+	  unsigned long doc_diff, count = 0;
+	  if (kd == in_k)
+	    kd = 0;
+	  if (in_k && kd == 0 && j + in_k < p)
+	    {
+	      int temp;
+	      BBLOCK_DECODE (next_mjr_dn, idn_blk);
+	      next_mjr_dn += doc_num;
+	      BBLOCK_DECODE (temp, ilen_blk);
+	    }
+	  ii[j].bits_so_far = bits_so_far;
+	  if (in_k && kd == in_k - 1 && j != p - 1)
+	    {
+	      int count;
+	      BBLOCK_LENGTH (next_mjr_dn - doc_num, blk, count);
+	      bits_so_far += count;
+	      doc_num = next_mjr_dn;
+	    }
+	  else
+	    {
+	      BBLOCK_DECODE_L (doc_diff, blk, bits_so_far);
+	      doc_num += doc_diff;
+	    }
+	  ii[j].doc_num = doc_num;
+	  if (ifh_in.InvfLevel >= 2)
+	    {
+	      int count_bits = 0;
+	      GAMMA_DECODE_L (count, count_bits);
+	      ii[j].count_bits = count_bits;
+	      bits_so_far += count_bits;
+	      ii[j].count = count;
+	    }
+	}
+
+      /* read till a byte boundary */
+      while (__btg)
+	{
+	  DECODE_BIT;
+	  bits_so_far++;
+	}
+
+      DECODE_PAUSE (in_buf)
+
+	doc_num = bits_so_far = 0;
+      last_major = 0;
+      kd = 0;
+      ENCODE_CONTINUE (out_buf)
+	for (j = 0; j < p; j++, kd++)
+	{
+	  if (kd == out_k)
+	    kd = 0;
+	  if (out_k && kd == 0)
+	    {
+	      if (j + out_k < p)
+		{
+		  int num = ii[j + out_k - 1].doc_num - last_major;
+		  BBLOCK_ENCODE_L (num, odn_blk, bits_out);
+		  last_major = ii[j + out_k - 1].doc_num;
+
+		  num = ii[j + out_k - 1].bits_so_far + ii[j + out_k - 1].count_bits -
+		    bits_so_far;
+		  BBLOCK_ENCODE_L (num, olen_blk, bits_out);
+		  bits_so_far = ii[j + out_k].bits_so_far;
+		}
+	    }
+	  if (!(out_k && kd == out_k - 1 && j != p - 1))
+	    BBLOCK_ENCODE_L (ii[j].doc_num - doc_num, blk, bits_out);
+	  doc_num = ii[j].doc_num;
+	  if (ifh_in.InvfLevel >= 2)
+	    GAMMA_ENCODE_L (ii[j].count, bits_out);
+	}
+
+      /* write till a byte boundary */
+      while (__btg != 8)
+	{
+	  ENCODE_BIT (0);
+	  bits_out++;
+	}
+      ENCODE_PAUSE (out_buf)
+
+	Xfree (ii);
+
+    }
+  ENCODE_CONTINUE (out_buf)
+    ENCODE_DONE
+
+    HTONUL2(bits_out >> 3, bytes_out);  /* [RPAP - Jan 97: Endian Ordering] */
+  fwrite ((char *) &bytes_out, sizeof (bytes_out), 1, odx);
+  NTOHUL(bytes_out);
+
+  fclose (idx);
+  fclose (odx);
+  fclose (in);
+  fclose (out);
+  fclose (dict);
+
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_merge.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_merge.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_merge.h	(revision 14757)
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * mgmerge.h --- mgmerge #defines, etc
+ * Copyright (C) 1995  Shane Hudson (shane@cosc.canterbury.ac.nz)
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * Last edtited: November 12 1994
+ *
+ **************************************************************************/
+
+#ifndef MGMERGE_H
+#define MGMERGE_H
+
+typedef unsigned char byte;
+
+#define OLD 0
+#define NEW 1
+#define MERGE 2
+
+#define OK 0
+#define ERROR_MGMERGE 1
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/mg_passes.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_passes.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_passes.1	(revision 14757)
@@ -0,0 +1,441 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_passes 1 \*(Dt CITRI
+.SH NAME
+mg_passes \- builds mg databases
+.SH SYNOPSIS
+.B mg_passes
+[
+.B \-h
+]
+[
+.B \-G
+]
+[
+.B \-S
+]
+[
+.B \-D
+]
+[
+.B \-W
+]
+.if n .ti +9n
+[
+.BR \-1 " |"
+.BR \-2 " |"
+.B  \-3
+]
+[
+.BI \-C " compstatpoint"
+]
+.if n .ti +9n
+[
+.BI \-n " tracename"
+]
+.if t .ti +.5i
+[
+.BI \-b " bufsize"
+]
+[
+.BI \-m " memlimit"
+]
+.if n .ti +9n
+[
+.BI \-c " numchunks"
+]
+[
+.BI \-a " stemmer"
+]
+[
+.BI \-s " stemmethod"
+]
+[
+.BI \-t " tracepos"
+]
+.if n .ti +9n
+[
+.B \-T1
+]
+[
+.B \-T2
+]
+.if t .ti +.5i
+[
+.B \-I1
+]
+[
+.B \-I2
+]
+.if n .ti +9n
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+[
+.I filename(s)
+]
+.SH DESCRIPTION
+.B mg_passes
+is the program that does most of the work when building
+.BR mg (1)
+database systems.  The input documents can come from either
+.I stdin
+or from a list of files on the command line.  Individual documents
+must be separated with control-B characters.  In general,
+.B mg_passes
+must be run twice to build a database, first with the
+.B \-T1
+and
+.B \-I1
+options, and second with the
+.B \-T2
+and
+.B \-I2
+options.  Several other programs must be run in order to get an
+.BR mg (1)
+database that is ready for the
+.BR mgquery (1)
+program.  The
+.SB EXAMPLE
+section below gives an example of how to build a complete
+.BR mg (1)
+database.
+.SH OPTIONS
+Options may appear in any order, but the
+.IR filename(s) ,
+if specified, must be last.
+.TP "\w'\fB\-C\fP \fIcompstatpoint\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-G
+Treat SGML tags as non-words when building the inverted file.  An SGML
+tag is anything between angle brackets, i.e., `<' and `>'.
+.TP
+.B \-S
+This option causes a special pass to be executed.  It is up to a user
+to modify
+.I mg.special.c
+in the source code to do something with the documents it is given.
+.TP
+.B \-D
+If
+.B mg_passes
+fails, then print the document that caused the failure to the trace
+file if tracing is active, or to
+.I stderr
+if it is not.
+.TP
+.B \-W
+This option enables the generation of the weights file when
+.B \-I2
+is specified.  It causes
+.B \-I2
+to use a little more memory and CPU.
+.TP
+.B \-1
+Produce a level-1 inverted file.  This option is only useful when
+specified with
+.BR "\-I1 ".
+A level-1 inverted file makes it possible for
+.BR mgquery (1)
+to do Boolean queries.  Ranked queries can still be done,
+although the quality of the ranking is abysmal.
+.TP
+.B \-2
+Produce a level-2 inverted file.  This option is only useful when
+specified with
+.BR "\-I1 ".
+This is the default when neither
+.BR \-1 ", " "\-2 " "or " \-3
+is specified.
+A level-2 inverted file makes it possible for
+.BR mgquery (1)
+to do Boolean queries and cosine-ranked queries.
+.TP
+.B \-3
+Produce a level-3 inverted file.  This option is only useful when
+specified with
+.BR "\-I1 ".
+This has been implemented to enable paragraph-level inversion.
+Paragraphs are delimited by control-C characters in the source text.
+.TP
+.BI \-C " compstatpoint"
+This option causes statistics on the compression performance to be
+output to a file called
+.IR *.compression.stats .
+.I compstatpoint
+specifies the interval between outputting each line of statistics.  The
+units of
+.I compstatpoint
+are kilobytes of source text.  E.g., if
+.I compstatpoint
+is 10, then a line is output to the file every 10 KB of input
+source.  Each line of the file consists of 4 numbers The first number
+is the amount of input text, in bytes, processed so far.  The second
+number is the amount of input text, in bytes, processed since the
+last line was output to the file.  The third number is the number of
+output bytes generated since the last line was output to the file, and
+the fourth number is the compression achieved since the last line was
+output, i.e., the third number divided by the second number.
+.TP
+.BI \-n " tracename"
+This specifies the filename to use for the trace log, if tracing is
+enabled using the
+.B \-t
+option.  If
+.BI \-n " tracename"
+is not given and tracing is enabled, a default trace filename will be
+used.
+.TP
+.BI \-s " stemmethod"
+This specifies the method to use to \*(lqstem\*(rq the words in the
+inverted file dictionary.  This is a bit mask specifying the
+operations to do on words as they are parsed out of the text, where
+bit number 0 is the low-order (rightmost) bit.  Bit 0 does case
+folding, and bit 1 does simple stemming, so the value 3 for
+.I stemmethod
+does both case folding and stemming.
+.TP
+.BI \-a " stemmer"
+This specifies the stemmer to use when stemming words.  This
+is a description of the language the stemmer is intended for
+or a description of the stemmer.  Valid options include:
+english, lovin, french, and simplefrench.
+.TP
+.BI \-b " bufsize"
+Specify the size of the document buffer in kilobytes.  If any document
+is larger than
+.IR bufsize ,
+the program will abort with an error message.  This should probably be
+replaced with some system which automatically increases the buffer
+size as required.  The default size is 3072 KB (3 MB).
+.TP
+.BI \-m " memlimit"
+Maximum amount of memory to use for the pass-2 file inversion in
+megabytes.  This option is only useful when used in conjunction with
+the option
+.BR \-I1 .
+The larger this value, the faster the pass-2 inversion will proceed.
+The default value is 5 MB.
+.TP
+.BI \-c " numchunks"
+The maximum number of inversion chunks to write to disk.  Each chunk
+will be approximately as large as
+.IR memlimit .
+This option is only useful when used in conjunction with the option
+.BR \-I2 .
+The larger this value, the faster the pass-2 inversion will proceed.
+The default value is 5 MB.
+.TP
+.BI \-t " tracepos"
+This option activates tracing.  A line will be generated in the
+trace file for every
+.I tracepos
+input bytes processed.  The default name for the trace file can be
+overridden using the
+.BI \-n " tracename"
+option.
+.TP
+.B \-T1
+Generate the
+.I *.text.stats
+file.
+.TP
+.B \-T2
+Generate the
+.IR *.text ,
+.IR *.text.idx ,
+and possibly the
+.I *.text.dict.aux
+files.  Using this option requires that the
+.I *.text.dict
+file be present.
+.TP
+.B \-I1
+Generate the
+.IR *.invf.dict ,
+.IR *.invf.chunk ,
+and
+.I *.invf.chunk.trans
+files.
+.TP
+.B \-I2
+Generate the
+.I *.invf
+and
+.I *.invf.idx
+files.  Using this option requires
+that the
+.IR *.invf.dict.hash ,
+.IR *.invf.chunk ,
+and
+.I *.invf.chunk.trans
+files
+be present.  The
+.I *.invf.dict.hash
+file is generated by
+.BR mg_perf_hash_build (1)
+from the
+.I *.invf.dict.build
+file.  If the
+.B \-W
+option is specified, the
+.I *.weight
+file will also be generated.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection is to be
+written.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection that will be
+created.
+.TP
+.I filename(s)
+This specifies the source text. If this is not specified, then the
+program expects the source text from
+.IR stdin .
+.SH EXAMPLE
+What follows is a UNIX
+.BR csh (1)
+script as an example of how to build an
+.BR mg (1)
+document collection.
+.LP
+.nf
+.DT
+.ft B
+.I #! /bin/csh
+.I
+# The first argument on the command line specifies the
+.I
+#   source of the text
+set source = ($1)
+.PP
+.I
+# The second argument is the name of the collection
+set text = ($2)
+.PP
+.I
+# Create *.text.stats,  *.invf.dict.build,
+.I
+#   *.invf.chunk and *.invf.chunks.trans
+${source} | mg_passes -T1 -I1 -m 1 -t 1 -f ${text}
+.PP
+.I
+# Create *.text.dict
+mg_compression_dict -f ${text}
+.PP
+.I
+# Create *.invf.dict.hash
+mg_perf_hash_build -f ${text}
+.PP
+.I
+# Create *.text,  *.text.idx,
+.I
+#   *.invf and *.invf.idx
+${source} | mg_passes -T2 -I2 -c 2 -t 1 -f ${text}
+.PP
+.I
+# Create *.text.idx.wgt and *.weight.approx
+mg_weights_build -f ${text} -b 8
+.PP
+.I
+# Create *.invf.dict
+mg_invf_dict -f ${text} -b 4096
+.PP
+.I
+# Create *.text.dict
+mg_fast_comp_dict -f ${text}
+.ft R
+.fi
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.chunk
+Inverted file chunk descriptor file.  When the inverted file is
+created it is created in chunks that use no more than a set amount of
+memory.  This file describes those chunks.
+.TP
+.B *.invf.chunk.trans
+Word-occurrence-order to lexical-order translation file.  The
+.B *.invf.chunk
+file is written in word-occurrence order but is required by
+.B \-I2
+to be in lexical order.
+.TP
+.B *.invf.dict.build
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict.hash
+Data for an order-preserving perfect hash function.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.B *.text
+Compressed documents.
+.TP
+.B *.text.stats
+Statistics about the text.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.trace
+The default trace file.
+.TP
+.B *.compression.stats
+Statistics about the compression of the text.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_passes.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_passes.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_passes.c	(revision 14757)
@@ -0,0 +1,641 @@
+/**************************************************************************
+ *
+ * mg_passes.c -- Driver for the various passes
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#ifdef HAVE_MALLINFO
+# include <malloc.h> 
+#endif
+#include <stdlib.h>
+#include "memlib.h"
+#include "messages.h"
+#include "timing.h"
+
+#include "longlong.h"
+
+#include "mg_files.h"
+#include "mg.h"
+#include "build.h"
+#include "text.h"
+#include "stemmer.h"
+
+#include "words.h"
+
+/*
+   $Log$
+   Revision 1.3  2004/11/29 03:15:13  kjdon
+   added some changes made by Emanuel Dejanu (Simple Words)
+
+   Revision 1.2  2004/04/25 23:01:18  kjdon
+   added a new -M option to mg_passes, allowing maxnumeric to be altered - made this change to keep gsdl3 mg inline with gsdl2 mg.
+
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.3  2001/09/21 12:46:42  kjm18
+   updated mg to be in line with mg_1.3f. Now uses long long for some variables
+   to enable indexing of very large collections.
+
+   Revision 1.2  2001/06/12 23:23:42  jrm21
+   fixed a bug where mg_passes segfaults when trying to print the usage message.
+
+   Revision 1.1  1999/08/10 21:18:12  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.3  1998/12/17 09:12:53  rjmcnab
+
+   Altered mg to process utf-8 encoded Unicode. The main changes
+   are in the parsing of the input, the casefolding, and the stemming.
+
+   Revision 1.2  1998/11/25 07:55:47  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:13  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:56:57  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:52  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+#define MAX_PASSES 5
+
+#define SPECIAL 1
+#define TEXT_PASS_1 2
+#define TEXT_PASS_2 4
+#define IVF_PASS_1 8
+#define IVF_PASS_2 16
+
+#define MIN_BUF 8192
+#define	TERMRECORD	'\002'
+
+unsigned long buf_size = 3 * 1024 * 1024;	/* 3Mb */
+unsigned long invf_buffer_size = 5 * 1024 * 1024;	/* 5Mb */
+unsigned long ChunkLimit = 0;
+char InvfLevel = 2;
+char SkipSGML = 0;
+char MakeWeights = 0;
+FILE *Comp_Stats = NULL;
+int comp_stat_point = 0;
+mg_ullong bytes_processed = 0;
+mg_ullong bytes_received = 0;
+int stemmer_num = 0; /* default to the lovin stemmer */
+int stem_method = 0;
+
+static char Passes = 0;
+static unsigned long trace = 0;
+static int Dump = 0;
+static char **files = NULL;
+static int num_files = 0;
+static char *trace_name = NULL;
+
+
+typedef struct pass_data
+  {
+    char *name;
+    int (*init) (char *);
+    int (*process) (u_char *, int);
+    int (*done) (char *);
+#ifdef HAVE_TIMES
+    clock_t init_time;
+    clock_t process_time;
+    clock_t done_time;
+#else
+    struct timeval init_time;
+    struct timeval process_time;
+    struct timeval done_time;
+#endif
+  }
+pass_data;
+
+#ifdef HAVE_TIMES
+#define NULL_TIMES 0, 0, 0
+#else
+#define NULL_TIMES {0, 0}, {0, 0}, {0, 0}
+#endif
+
+static pass_data PassData[MAX_PASSES] =
+{
+  {"special", init_special, process_special, done_special, NULL_TIMES},
+  {"text.pass1", init_text_1, process_text_1, done_text_1, NULL_TIMES},
+  {"text.pass2", init_text_2, process_text_2, done_text_2, NULL_TIMES},
+  {"ivf.pass1", init_ivf_1, process_ivf_1, done_ivf_1, NULL_TIMES},
+  {"ivf.pass2", init_ivf_2, process_ivf_2, done_ivf_2, NULL_TIMES},
+};
+
+static char *usage_str = "\nUSAGE:\n"
+"  %s [-h] [-G] [-D] [-1|-2|-3] [-T1] [-T2] [-I1] [-I2] [-N1]\n"
+"  %*s [-N2] [-W] [-S] [-b buffer-size] [-d dictionary-directory]\n"
+"  %*s [-t trace-point Mb] [-m invf-memory] [-c chunk-limit]\n"
+"  %*s [-n trace-name] [-C comp-stat-size] [-s stem_method]\n"
+"  %*s [-a stemmer] [-M max-numeric] -f doc-collection-name\n";
+
+
+static void 
+usage (char *err)
+{
+  if (err)
+    Message (err);
+  fprintf (stderr, usage_str, msg_prefix, strlen (msg_prefix), "",
+	   strlen (msg_prefix), "",strlen (msg_prefix), "",
+	   strlen (msg_prefix),"");
+  exit (1);
+}
+
+
+
+
+#if 0
+static char *
+str_comma (unsigned long u)
+{
+  static char buf[20];
+  unsigned long a, b, c, d;
+  a = u / 1000000000;
+  u -= a * 1000000000;
+  b = u / 1000000;
+  u -= b * 1000000;
+  c = u / 1000;
+  u -= c * 1000;
+  d = u;
+
+  if (a)
+    sprintf (buf, "%u,%03u,%03u,%03u", a, b, c, d);
+  else if (b)
+    sprintf (buf, "%u,%03u,%03u", b, c, d);
+  else if (c)
+    sprintf (buf, "%u,%03u", c, d);
+  else
+    sprintf (buf, "%u", d);
+  return (buf);
+}
+#endif
+
+
+
+
+int 
+open_next_file (int in_fd)
+{
+  if (in_fd > 0)
+    close (in_fd);
+  if (num_files == 0)
+    return (-1);
+  if ((in_fd = open (files[0], O_RDONLY)) == -1)
+    FatalError (1, "Cannot open %s", files[0]);
+  files++;
+  num_files--;
+  return (in_fd);
+}
+
+
+static void 
+driver (int in_fd, FILE * Trace, char *file_name)
+{
+  int pass, num = 1;
+
+  char *buffer = Xmalloc (buf_size);
+  unsigned long num_docs = 0;
+  unsigned long block_bytes = 0;
+  register int buf_left = buf_size;
+  register char *look_pos = buffer;
+  register char *end_pos = buffer;
+
+  ProgTime StartTime, InitTime, ProcTime, DoneTime;
+
+  GetTime (&StartTime);
+
+  for (pass = 0; pass < MAX_PASSES; pass++)
+    if (Passes & (1 << pass))
+      {
+	pass_data *pd = &PassData[pass];
+#ifdef HAVE_TIMES
+	struct tms tims;
+	times (&tims);
+	pd->init_time -= tims.tms_utime + tims.tms_stime;
+#elif defined(HAVE_GETRUSAGE)  /* [RPAP - Feb 97: WIN32 Port] */
+	struct rusage ru;
+
+	getrusage (RUSAGE_SELF, &ru);
+	pd->init_time.tv_sec -= ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+	pd->init_time.tv_usec -= ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+#endif
+	if (pd->init (file_name) == COMPERROR)
+	  FatalError (1, "Error during init of \"%s\"", pd->name);
+
+#ifdef HAVE_TIMES
+	times (&tims);
+	pd->init_time += tims.tms_utime + tims.tms_stime;
+#elif defined(HAVE_GETRUSAGE)  /* [RPAP - Feb 97: WIN32 Port] */
+	getrusage (RUSAGE_SELF, &ru);
+	pd->init_time.tv_sec += ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+	pd->init_time.tv_usec += ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+	time_normalise (&pd->init_time);
+#endif
+      }
+
+  GetTime (&InitTime);
+  for (;;)
+    {
+      int len = 0;
+      char *base = look_pos;
+
+      while (look_pos != end_pos && *look_pos != TERMRECORD)
+	look_pos++;
+
+      while (look_pos == end_pos)
+	{
+	  if (buf_left < MIN_BUF)
+	    {
+	      bcopy (base, buffer, end_pos - base);
+	      look_pos = buffer + (end_pos - base);
+	      buf_left = buf_size - (end_pos - base);
+	      end_pos = look_pos;
+	      base = buffer;
+	    }
+	  if (buf_left)
+	    {
+    	      num = read (in_fd, end_pos, buf_left);
+	      if (num < 0) num = 0; /* RJM - quick hack :-) */
+	      if (num == 0)
+		if ((in_fd = open_next_file (in_fd)) != -1)
+		  num = read (in_fd, end_pos, buf_left);
+	      bytes_received += num;
+	      buf_left -= num;
+	      end_pos += num;
+	    }
+	  while (look_pos < end_pos && *look_pos != TERMRECORD)
+	    look_pos++;
+	  if (buf_left == 0 && base == buffer && look_pos == end_pos)
+	    {
+	      Message ("Unable to find document terminator (i.e ^B)"
+		       " in the document");
+	      FatalError (1, "The document is in excess of %d chars long",
+			  look_pos - base);
+	    }
+	  if (!num)
+	    break;
+	}
+      len = look_pos++ - base;
+
+      if (!num && base == end_pos)
+	break;
+
+      bytes_processed += len;
+
+#ifndef QUIET
+      if (!len)
+	Message ("Warning : Processing zero length document");
+#endif
+
+      for (pass = 0; pass < MAX_PASSES; pass++)
+	if (Passes & (1 << pass))
+	  {
+	    register pass_data *pd = &PassData[pass];
+
+#ifdef HAVE_TIMES
+	    struct tms tims;
+	    times (&tims);
+	    pd->process_time -= tims.tms_utime + tims.tms_stime;
+#elif defined(HAVE_GETRUSAGE)  /* [RPAP - Feb 97: WIN32 Port] */
+	    struct rusage ru;
+	    register struct timeval *tv = &pd->process_time;
+
+	    getrusage (RUSAGE_SELF, &ru);
+	    tv->tv_sec -= ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+	    tv->tv_usec -= ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+#endif
+
+	    if (pd->process ((u_char *) base, len) == COMPERROR)
+	      {
+		Message ("Error during processing of \"%s\"", pd->name);
+		if (Dump || Trace)
+		  {
+		    int i;
+		    FILE *f = Trace ? Trace : stderr;
+		    fprintf (f, "-=- * -=- * -=- * -=- * -=- * -=- * -=-\n");
+		    for (i = 0; i < len; i++)
+		      {
+			char ch = base[i];
+			if (ch == '\1' || ch == '\2')
+			  ch = '\n';
+			putc (ch, f);
+		      }
+		    fprintf (f, "-=- * -=- * -=- * -=- * -=- * -=- * -=-\n");
+		  }
+		if (Trace)
+		  fprintf (Trace, "%11" ULL_FS " bytes |%7lu docs | %s\n",
+			   bytes_processed, num_docs,
+			   ElapsedTime (&StartTime, NULL));
+		exit (1);
+	      }
+
+#ifdef HAVE_TIMES
+	    times (&tims);
+	    pd->process_time += tims.tms_utime + tims.tms_stime;
+#elif defined(HAVE_GETRUSAGE)  /* [RPAP - Feb 97: WIN32 Port] */
+	    getrusage (RUSAGE_SELF, &ru);
+	    tv->tv_sec += ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+	    tv->tv_usec += ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+#endif
+	  }
+      num_docs++;
+      if (Trace)
+	{
+	  block_bytes += (look_pos - base);
+	  if (block_bytes >= trace)
+	    {
+#ifdef HAVE_MALLINFO
+	      struct mallinfo mi;
+	      mi = mallinfo ();
+	      block_bytes -= trace;
+	      fprintf (Trace, "%11" ULL_FS " bytes |%7lu docs |%7.3f Mb | %s\n",
+		       bytes_processed, num_docs, mi.arena / 1024.0 / 1024.0,
+		       ElapsedTime (&StartTime, NULL));
+#else
+	      block_bytes -= trace;
+	      fprintf (Trace, "%11" ULL_FS " bytes |%7lu docs | %s\n",
+		       bytes_processed, num_docs,
+		       ElapsedTime (&StartTime, NULL));
+#endif
+	    }
+	}
+      if (!num && look_pos - 1 == end_pos)
+	break;
+    }
+
+#ifndef HAVE_TIMES
+  for (pass = 0; pass < MAX_PASSES; pass++)
+    if (Passes & (1 << pass))
+      time_normalise (&PassData[pass].process_time);
+#endif
+
+  GetTime (&ProcTime);
+
+  for (pass = 0; pass < MAX_PASSES; pass++)
+    if (Passes & (1 << pass))
+      {
+	pass_data *pd = &PassData[pass];
+#ifdef HAVE_TIMES
+	struct tms tims;
+	times (&tims);
+	pd->done_time -= tims.tms_utime + tims.tms_stime;
+#elif defined(HAVE_GETRUSAGE)  /* [RPAP - Feb 97: WIN32 Port] */
+	struct rusage ru;
+
+	getrusage (RUSAGE_SELF, &ru);
+	pd->done_time.tv_sec -= ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+	pd->done_time.tv_usec -= ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+#endif
+	if (pd->done (file_name) == COMPERROR)
+	  FatalError (1, "Error during done of \"%s\"", pd->name);
+
+#ifdef HAVE_TIMES
+	times (&tims);
+	pd->done_time += tims.tms_utime + tims.tms_stime;
+#elif defined(HAVE_GETRUSAGE)  /* [RPAP - Feb 97: WIN32 Port] */
+	getrusage (RUSAGE_SELF, &ru);
+	pd->done_time.tv_sec += ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+	pd->done_time.tv_usec += ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+	time_normalise (&pd->done_time);
+#endif
+      }
+  if (Trace)
+    {
+#ifdef HAVE_MALLINFO
+      struct mallinfo mi;
+      mi = mallinfo ();
+      fprintf (Trace, "%11" ULL_FS " bytes |%7lu docs |%7.3f Mb | %s\n",
+	       bytes_processed, num_docs, mi.arena / 1024.0 / 1024.0,
+	       ElapsedTime (&StartTime, NULL));
+#else
+      fprintf (Trace, "%11" ULL_FS " bytes |%7lu docs | %s\n",
+	       bytes_processed, num_docs,
+	       ElapsedTime (&StartTime, NULL));
+#endif
+    }
+
+  GetTime (&DoneTime);
+
+  Message ("");
+  Message ("%10s      :    init         process        done", "");
+  for (pass = 0; pass < MAX_PASSES; pass++)
+    if (Passes & (1 << pass))
+      {
+	pass_data *pd = &PassData[pass];
+	char it[15], pt[15], dt[15];
+#ifdef HAVE_TIMES
+	strcpy (it, cputime_string (pd->init_time));
+	strcpy (pt, cputime_string (pd->process_time));
+	strcpy (dt, cputime_string (pd->done_time));
+#else
+	strcpy (it, cputime_string (&pd->init_time));
+	strcpy (pt, cputime_string (&pd->process_time));
+	strcpy (dt, cputime_string (&pd->done_time));
+#endif
+	Message ("%-10s      : %s   %s   %s", pd->name, it, pt, dt);
+      }
+  Message ("");
+  Message ("Init time       : %s", ElapsedTime (&StartTime, &InitTime));
+  Message ("Process time    : %s", ElapsedTime (&InitTime, &ProcTime));
+  Message ("Done time       : %s", ElapsedTime (&ProcTime, &DoneTime));
+  Message ("Total time      : %s", ElapsedTime (&StartTime, &DoneTime));
+  Message ("Documents       : %u", num_docs);
+  Message ("Bytes received  : %" ULL_FS, bytes_received);
+  Message ("Bytes processed : %" ULL_FS, bytes_processed);
+  Message ("Process Rate    : %.1f kB per cpu second",
+   (double) bytes_processed / (ProcTime.CPUTime - InitTime.CPUTime) / 1024);
+  free (buffer);
+}
+
+
+
+int main (int argc, char **argv)
+{
+  int ch, in_fd;
+  char *filename = NULL;
+  FILE *Trace = NULL;
+
+  msg_prefix = argv[0];
+
+  opterr = 0;
+  while ((ch = getopt (argc, argv, "hC:WGSD123f:d:b:T:I:t:m:N:c:n:s:a:M:")) != -1)
+    {
+      switch (ch)
+	{
+	case 'G':
+	  SkipSGML = 1;
+	  break;
+	case 'S':
+	  Passes |= SPECIAL;
+	  break;
+	case '1':
+	  InvfLevel = 1;
+	  break;
+	case '2':
+	  InvfLevel = 2;
+	  break;
+	case '3':
+	  InvfLevel = 3;
+	  break;
+	case 'f':
+	  filename = optarg;
+	  break;
+	case 'n':
+	  trace_name = optarg;
+	  break;
+	case 'D':
+	  Dump = 1;
+	  break;
+	case 'W':
+	  MakeWeights = 1;
+	  break;
+	case 'd':
+	  set_basepath (optarg);
+	  break;
+	case 'a':
+	  stemmer_num = stemmernumber (optarg);
+	  break;
+	case 's':
+	  stem_method = atoi (optarg) & STEMMER_MASK;
+	  break;
+	case 'b':
+	  buf_size = atoi (optarg) * 1024;
+	  break;
+	case 'C':
+	  comp_stat_point = atoi (optarg) * 1024;
+	  break;
+	case 'c':
+	  ChunkLimit = atoi (optarg);
+	  break;
+	case 'm':
+	  invf_buffer_size = (int) (atof (optarg) * 1024 * 1024);
+	  break;
+	case 'I':
+	case 'N': /* N kept for compatability */
+	  if (*optarg == '1')
+	    Passes |= IVF_PASS_1;
+	  else if (*optarg == '2')
+	    Passes |= IVF_PASS_2;
+	  else
+	    usage ("Invalid pass number");
+	  break;
+	case 'T':
+	  if (*optarg == '1')
+	    Passes |= TEXT_PASS_1;
+	  else if (*optarg == '2')
+	    Passes |= TEXT_PASS_2;
+	  else
+	    usage ("Invalid pass number");
+	  break;
+	case 't':
+	  trace = (unsigned long) (atof (optarg) * 1024 * 1024);
+	  break;
+	case 'M':
+	  SetEnv ("maxnumeric", optarg, NULL);
+	  break;
+	case 'h':
+	case '?':
+	  usage (NULL);
+	}
+    }
+
+  if (!filename || *filename == '\0')
+    FatalError (1, "A document collection name must be specified.");
+
+  if (buf_size < MIN_BUF)
+    FatalError (1, "The buffer size must exceed 1024 bytes.");
+
+  if ((Passes & (IVF_PASS_1 | IVF_PASS_2)) == (IVF_PASS_1 | IVF_PASS_2))
+    FatalError (1, "I1 and I2 cannot be done simultaneously.");
+
+  if ((Passes & (TEXT_PASS_1 | TEXT_PASS_2)) == (TEXT_PASS_1 | TEXT_PASS_2))
+    FatalError (1, "T1 and T2 cannot be done simultaneously.");
+
+  if (!Passes)
+    FatalError (1, "S, T1, T2, I1 or I2 must be specified.");
+
+  if (optind < argc)
+    {
+      if ((in_fd = open (argv[optind], O_RDONLY)) == -1)
+	FatalError (1, "Cannot open %s", argv[optind]);
+      files = &argv[optind + 1];
+      num_files = argc - (optind + 1);
+    }
+  else
+    in_fd = 0;			/* stdin */
+
+
+  if (trace)
+    {
+      if (!trace_name)
+	trace_name = make_name (filename, TRACE_SUFFIX, NULL);
+      if (!(Trace = fopen (trace_name, "a")))
+	Message ("Unable to open \"%s\". No tracing will be done.", trace_name);
+      else
+	setbuf (Trace, NULL);
+    }
+  else
+    Trace = NULL;
+
+  if (comp_stat_point)
+    {
+      char *name = make_name (filename, COMPRESSION_STATS_SUFFIX, NULL);
+      if (!(Comp_Stats = fopen (name, "wb")))  /* [RPAP - Feb 97: WIN32 Port] */
+	Message ("Unable to open \"%s\". No comp. stats. will be generated.",
+		 name);
+    }
+
+
+  if (Trace)
+    {
+      int i;
+      fprintf (Trace, "\n\n\t\t-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n");
+      for (i = 0; i < argc; i++)
+	fprintf (Trace, "%s ", argv[i]);
+      fprintf (Trace, "\n\n");
+    }
+
+  driver (in_fd, Trace, filename);
+
+  if (Trace)
+    fclose (Trace);
+
+  if (Comp_Stats)
+    fclose (Comp_Stats);
+
+  return 0;
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_passes_4jni.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_passes_4jni.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_passes_4jni.c	(revision 14757)
@@ -0,0 +1,546 @@
+/**************************************************************************
+ *
+ * mg_passes_4jni.c -- Driver for the various passes
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+/* this needs to come first */
+#include "sysfuncs.h"
+
+#ifdef HAVE_MALLINFO
+# include <malloc.h> 
+#endif
+
+#include "mg_passes_4jni.h"
+#include "memlib.h"
+#include "messages.h"
+#include "timing.h"
+
+#include "longlong.h"
+#include "stemmer.h"
+
+#include "mg_files.h"
+#include "mg.h"
+#include "build.h"
+#include "text.h"
+
+#include "words.h"
+#include "environment.h"
+
+static char *RCSID = "$Id$";
+
+#define MAX_PASSES 5
+
+#define SPECIAL 1
+#define TEXT_PASS_1 2
+#define TEXT_PASS_2 4
+#define IVF_PASS_1 8
+#define IVF_PASS_2 16
+
+#define MIN_BUF 8192
+#define	TERMRECORD	'\002'
+
+unsigned long buf_size = 3 * 1024 * 1024;	/* 3Mb */
+unsigned long invf_buffer_size = 5 * 1024 * 1024;	/* 5Mb */
+unsigned long ChunkLimit = 0;
+char InvfLevel = 2;
+char SkipSGML = 0;
+char MakeWeights = 0;
+FILE *Comp_Stats = NULL;
+int comp_stat_point = 0;
+mg_ullong bytes_processed = 0;
+mg_ullong bytes_received = 0;
+int stemmer_num = 0; /* default to the lovin stemmer */
+int stem_method = 0;
+FILE * Trace;
+char * filename;
+unsigned long num_docs = 0;
+unsigned long block_bytes = 0;
+
+static char Passes = 0;
+static unsigned long trace = 0;
+static int Dump = 0;
+static char **files = NULL;
+static int num_files = 0;
+static char *trace_name = NULL;
+
+int mg_passes_exit_value = 0;
+
+typedef struct pass_data
+  {
+    char *name;
+    int (*init) (char *);
+    int (*process) (u_char *, int);
+    int (*done) (char *);
+#ifdef HAVE_TIMES
+    clock_t init_time;
+    clock_t process_time;
+    clock_t done_time;
+#else
+    struct timeval init_time;
+    struct timeval process_time;
+    struct timeval done_time;
+#endif
+  }
+pass_data;
+
+#ifdef HAVE_TIMES
+#define NULL_TIMES 0, 0, 0
+#else
+#define NULL_TIMES {0, 0}, {0, 0}, {0, 0}
+#endif
+
+static pass_data PassData[MAX_PASSES] =
+{
+  {"special", init_special, process_special, done_special, NULL_TIMES},
+  {"text.pass1", init_text_1, process_text_1, done_text_1, NULL_TIMES},
+  {"text.pass2", init_text_2, process_text_2, done_text_2, NULL_TIMES},
+  {"ivf.pass1", init_ivf_1, process_ivf_1, done_ivf_1, NULL_TIMES},
+  {"ivf.pass2", init_ivf_2, process_ivf_2, done_ivf_2, NULL_TIMES},
+};
+
+
+/* clear all the settings from one mg_passes run to the next */
+void clear_variables() {
+
+  buf_size = 3 * 1024 * 1024;	/* 3Mb */
+  invf_buffer_size = 5 * 1024 * 1024;	/* 5Mb */
+  ChunkLimit = 0;
+  InvfLevel = 2;
+  SkipSGML = 0;
+  MakeWeights = 0;
+  Comp_Stats = NULL;
+  comp_stat_point = 0;
+  bytes_processed = 0;
+  bytes_received = 0;
+  stemmer_num = 0; /* default to the lovin stemmer */
+  stem_method = 0;
+  Trace = NULL;
+  filename = NULL;
+  num_docs = 0;
+  block_bytes = 0;
+  
+  Passes = 0;
+  trace = 0;
+  Dump = 0;
+  files = NULL;
+  num_files = 0;
+  trace_name = NULL;
+  
+  mg_passes_exit_value = 0;
+}
+
+/* ################################################## */
+/* the following are methods to set all the variables that used to be
+   set by command line args */
+
+/* -S, -T1, -T2, -I1, -I2, args to mg_passes */
+void add_pass (char pass_type, char pass_num) {
+
+  switch(pass_type) {
+  case 'S':
+    Passes |= SPECIAL;
+    break;
+  case 'I':
+  case 'N':
+    if (pass_num == '1')
+      Passes |= IVF_PASS_1;
+    else if (pass_num == '2')
+      Passes |= IVF_PASS_2;
+    else
+      fprintf(stderr, "Invalid pass number %c for pass type %c\n", pass_num, pass_type);
+    break;
+  case 'T':
+    if (pass_num == '1')
+      Passes |= TEXT_PASS_1;
+    else if (pass_num == '2')
+      Passes |= TEXT_PASS_2;
+    else
+      fprintf(stderr, "Invalid pass number %c for pass type %c\n", pass_num, pass_type);
+    break;
+  }
+}
+
+/* -D arg to mg_passes */
+void dump_failed_document(int dump) {
+  Dump = dump;
+}
+
+/* -G arg to mg_passes */
+void ignore_sgml_tags(int ignore) {
+  if (ignore) {
+    SkipSGML = 1;
+  } else {
+    SkipSGML = 0;
+  }
+}
+
+/* -b arg to mg_passes */
+void set_buffer_size(long size) {
+  buf_size = size * 1024;
+  if (buf_size <  MIN_BUF) {
+    buf_size = MIN_BUF;
+  }
+}
+
+/* -c arg to mg_passes */
+void set_chunk_limit(long chunk_limit) {
+  ChunkLimit = chunk_limit;
+}
+
+/* -C arg to mg_passes */
+void set_comp_stat_point(int stat_point) {
+  comp_stat_point = stat_point * 1024;
+}
+
+/* -f arg to mg_passes */
+void set_filename(const char * filen) {
+  if (filename) {
+    Xfree (filename);
+    filename = NULL;
+  }
+  filename = Xstrdup (filen);  
+}
+
+/* -m arg to mg_passes */
+void set_inversion_limit(int limit) {
+  invf_buffer_size = limit * 1024 * 1024;
+}
+
+/* -1, -2, -3 args to mg_passes */
+void set_invf_level(char level) {
+  switch (level) {
+  case '1':
+    InvfLevel = 1;
+    break;
+  case '2':
+    InvfLevel = 2;
+    break;
+  case '3':
+    InvfLevel = 3;
+    break;
+  }
+}
+
+/* -W arg to mg_passes */
+void set_make_weights(int make_w) {
+  MakeWeights = make_w;
+}
+
+/* -M arg to mg_passes */
+void set_max_numeric(int max_numeric) {
+  char data[99];
+  sprintf(data, "%d", max_numeric);
+  SetEnv ("maxnumeric", data, NULL);
+}
+
+/* -a, -s args to mg_passes */
+void set_stem_options(const char * stemmer, int method) {
+  stemmer_num = stemmernumber (stemmer);
+  stem_method = method & STEMMER_MASK;
+}
+
+/* -t arg to mg_passes */
+void set_trace_point(int tracepos) {
+  trace = (unsigned long) (tracepos * 1024 * 1024);
+}
+
+/* -n arg to mg_passes */
+void set_trace_file(const char * filen) {
+  if (trace_name) {
+    Xfree (trace_name);
+    trace_name = NULL;
+  }
+  trace_name = Xstrdup (filen);
+}
+
+/* ############################################### */
+/* The old driver method has been split into 3:
+init_driver, process_document (called numdocs times), 
+finalise_driver.
+The above set vars methods should all be called before init_driver.
+*/
+
+
+ProgTime StartTime, InitTime, ProcTime, DoneTime;
+
+void 
+init_driver ()
+{
+  int pass;
+  if (!filename || *filename == '\0') {
+    mg_passes_exit_value = 1;
+    FatalError (1, "A document collection name must be specified.");
+  }
+
+  if ((Passes & (IVF_PASS_1 | IVF_PASS_2)) == (IVF_PASS_1 | IVF_PASS_2)) {
+    mg_passes_exit_value = 1;
+    FatalError (1, "I1 and I2 cannot be done simultaneously.");
+
+  }
+  if ((Passes & (TEXT_PASS_1 | TEXT_PASS_2)) == (TEXT_PASS_1 | TEXT_PASS_2)) {
+    mg_passes_exit_value = 1;
+    FatalError (1, "T1 and T2 cannot be done simultaneously.");
+  }
+  if (!Passes) {
+    mg_passes_exit_value = 1;
+    FatalError (1, "S, T1, T2, I1 or I2 must be specified.");
+  }
+  if (trace)
+    {
+      if (!trace_name)
+	trace_name = make_name (filename, TRACE_SUFFIX, NULL);
+      if (!(Trace = fopen (trace_name, "a")))
+	Message ("Unable to open \"%s\". No tracing will be done.", trace_name);
+      else
+	setbuf (Trace, NULL);
+    }
+  else
+    Trace = NULL;
+
+  if (comp_stat_point)
+    {
+      char *name = make_name (filename, COMPRESSION_STATS_SUFFIX, NULL);
+      if (!(Comp_Stats = fopen (name, "wb")))  /* [RPAP - Feb 97: WIN32 Port] */
+	Message ("Unable to open \"%s\". No comp. stats. will be generated.",
+		 name);
+    }
+
+  if (Trace)
+    {
+      fprintf (Trace, "\n\n\t\t-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n");
+      /* print out the args to mg_passes */
+      fprintf (Trace, "\n\n");
+    }
+
+
+  GetTime (&StartTime);
+  
+  for (pass = 0; pass < MAX_PASSES; pass++) {
+    if (Passes & (1 << pass)) {
+      pass_data *pd = &PassData[pass];
+#ifdef HAVE_TIMES
+      struct tms tims;
+      times (&tims);
+      pd->init_time -= tims.tms_utime + tims.tms_stime;
+#elif defined(HAVE_GETRUSAGE)  /* [RPAP - Feb 97: WIN32 Port] */
+      struct rusage ru;
+      
+      getrusage (RUSAGE_SELF, &ru);
+      pd->init_time.tv_sec -= ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+      pd->init_time.tv_usec -= ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+#endif
+      if (pd->init (filename) == COMPERROR) {
+	mg_passes_exit_value = 1;
+	FatalError (1, "Error during init of \"%s\"", pd->name);
+      }
+#ifdef HAVE_TIMES
+      times (&tims);
+      pd->init_time += tims.tms_utime + tims.tms_stime;
+#elif defined(HAVE_GETRUSAGE)  /* [RPAP - Feb 97: WIN32 Port] */
+      getrusage (RUSAGE_SELF, &ru);
+      pd->init_time.tv_sec += ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+      pd->init_time.tv_usec += ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+      time_normalise (&pd->init_time);
+#endif
+    }
+  }
+  GetTime (&InitTime);
+}
+
+
+void process_document(const u_char *buffer, int len) {
+  int pass;
+  bytes_processed += len;
+
+#ifndef QUIET
+  if (!len)
+    Message ("Warning : Processing zero length document");
+#endif
+  
+  for (pass = 0; pass < MAX_PASSES; pass++) {
+    if (Passes & (1 << pass))
+      {
+	register pass_data *pd = &PassData[pass];
+	
+#ifdef HAVE_TIMES
+	struct tms tims;
+	times (&tims);
+	pd->process_time -= tims.tms_utime + tims.tms_stime;
+#elif defined(HAVE_GETRUSAGE)  /* [RPAP - Feb 97: WIN32 Port] */
+	struct rusage ru;
+	register struct timeval *tv = &pd->process_time;
+	
+	getrusage (RUSAGE_SELF, &ru);
+	tv->tv_sec -= ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+	tv->tv_usec -= ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+#endif
+	if (pd->process ((u_char *) buffer, len) == COMPERROR)
+	  {
+	    Message ("Error during processing of \"%s\"", pd->name);
+	    if (Dump || Trace)
+	      {
+		int i;
+		FILE *f = Trace ? Trace : stderr;
+		fprintf (f, "-=- * -=- * -=- * -=- * -=- * -=- * -=-\n");
+		for (i = 0; i < len; i++)
+		  {
+		    char ch = buffer[i];
+		    if (ch == '\1' || ch == '\2')
+		      ch = '\n';
+		    putc (ch, f);
+		  }
+		fprintf (f, "-=- * -=- * -=- * -=- * -=- * -=- * -=-\n");
+	      }
+	    if (Trace)
+	      fprintf (Trace, "%11" ULL_FS " bytes |%7lu docs | %s\n",
+		       bytes_processed, num_docs,
+		       ElapsedTime (&StartTime, NULL));
+	    exit (1);
+	  }
+#ifdef HAVE_TIMES
+	times (&tims);
+	pd->process_time += tims.tms_utime + tims.tms_stime;
+#elif defined(HAVE_GETRUSAGE)  /* [RPAP - Feb 97: WIN32 Port] */
+	getrusage (RUSAGE_SELF, &ru);
+	tv->tv_sec += ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+	tv->tv_usec += ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+#endif
+      }
+  }
+  num_docs++;
+  if (Trace)
+    {
+      block_bytes += len;
+      if (block_bytes >= trace)
+	{
+#ifdef HAVE_MALLINFO
+	  struct mallinfo mi;
+	  mi = mallinfo ();
+	  block_bytes -= trace;
+	  fprintf (Trace, "%11" ULL_FS " bytes |%7lu docs |%7.3f Mb | %s\n",
+		   bytes_processed, num_docs, mi.arena / 1024.0 / 1024.0,
+		   ElapsedTime (&StartTime, NULL));
+#else
+	  block_bytes -= trace;
+	  fprintf (Trace, "%11" ULL_FS " bytes |%7lu docs | %s\n",
+		   bytes_processed, num_docs,
+		   ElapsedTime (&StartTime, NULL));
+#endif
+	}
+    }
+}
+
+void finalise_driver() {
+  int pass;
+#ifndef HAVE_TIMES
+  for (pass = 0; pass < MAX_PASSES; pass++)
+    if (Passes & (1 << pass))
+      time_normalise (&PassData[pass].process_time);
+#endif
+
+  GetTime (&ProcTime);
+
+  for (pass = 0; pass < MAX_PASSES; pass++)
+    if (Passes & (1 << pass))
+      {
+	pass_data *pd = &PassData[pass];
+#ifdef HAVE_TIMES
+	struct tms tims;
+	times (&tims);
+	pd->done_time -= tims.tms_utime + tims.tms_stime;
+#elif defined(HAVE_GETRUSAGE)  /* [RPAP - Feb 97: WIN32 Port] */
+	struct rusage ru;
+	
+	getrusage (RUSAGE_SELF, &ru);
+	pd->done_time.tv_sec -= ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+	pd->done_time.tv_usec -= ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+#endif
+	if (pd->done (filename) == COMPERROR) {
+	  mg_passes_exit_value = 1;
+	  FatalError (1, "Error during done of \"%s\"", pd->name);
+	}
+#ifdef HAVE_TIMES
+	times (&tims);
+	pd->done_time += tims.tms_utime + tims.tms_stime;
+#elif defined(HAVE_GETRUSAGE)  /* [RPAP - Feb 97: WIN32 Port] */
+	getrusage (RUSAGE_SELF, &ru);
+	pd->done_time.tv_sec += ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+	pd->done_time.tv_usec += ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+	time_normalise (&pd->done_time);
+#endif
+      }
+  if (Trace)
+    {
+#ifdef HAVE_MALLINFO
+      struct mallinfo mi;
+      mi = mallinfo ();
+      fprintf (Trace, "%11" ULL_FS " bytes |%7lu docs |%7.3f Mb | %s\n",
+	       bytes_processed, num_docs, mi.arena / 1024.0 / 1024.0,
+	       ElapsedTime (&StartTime, NULL));
+#else
+      fprintf (Trace, "%11" ULL_FS " bytes |%7lu docs | %s\n",
+	       bytes_processed, num_docs,
+	       ElapsedTime (&StartTime, NULL));
+#endif
+    }
+
+  GetTime (&DoneTime);
+
+  Message ("");
+  Message ("%10s      :    init         process        done", "");
+  for (pass = 0; pass < MAX_PASSES; pass++)
+    if (Passes & (1 << pass))
+      {
+	pass_data *pd = &PassData[pass];
+	char it[15], pt[15], dt[15];
+#ifdef HAVE_TIMES
+	strcpy (it, cputime_string (pd->init_time));
+	strcpy (pt, cputime_string (pd->process_time));
+	strcpy (dt, cputime_string (pd->done_time));
+#else
+	strcpy (it, cputime_string (&pd->init_time));
+	strcpy (pt, cputime_string (&pd->process_time));
+	strcpy (dt, cputime_string (&pd->done_time));
+#endif
+	Message ("%-10s      : %s   %s   %s", pd->name, it, pt, dt);
+      }
+  Message ("");
+  Message ("Init time       : %s", ElapsedTime (&StartTime, &InitTime));
+  Message ("Process time    : %s", ElapsedTime (&InitTime, &ProcTime));
+  Message ("Done time       : %s", ElapsedTime (&ProcTime, &DoneTime));
+  Message ("Total time      : %s", ElapsedTime (&StartTime, &DoneTime));
+  Message ("Documents       : %u", num_docs);
+  Message ("Bytes received  : %" ULL_FS, bytes_received);
+  Message ("Bytes processed : %" ULL_FS, bytes_processed);
+  Message ("Process Rate    : %.1f kB per cpu second",
+   (double) bytes_processed / (ProcTime.CPUTime - InitTime.CPUTime) / 1024);
+  //free (buffer);
+
+  if (Trace)
+    fclose (Trace);
+
+  if (Comp_Stats)
+    fclose (Comp_Stats);
+
+}
+
+int get_exit_value() {
+  return mg_passes_exit_value;
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_passes_4jni.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_passes_4jni.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_passes_4jni.h	(revision 14757)
@@ -0,0 +1,86 @@
+/**************************************************************************
+ *
+ * mg_passes_4jni.h -- modified mg_passes for use from jni
+ * Copyright (C) 2004 New Zealand Digital Library, http://www.nzdl.org
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+#ifndef H_MG_PASSES_4JNI
+#define H_MG_PASSES_4JNI
+
+/* clear all the settings from one mg_passes run to the next */
+void clear_variables();
+
+/* the following are methods to set all the variables that used to be
+   set by command line args */
+
+/* -S, -T1, -T2, -I1, -I2, args to mg_passes */
+void add_pass(char pass_type, char pass_num);
+
+/* -D arg to mg_passes */
+void dump_failed_document(int dump);
+
+/* -G arg to mg_passes */
+void ignore_sgml_tags(int ignore);
+
+/* -b arg to mg_passes */
+void set_buffer_size(long size);
+
+/* -c arg to mg_passes */
+void set_chunk_limit(long chunk_limit);
+
+/* -C arg to mg_passes */
+void set_comp_stat_point(int stat_point);
+
+/* -f arg to mg_passes */
+void set_filename(const char * filen);
+
+/* -m arg to mg_passes */
+void set_inversion_limit(int limit);
+
+/* -1, -2, -3 args to mg_passes */
+void set_invf_level(char level);
+
+/* -W arg to mg_passes */
+void set_make_weights(int make_w);
+
+/* -M arg to mg_passes */
+void set_max_numeric(int max_numeric);
+
+/* -a, -s args to mg_passes */
+void set_stem_options(const char * stemmer, int method);
+
+/* -t arg to mg_passes */
+void set_trace_point(int tracepos);
+
+/* -n arg to mg_passes */
+void set_trace_file(const char * filen);
+
+/* The old driver method has been split into 3:
+init_driver, process_document (called numdocs times), 
+finalise_driver.
+The above set vars methods should all be called before init_driver.
+*/
+
+void init_driver ();
+
+void process_document(const u_char *buffer, int len);
+
+void finalise_driver();
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/mg_perf_hash_build.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_perf_hash_build.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_perf_hash_build.1	(revision 14757)
@@ -0,0 +1,89 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_perf_hash_build 1 \*(Dt CITRI
+.SH NAME
+mg_perf_hash_build \- generate an order-preserving hash function for the stemmed dictionary
+.SH SYNOPSIS
+.B mg_perf_hash_build
+[
+.B \-h
+]
+[
+.BI \-r " rndseed"
+]
+[
+.BI \-d  " directory"
+]
+.if n .ti +9n
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_perf_hash_build
+generates an order-preserving hashing function from the compressed
+stemmed dictionary and writes it out to disk.
+.BR mg_passes (1)
+will make use of the hash function when it builds the inverted file.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-r " rndseed"
+This specifies the random seed to be used in the generation of the
+hash function; it must be an integer.  If this is not specified, the
+current time will be used as the random seed.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf.dict
+Stemmed dictionary.
+.TP
+.B *.invf.dict.hash
+Data for a order-preserving perfect hash function.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_perf_hash_build.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_perf_hash_build.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_perf_hash_build.c	(revision 14757)
@@ -0,0 +1,186 @@
+/**************************************************************************
+ *
+ * mg_perf_hash_build.c -- Program to build a perfect hash function
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "messages.h"
+#include "timing.h"
+#include "local_strings.h"
+#include "perf_hash.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "invf.h"
+#include "locallib.h"
+#include "words.h"
+#include "mg.h"
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:13  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:47  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:15  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:56:58  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:53  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+
+
+#define POOL_SIZE 1024*1024
+
+static void process_files (char *filename);
+
+int r = -1;
+
+int main (int argc, char **argv)
+{
+  ProgTime start;
+  char *file_name = "";
+  int ch;
+  msg_prefix = argv[0];
+  opterr = 0;
+  while ((ch = getopt (argc, argv, "f:d:r:h")) != -1)
+    switch (ch)
+      {
+      case 'f':		/* input file */
+	file_name = optarg;
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 'r':
+	r = atoi (optarg);
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-f input_file]"
+		 "[-d data directory] [-r random seed] [-h]\n", argv[0]);
+	exit (1);
+      }
+
+  GetTime (&start);
+  process_files (file_name);
+  Message ("%s\n", ElapsedTime (&start, NULL));
+  return 0;
+}
+
+
+
+
+
+static void 
+process_files (char *filename)
+{
+  FILE *dict, *hash;
+  unsigned long i;
+  u_char prev[MAXSTEMLEN + 1];
+  struct invf_dict_header idh;
+  perf_hash_data *phd;
+  u_char *pool;
+  int pool_left;
+  u_char **starts;
+
+
+  dict = open_file (filename, INVF_DICT_SUFFIX, "rb",
+		    MAGIC_STEM_BUILD, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  fread ((char *) &idh, sizeof (idh), 1, dict);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(idh.lookback);
+  NTOHUL(idh.dict_size);
+  NTOHUL(idh.total_bytes);
+  NTOHUL(idh.index_string_bytes);
+  NTOHD(idh.input_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(idh.num_of_docs);
+  NTOHUL(idh.static_num_of_docs);
+  NTOHUL(idh.num_of_words);
+  NTOHUL(idh.stemmer_num);
+  NTOHUL(idh.stem_method);
+
+  hash = create_file (filename, INVF_DICT_HASH_SUFFIX, "wb",
+		      MAGIC_HASH, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  if (!(pool = Xmalloc (POOL_SIZE)))
+    FatalError (1, "Out of memory");
+  pool_left = POOL_SIZE;
+
+  if (!(starts = Xmalloc (sizeof (u_char *) * idh.dict_size)))
+    FatalError (1, "Out of memory");
+
+  for (i = 0; i < idh.dict_size; i++)
+    {
+      register unsigned long copy, suff, l;
+      unsigned long wcnt, fcnt;
+
+      /* build a new word on top of prev */
+      copy = getc (dict);
+      suff = getc (dict);
+      *prev = copy + suff;
+      fread (prev + copy + 1, sizeof (u_char), suff, dict);
+
+      /* read other data, but no need to store it */
+      fread (&fcnt, sizeof (fcnt), 1, dict);
+      fread (&wcnt, sizeof (wcnt), 1, dict);
+
+      l = *prev + 1;
+      if (pool_left < l)
+	{
+	  pool = Xmalloc (POOL_SIZE);
+	  pool_left = POOL_SIZE;
+	}
+      starts[i] = pool;
+      bcopy ((char *) prev, (char *) pool, l);
+      pool += l;
+      pool_left -= l;
+    }
+  if (!(phd = gen_hash_func (idh.dict_size, starts, r)))
+    FatalError (1, "Unable to generate hash function");
+  if (write_perf_hash_data (hash, phd) == -1)
+    FatalError (1, "Unable to write hash function");
+  fclose (dict);
+  fclose (hash);
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_stem_idx.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_stem_idx.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_stem_idx.1	(revision 14757)
@@ -0,0 +1,95 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_stem_idx 1 \*(Dt CITRI
+.SH NAME
+mg_stem_idx \- builds a stem index file
+.SH SYNOPSIS
+.B mg_stem_idx
+[
+.B \-h
+]
+[
+.B \-F
+]
+[
+.BI \-b " num"
+]
+[
+.BI \-d " directory"
+]
+.if n .ti +9n
+.B \-s 1|2|3
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_stem_idx
+generates a stem index file for a collection that is to be built with
+stem indexes.  This program should be called three times: once for each
+.B -s
+parameter.  It uses the stemmed dictionary to create the stem index which
+contains pointers into the stemmed dictionary.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-b " num"
+The dictionary is stored in blocks on disk; this option is used to set
+the block size.  The default is 4-KB blocks.
+.TP
+.B \-F
+This option causes the disk blocks to be aligned on the appropriate
+boundaries.  For example, if 4-KB blocks are used, they will be aligned
+in the file on 4-KB boundaries.
+.TP
+.B -s 1|2|3
+The stem method to apply for the stem index.
+.br
+1 = casefolded and non-stemmed
+.br
+2 = non-casefolded and stemmed
+.br
+3 = casefolded and stemmed
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 25
+.B *.invf.dict.blocked
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict.blocked.1
+Stem index with stem index method 1.
+.TP
+.B *.invf.dict.blocked.2
+Stem index with stem index method 2.
+.TP
+.B *.invf.dict.blocked.3
+Stem index with stem index method 3.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_invf_dict (1),
+.BR mgstemidxlist (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_stem_idx.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_stem_idx.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_stem_idx.c	(revision 14757)
@@ -0,0 +1,892 @@
+/**************************************************************************
+ *
+ * mg_stem_idx.c -- Memory efficient stem index builder
+ * Copyright (C) 1997  Ross Peeters
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "messages.h"
+#include "filestats.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "invf.h"
+#include "mg.h"
+#include "locallib.h"
+#include "backend.h"     /* For struct stemmed_dict */
+#include "words.h"
+#include "stemmer.h"
+#include "hash.h"
+#include "local_strings.h"
+
+typedef struct PosEntry
+{
+  unsigned int num_cases;
+  unsigned int blk;
+  unsigned short blk_index;
+  unsigned short offset;
+}
+PosEntry;
+
+
+typedef struct PosList
+{
+  unsigned int list_size;
+  unsigned int num_entries;
+  PosEntry PE[1];
+}
+PosList;
+
+
+typedef struct idx_hash_rec
+{
+  u_char *word;
+  PosList *PL;
+}
+idx_hash_rec;
+
+
+#define POOL_SIZE 1024*1024
+#define HASH_POOL_SIZE 8192
+#define INITIAL_HASH_SIZE 7927
+
+
+static unsigned long MaxMemInUse = 0;
+static unsigned long MemInUse = 0;
+
+static idx_hash_rec **IdxHashTable;
+static unsigned long IdxHashSize;
+static unsigned long IdxHashUsed;
+static u_char *IdxPool;
+static int IdxPoolLeft;
+
+static idx_hash_rec *idx_hr_pool;
+static int idx_hr_PoolLeft;
+
+static idx_hash_rec **idx_first_occr;
+static int idx_max_first_occr;
+
+int block_size = 1024 * 4;
+
+int force = 0;
+
+static long lookback = 4;
+
+static void 
+ChangeMem (int Change)
+{
+  MemInUse += Change;
+  if (MemInUse > MaxMemInUse)
+    MaxMemInUse = MemInUse;
+}
+
+
+/* =========================================================================
+ * Function: MakePosList
+ * Description:
+ * Input:
+ * Output:
+ * ========================================================================= */
+PosList *
+MakePosList (int n)
+{
+  PosList *pl;
+  int list_size = (n == 0 ? 1 : n);	/* always allocate at least one node */
+
+  pl = Xmalloc (sizeof (PosList) + (list_size - 1) * sizeof (PosEntry));
+  if (!pl)
+    FatalError (1, "Unable to allocate term list");
+  ChangeMem (sizeof (PosList) + (list_size - 1) * sizeof (PosEntry));
+
+  pl->num_entries = n;
+  pl->list_size = list_size;
+
+  return pl;
+}
+
+/* =========================================================================
+ * Function: ResizePosList
+ * Description:
+ * Input:
+ * Output:
+ * ========================================================================= */
+
+#define GROWTH_FACTOR 2
+#define MIN_SIZE 2
+
+static void
+ResizePosList (PosList ** pos_list)
+{
+  PosList *pl = *pos_list;
+
+  ChangeMem (-(sizeof (PosList) + (pl->list_size - 1) * sizeof (PosEntry)));
+  if (pl->num_entries > pl->list_size)
+    {
+      if (pl->list_size)
+	pl->list_size *= GROWTH_FACTOR;
+      else
+	pl->list_size = MIN_SIZE;
+    }
+  pl = Xrealloc (pl, sizeof (PosList) + (pl->list_size - 1) * sizeof (PosEntry));
+
+  if (!pl)
+    FatalError (1, "Unable to resize pos list");
+  ChangeMem (sizeof (PosList) + (pl->list_size - 1) * sizeof (PosEntry));
+
+  *pos_list = pl;
+}
+
+
+/* =========================================================================
+ * Function: FreePosList
+ * Description:
+ * Input:
+ * Output:
+ * ========================================================================= */
+
+void
+FreePosList (PosList ** the_pl)
+{
+  PosList *pl = *the_pl;
+
+  ChangeMem (-(sizeof(PosList) + sizeof (PosEntry) * (pl->list_size - 1)));
+  Xfree (pl);
+
+  *the_pl = NULL;
+}
+
+
+/* =========================================================================
+ * Function: ResetPosList
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+void
+ResetPosList (PosList ** pl)
+{
+  if (*pl)
+    FreePosList (pl);
+  *pl = MakePosList (0);
+}
+
+/* =========================================================================
+ * Function: AddPosEntry
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+int
+AddPosEntry (PosList ** pos_list, PosEntry * pe)
+{
+  PosList *pl = *pos_list;
+
+  pl->num_entries++;
+  ResizePosList (pos_list);
+  pl = *pos_list;
+
+  /* copy the structure contents */
+  bcopy ((char *) pe, (char *) &(pl->PE[pl->num_entries - 1]), sizeof (PosEntry));
+
+  return pl->num_entries - 1;
+}
+
+
+/* Modified from stem_search.c */
+stemmed_dict *
+ReadStemDictBlk (File * stem_file)
+{
+  unsigned long i;
+  stemmed_dict *sd;
+  u_char *buffer;
+
+  if (!(sd = Xmalloc (sizeof (stemmed_dict))))
+    FatalError (1, "Could not allocate memory for stemmed dict");
+
+
+  sd->stem_file = stem_file;
+  sd->MemForStemDict = 0;
+
+  Fread (&sd->sdh, sizeof (sd->sdh), 1, stem_file);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(sd->sdh.lookback);
+  NTOHUL(sd->sdh.block_size);
+  NTOHUL(sd->sdh.num_blocks);
+  NTOHUL(sd->sdh.blocks_start);
+  NTOHUL(sd->sdh.index_chars);
+  NTOHUL(sd->sdh.num_of_docs);
+  NTOHUL(sd->sdh.static_num_of_docs);
+  NTOHUL(sd->sdh.num_of_words);
+  NTOHUL(sd->sdh.stemmer_num);
+  NTOHUL(sd->sdh.stem_method);
+  NTOHUL(sd->sdh.indexed);
+
+  if (!(buffer = Xmalloc (sd->sdh.index_chars)))
+    {
+      Xfree (sd);
+      FatalError (1, "Could not allocate memory for stemmed dict");
+      return (NULL);
+    };
+  sd->MemForStemDict += sd->sdh.index_chars;
+
+  if (!(sd->index = Xmalloc (sd->sdh.num_blocks * sizeof (*sd->index))))
+    {
+      Xfree (sd);
+      Xfree (buffer);
+      FatalError (1, "Could not allocate memory for stemmed dict");
+      return (NULL);
+    };
+  sd->MemForStemDict += sd->sdh.num_blocks * sizeof (*sd->index);
+
+  if (!(sd->pos = Xmalloc (sd->sdh.num_blocks * sizeof (*sd->pos))))
+    {
+      Xfree (sd);
+      Xfree (buffer);
+      Xfree (sd->index);
+      FatalError (1, "Could not allocate memory for stemmed dict");
+      return (NULL);
+    };
+  sd->MemForStemDict += sd->sdh.num_blocks * sizeof (*sd->pos);
+
+  if (!(sd->buffer = Xmalloc (sd->sdh.block_size * sizeof (*sd->buffer))))
+    {
+      Xfree (sd);
+      Xfree (buffer);
+      Xfree (sd->index);
+      Xfree (sd->buffer);
+      FatalError (1, "Could not allocate memory for stemmed dict");
+      return (NULL);
+    };
+  sd->MemForStemDict += sd->sdh.block_size * sizeof (*sd->buffer);
+
+  sd->active = -1;
+
+  for (i = 0; i < sd->sdh.num_blocks; i++)
+    {
+      register u_char len;
+      sd->index[i] = buffer;
+      len = Getc (stem_file);
+      *buffer++ = len;
+      Fread (buffer, sizeof (u_char), len, stem_file);
+      buffer += len;
+      Fread (&sd->pos[i], sizeof (*sd->pos), 1, stem_file);
+      NTOHUL(sd->pos[i]);  /* [RPAP - Jan 97: Endian Ordering] */
+    }
+
+  return sd;
+}
+
+
+void
+mg_init_process ()
+{
+  /* Allocate memory for idx hash table */
+
+  if (!(IdxPool = Xmalloc (POOL_SIZE)))
+    FatalError (1, "Unable to allocate memory for idx pool");
+  IdxPoolLeft = POOL_SIZE;
+  ChangeMem (POOL_SIZE);
+
+  if (!(idx_hr_pool = Xmalloc (HASH_POOL_SIZE * sizeof (idx_hash_rec))))
+    FatalError (1, "Unable to allocate memory for idx pool");
+  idx_hr_PoolLeft = HASH_POOL_SIZE;
+  ChangeMem (HASH_POOL_SIZE * sizeof (idx_hash_rec));
+
+  IdxHashSize = INITIAL_HASH_SIZE;
+  IdxHashUsed = 0;
+  if (!(IdxHashTable = Xmalloc (sizeof (idx_hash_rec *) * IdxHashSize)))
+    FatalError (1, "Unable to allocate memory for idx table");
+  ChangeMem (sizeof (idx_hash_rec *) * IdxHashSize);
+  bzero ((char *) IdxHashTable, sizeof (idx_hash_rec *) * IdxHashSize);
+  idx_max_first_occr = 8192;
+  if (!(idx_first_occr = Xmalloc (sizeof (idx_hash_rec *) * idx_max_first_occr)))
+    FatalError (1, "Unable to allocate memory for idx_first_occur");
+  ChangeMem (sizeof (idx_hash_rec *) * idx_max_first_occr);
+}
+
+
+void
+PackIdxHashTable (void)
+{
+  int s, d;
+  for (s = d = 0; s < IdxHashSize; s++)
+    if (IdxHashTable[s])
+      IdxHashTable[d++] = IdxHashTable[s];
+  ChangeMem (-sizeof (idx_hash_rec *) * IdxHashSize);
+  ChangeMem (sizeof (idx_hash_rec *) * IdxHashUsed);
+  if (!(IdxHashTable = Xrealloc (IdxHashTable, sizeof (idx_hash_rec *) * IdxHashUsed)))
+    FatalError (1, "Out of memory");
+  IdxHashSize = IdxHashUsed;
+}
+
+
+void
+process_stem_dict (stemmed_dict * sd, int stem_method)
+{
+  int block;
+  short blk_index = -1;
+  int wordnum = -1;
+  PosEntry *prevPE = NULL;
+  idx_hash_rec *prevIdx = NULL;
+  u_char word[MAXSTEMLEN + 1];
+  u_char prev[MAXSTEMLEN + 1];
+
+  /* For each block in stem dict... */
+  for (block = 0; block < sd->sdh.num_blocks; block++)
+    {
+      register unsigned int res;
+      int num_indexes;
+      unsigned long *first_word, *last_invf_len;
+      unsigned short *num_words;
+      u_char *base;
+      unsigned short *index;
+
+      /* Read block into buffer */
+      Fseek (sd->stem_file, sd->pos[block] + sd->sdh.blocks_start, 0);
+      Fread (sd->buffer, sd->sdh.block_size, sizeof (u_char), sd->stem_file);
+      sd->active = sd->pos[block];
+
+      /* Move through block header */
+      first_word = (unsigned long *) (sd->buffer);
+      NTOHUL(*first_word);  /* [RPAP - Jan 97: Endian Ordering] */
+      last_invf_len = (unsigned long *) (first_word + 1);
+      NTOHUL(*last_invf_len);  /* [RPAP - Jan 97: Endian Ordering] */
+      num_words = (unsigned short *) (last_invf_len + 1);
+      NTOHUS(*num_words);  /* [RPAP - Jan 97: Endian Ordering] */
+      index = num_words + 1;
+      num_indexes = ((*num_words - 1) / sd->sdh.lookback) + 1;
+
+      {
+	/* [RPAP - Jan 97: Endian Ordering] */
+	int i;
+	for (i = 0; i < num_indexes; i++)
+	  NTOHUS(index[i]);
+      }
+
+      base = (u_char *) (index + num_indexes);
+      blk_index = -1;
+
+      /* For each word in block... */
+      for (res = 0; res < *num_words; res++)
+	{
+	  unsigned copy, suff;
+	  register idx_hash_rec *idx_ent = 0;
+
+	  /* Update blk_index */
+	  if (!(res % sd->sdh.lookback))
+	    blk_index++;
+
+	  copy = *base++;
+	  suff = *base++;
+	  bcopy ((char *) base, (char *) (prev + copy + 1), suff);
+	  base += suff;
+	  *prev = copy + suff;
+
+	  /* Skip irrelevant word info */
+	  base += sizeof (u_long);
+	  base += sizeof (u_long);
+	  base += sizeof (u_long);
+
+	  /* Stem word */
+	  bcopy ((char *) prev, (char *) word, *prev + 1);
+	  stemmer (stem_method, sd->sdh.stemmer_num, word);
+
+	  /* Check if word follows straight on from previous word */
+	  if (prevIdx && !compare (word, prevIdx->word))
+	    prevPE->num_cases++;
+
+	  else 
+	    {
+	      /* Search the idx hash table for word */
+	      register unsigned long hashval, step;
+	      register int hsize = IdxHashSize;
+	      HASH (hashval, step, word, hsize);
+	      for (;;)
+		{
+		  register u_char *s1;
+		  register u_char *s2;
+		  register int len;
+		  idx_ent = IdxHashTable[hashval];
+		  if (!idx_ent)
+		    {
+		      /* Create a next entry in the hash table */
+		      int len = *word + 1;
+		      if (!idx_hr_PoolLeft)
+			{
+			  if (!(idx_hr_pool = Xmalloc (HASH_POOL_SIZE *
+						       sizeof (idx_hash_rec))))
+			    FatalError (1, "Unable to allocate memory for pool");
+			  idx_hr_PoolLeft = HASH_POOL_SIZE;
+			  ChangeMem (HASH_POOL_SIZE * sizeof (idx_hash_rec));
+			}
+		      idx_ent = idx_hr_pool++;
+		      idx_hr_PoolLeft--;
+		      if (len > IdxPoolLeft)
+			{
+			  if (!(IdxPool = Xmalloc (POOL_SIZE)))
+			    FatalError (1, "Unable to allocate memory for pool");
+			  IdxPoolLeft = POOL_SIZE;
+			  ChangeMem (POOL_SIZE);
+			}
+		      wordnum++;
+
+		      idx_ent->word = IdxPool;
+		      idx_ent->PL = MakePosList (0);
+		      {
+			PosEntry PE;
+			PE.num_cases = 1;
+			PE.blk = block;
+			PE.blk_index = (unsigned short) blk_index;
+			PE.offset = res % sd->sdh.lookback;
+			AddPosEntry (&(idx_ent->PL), &PE);
+		      }
+		      prevIdx = idx_ent;
+		      prevPE = &(idx_ent->PL->PE[idx_ent->PL->num_entries - 1]);
+
+		      bcopy ((char *) word, (char *) IdxPool, len);
+		      IdxPool += len;
+		      IdxPoolLeft -= len;
+		      if (IdxHashUsed == idx_max_first_occr - 1)
+			{
+			  ChangeMem (-sizeof (idx_hash_rec *) * idx_max_first_occr);
+			  idx_max_first_occr *= 2;
+			  if (!(idx_first_occr = Xrealloc (idx_first_occr, sizeof (idx_hash_rec *) *
+							   idx_max_first_occr)))
+			    FatalError (1, "Unable to allocate memory for idx_first_occr");
+			  ChangeMem (sizeof (idx_hash_rec *) * idx_max_first_occr);
+			}
+		      idx_first_occr[IdxHashUsed] = idx_ent;
+		      IdxHashUsed++;
+		      IdxHashTable[hashval] = idx_ent;
+		      break;
+		    } /* if (!idx_ent) */
+		  
+		  /* Compare the words */
+		  s1 = word;
+		  s2 = idx_ent->word;
+		  len = *s1 + 1;
+		  for (; len; len--)
+		    if (*s1++ != *s2++)
+		      break;
+		  
+		  if (len)
+		    {
+		      /* Entry is not the right one - move to next hash index */
+		      hashval = (hashval + step);
+		      if (hashval >= hsize)
+			hashval -= hsize;
+		    }
+		  else
+		    {
+		      /* Entry is correct - added PosEntry to word */
+		      PosEntry PE;
+		      PE.num_cases = 1;
+		      PE.blk = block;
+		      PE.blk_index = (unsigned short) blk_index;
+		      PE.offset = res % sd->sdh.lookback;
+		      AddPosEntry (&(idx_ent->PL), &PE);
+		      prevIdx = idx_ent;
+		      prevPE = &(idx_ent->PL->PE[idx_ent->PL->num_entries - 1]);
+		      break;
+		    }
+		} /* for (;;) */
+	    } /* else (the word does not follow on from previous one) */
+
+	  if (IdxHashUsed >= IdxHashSize >> 1)
+	    {
+	      idx_hash_rec **ht;
+	      unsigned long size;
+	      unsigned long i;
+	      size = prime (IdxHashSize * 2);
+	      if (!(ht = Xmalloc (sizeof (idx_hash_rec *) * size)))
+		FatalError (1, "Unable to allocate memory for idx table");
+	      bzero ((char *) ht, sizeof (idx_hash_rec *) * size);
+	      ChangeMem (sizeof (idx_hash_rec *) * size);
+
+	      for (i = 0; i < IdxHashSize; i++)
+		if (IdxHashTable[i])
+		  {
+		    register u_char *wptr;
+		    idx_hash_rec *ent;
+		    register unsigned long hashval, step;
+		    
+		    wptr = IdxHashTable[i]->word;
+		    HASH (hashval, step, wptr, size);
+		    ent = ht[hashval];
+		    while (ent)
+		      {
+			hashval += step;
+			if (hashval >= size)
+			  hashval -= size;
+			ent = ht[hashval];
+		      }
+		    ht[hashval] = IdxHashTable[i];
+		  }
+	      Xfree (IdxHashTable);
+	      ChangeMem (-sizeof (idx_hash_rec *) * IdxHashSize);
+	      IdxHashTable = ht;
+	      IdxHashSize = size;
+	    }
+	  
+	} /* end for each word */
+
+    } /* end for each block */
+
+}
+ 
+static int 
+idx_comp (const void *A, const void *B)
+{
+  u_char *s1 = (*((idx_hash_rec **) A))->word;
+  u_char *s2 = (*((idx_hash_rec **) B))->word;
+  return (casecompare (s1, s2));
+}
+
+
+void
+save_idx (char * filename, int stem_method)
+{
+  char *FName;
+  unsigned long i, j, pos, First_word, num;
+  struct stem_idx_header sih;
+  u_char *buffer, *last_word = NULL;
+  unsigned short *pointers;
+  int buf_in_use;
+  unsigned short ptrs_in_use, word_num;
+  FILE *idbi = NULL, *tmp = NULL;
+
+  FName = make_name (filename, ".tmp", NULL);
+  if (!(tmp = fopen (FName, "w+b")))
+    FatalError (1, "Unable to open \"%s\".\n", FName);
+
+  /* Delete the file now */
+  unlink (FName);
+
+  /* Create appropriate stem index file */
+  switch (stem_method)
+    {
+    case (1):
+      {
+	idbi = create_file (filename, INVF_DICT_BLOCKED_1_SUFFIX, "wb", MAGIC_STEM_1,
+			    MG_ABORT);
+	break;
+      }
+
+    case (2):
+      {
+	idbi = create_file (filename, INVF_DICT_BLOCKED_2_SUFFIX, "wb", MAGIC_STEM_2,
+			    MG_ABORT);
+	break;
+      }
+    case (3):
+      {
+	idbi = create_file (filename, INVF_DICT_BLOCKED_3_SUFFIX, "wb", MAGIC_STEM_3,
+			    MG_ABORT);
+	break;
+      }
+    }
+
+  if (!idbi)
+    FatalError (1, "Could NOT create .invf.blocked.%d file", stem_method);
+
+  PackIdxHashTable();
+  qsort (IdxHashTable, IdxHashUsed, sizeof (idx_hash_rec *), idx_comp);
+
+  sih.lookback = lookback;
+  sih.block_size = block_size;
+  sih.num_blocks = 0;
+  sih.blocks_start = 0;
+  sih.index_chars = 0;
+  sih.num_of_words = IdxHashUsed;
+
+  fwrite ((char *) &sih, sizeof (sih), 1, idbi);
+
+  if (!(buffer = Xmalloc (block_size + 512)))
+    FatalError (1, "Unable to allocate memory for \"buffer\"\n");
+  if (!(pointers = Xmalloc (block_size + 512)))
+    FatalError (1, "Unable to allocate memory for \"buffer\"\n");
+
+  buf_in_use = 0;
+  pos = 0;
+  word_num = 0;
+  ptrs_in_use = 0;
+  First_word = 0;
+
+  /* For each word in the hashtable... */
+  for (i = 0; i < IdxHashUsed; i++)
+    {
+      register unsigned long extra, copy, suff;
+      register struct idx_hash_rec *ent = IdxHashTable[i];
+
+      /* build a new word on top of prev */
+      if (last_word != NULL)
+	copy = prefixlen (last_word, ent->word);
+      else
+	copy = 0;
+      suff = *(ent->word) - copy;
+      last_word = ent->word;
+
+      if (word_num % sih.lookback == 0)
+	/* Will need copy chars to add + a pointer in index */
+	extra = copy + sizeof (*pointers);
+      else
+	extra = 0;
+      if ((ptrs_in_use + 1) * sizeof (*pointers) + sizeof (ptrs_in_use) + extra +
+	  buf_in_use + sizeof (First_word) + suff + 1 + sizeof (ent->PL->num_entries) + 
+	  ent->PL->num_entries * sizeof (PosEntry) > block_size)
+	{
+	  /* Dump buffer to tmp file */
+	  int chunk;
+	  HTONUL(First_word);  /* [RPAP - Jan 97: Endian Ordering] */
+	  HTONUS(word_num);  /* [RPAP - Jan 97: Endian Ordering] */
+	  fwrite (&First_word, sizeof (First_word), 1, tmp);
+	  fwrite (&word_num, sizeof (word_num), 1, tmp);
+	  fwrite (pointers, sizeof (*pointers), ptrs_in_use, tmp);
+	  fwrite (buffer, sizeof (u_char), buf_in_use, tmp);
+	  bzero ((char *) buffer, block_size);
+	  chunk = buf_in_use + ptrs_in_use * sizeof (*pointers) +
+	    sizeof (ptrs_in_use) + sizeof (First_word);
+	  if (force && chunk < block_size)
+	    {
+	      fwrite (buffer, sizeof (u_char), block_size - chunk, tmp);
+	      chunk = block_size;
+	    }
+
+	  pos += chunk;
+
+	  buf_in_use = 0;
+	  word_num = 0;
+	  ptrs_in_use = 0;
+	  sih.num_blocks++;
+
+	  /* Check that entry will fit into new block */
+	  if (sizeof (*pointers) + sizeof (ptrs_in_use) + extra + sizeof (First_word) +
+	      suff + 1 + sizeof (ent->PL->num_entries) + 
+	      ent->PL->num_entries * sizeof (PosEntry) > block_size)
+	    FatalError (1, "Block size to small");
+
+	} /* if size > block_size */
+
+      if (word_num % sih.lookback == 0)
+	{
+	  HTONUS2(buf_in_use, pointers[ptrs_in_use++]);  /* [RPAP - Jan 97: Endian Ordering] */
+	  suff += copy;
+	  copy = 0;
+	}
+
+      /* Output Word information */
+      buffer[buf_in_use++] = copy;
+      buffer[buf_in_use++] = suff;
+      bcopy ((char *) (ent->word + copy + 1), (char *) (buffer + buf_in_use), suff);
+      buf_in_use += suff;
+      HTONUI(ent->PL->num_entries);  /* [RPAP - Jan 97: Endian Ordering] */
+      bcopy ((char *) &(ent->PL->num_entries), (char *) (buffer + buf_in_use), sizeof (ent->PL->num_entries));
+      NTOHUI(ent->PL->num_entries);  /* [RPAP - Jan 97: Endian Ordering] */
+      buf_in_use += sizeof (ent->PL->num_entries);
+
+      for (j = 0; j < ent->PL->num_entries; j++)
+	{
+	  register PosEntry *pe = &(ent->PL->PE[j]);
+	  HTONUI(pe->num_cases);  /* [RPAP - Jan 97: Endian Ordering] */
+	  bcopy ((char *) &(pe->num_cases), (char *) (buffer + buf_in_use), sizeof (pe->num_cases));
+	  buf_in_use += sizeof (pe->num_cases);
+	  HTONUI(pe->blk);  /* [RPAP - Jan 97: Endian Ordering] */
+	  bcopy ((char *) &(pe->blk), (char *) (buffer + buf_in_use), sizeof (pe->blk));
+	  buf_in_use += sizeof (pe->blk);
+	  HTONUS(pe->blk_index);  /* [RPAP - Jan 97: Endian Ordering] */
+	  bcopy ((char *) &(pe->blk_index), (char *) (buffer + buf_in_use), sizeof (pe->blk_index));
+	  buf_in_use += sizeof (pe->blk_index);
+	  HTONUS(pe->offset);  /* [RPAP - Jan 97: Endian Ordering] */
+	  bcopy ((char *) &(pe->offset), (char *) (buffer + buf_in_use), sizeof (pe->offset));
+	  buf_in_use += sizeof (pe->offset);
+	}
+
+      if (buf_in_use + ptrs_in_use * sizeof (*pointers) +
+	  sizeof (ptrs_in_use) > block_size)
+	FatalError (1, "Fatal Internal Error # 64209258\n");
+
+      if (word_num == 0) /* the first word in each block - word_num set to 0 when buffer written to tmp file */
+	{
+	  /* Write word to main index */
+	  fwrite (ent->word, sizeof (u_char), *(ent->word) + 1, idbi);
+	  HTONUL(pos);  /* [RPAP - Jan 97: Endian Ordering] */
+	  fwrite (&pos, sizeof (pos), 1, idbi);
+	  NTOHUL(pos);  /* [RPAP - Jan 97: Endian Ordering] */
+	  sih.index_chars += *(ent->word) + 1;
+	  First_word = i;
+	}
+      word_num++;
+    } /* end for each word */ /* for each hash entry */
+
+  if (buf_in_use)
+    {
+      /* Write last buffer to tmp file */
+      int chunk;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      HTONUL(First_word);
+      HTONUS(word_num);
+
+      fwrite (&First_word, sizeof (First_word), 1, tmp);
+      fwrite (&word_num, sizeof (word_num), 1, tmp);
+      fwrite (pointers, sizeof (*pointers), ptrs_in_use, tmp);
+      fwrite (buffer, sizeof (u_char), buf_in_use, tmp);
+      bzero ((char *) buffer, block_size);
+      chunk = buf_in_use + ptrs_in_use * sizeof (*pointers) +
+	sizeof (ptrs_in_use) + sizeof (First_word);
+      if (force && chunk < block_size)
+	{
+	  fwrite (buffer, sizeof (u_char), block_size - chunk, tmp);
+	  chunk = block_size;
+	}
+
+      sih.num_blocks++;
+    }
+
+  rewind (tmp);
+  sih.blocks_start = sih.index_chars + sizeof (u_long) + sizeof (sih) +
+    sih.num_blocks * sizeof (pos);
+  if (force)
+    {
+      int amount;
+      amount = sih.blocks_start % block_size;
+      if (amount != 0)
+	{
+	  bzero ((char *) buffer, block_size);
+	  fwrite (buffer, sizeof (u_char), block_size - amount, idbi);
+	  sih.blocks_start += block_size - amount;
+	}
+    }
+
+  while ((num = fread (buffer, sizeof (u_char), block_size, tmp)) != 0)
+    fwrite (buffer, sizeof (u_char), num, idbi);
+  fclose (tmp);
+
+  /* skip over the magic number */
+  fseek (idbi, sizeof (u_long), 0);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(sih.lookback);
+  HTONUL(sih.block_size);
+  HTONUL(sih.num_blocks);
+  HTONUL(sih.blocks_start);
+  HTONUL(sih.index_chars);
+  HTONUL(sih.num_of_words);
+
+  fwrite (&sih, sizeof (sih), 1, idbi);
+  fclose (idbi);
+
+#ifndef SILENT
+  Message ("Stem %d:\n", stem_method);
+  Message ("     Block size   : %10d\n", block_size);
+  Message ("     Num_blocks   : %10d\n", NTOHUL(sih.num_blocks));  /* [RPAP - Jan 97: Endian Ordering] */
+  Message ("     Max mem used : %10.1f Mb\n", (double) MaxMemInUse / 1024.0 / 1024.0);
+  Message ("     Num_of_words : %10d\n", NTOHUL(sih.num_of_words));  /* [RPAP - Jan 97: Endian Ordering] */
+#endif
+}
+
+
+void
+UpdateStemDict (char * filename, int stem_method)
+{
+  FILE *idb;
+  struct stem_dict_header sdh;
+
+  if (!(idb = open_file (filename, INVF_DICT_BLOCKED_SUFFIX, "r+b",
+			 MAGIC_STEM, MG_CONTINUE)))
+    FatalError (1, "Could not update stemmed dict");
+
+  fread ((char *) &sdh, sizeof (sdh), 1, idb);
+  NTOHUL(sdh.indexed);  /* [RPAP - Jan 97: Endian Ordering] */
+  sdh.indexed |= 1 << (stem_method - 1);
+  HTONUL(sdh.indexed);
+  fseek (idb, sizeof (u_long), 0);
+  fwrite ((char *) &sdh, sizeof (sdh), 1, idb);
+  fclose (idb);
+}
+
+
+
+/* Main */
+int main (int argc, char **argv)
+{
+  File *idb;    /* File to .invf.dict.blocked */
+  char *filename = "";
+  stemmed_dict *sd;   /* Stemmed dictionary */
+  int ch;
+  char path[512];
+  int stem_method = 0;
+
+  msg_prefix = argv[0];
+  opterr = 0;
+  while ((ch = getopt (argc, argv, "f:d:b:hFs:")) != -1)
+    switch (ch)
+      {
+      case 'f':		/* input file */
+	filename = optarg;
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 'b':
+	block_size = atoi (optarg);
+	break;
+      case 'F':
+	force = 1;
+	break;
+      case 's':
+	stem_method = atoi (optarg);
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-d directory] "
+		 "[-b num] [-F] [-h] -s 1|2|3 -f name\n", argv[0]);
+	exit (1);
+      }
+
+  if (stem_method < 1 || stem_method > 3)
+    FatalError (1, "Stem method must be 1, 2 or 3");
+
+  /* Open required stem dict file */
+  sprintf (path, FILE_NAME_FORMAT, get_basepath (), filename, INVF_DICT_BLOCKED_SUFFIX);
+  if (!(idb = Fopen (path, "rb", MAGIC_STEM)))
+    FatalError (1, "Unable to open \"%s\"", path);
+
+  /* Read in idb header and index to blocks */
+  if (!(sd = ReadStemDictBlk (idb)))
+    FatalError (1, "Could not read stemmed dictionary");
+
+  /* Process stemmed dictionary */
+  mg_init_process ();
+  process_stem_dict (sd, stem_method);
+  save_idx (filename, stem_method);
+ 
+  /* Close stemmed dict */
+  Fclose (idb);
+
+  /* Update stemmed dict */
+  UpdateStemDict (filename, stem_method);
+
+  return 0;
+}
+
Index: /indexers/branches/3.03a/mg/src/text/mg_text_estimate.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_text_estimate.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_text_estimate.1	(revision 14757)
@@ -0,0 +1,112 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_text_estimate 1 \*(Dt CITRI
+.SH NAME
+mg_text_estimate \- Estimate the size of the compressed text based on the text statistics and a compression dictionary.
+.SH SYNOPSIS
+.B mg_text_estimate
+[
+.B \-h
+]
+[
+.BR \-H " |"
+.BR \-B " |"
+.BR \-D " |"
+.BR \-Y " |"
+.B \-M
+]
+.if n .ti +9n
+.I stats-dict
+.I compression-dict
+.SH DESCRIPTION
+This program estimates the size of the compressed text that would be
+generated if text with certain statistics were compressed with a
+particular dictionary.  This program has no real use in the
+.BR mg (1)
+system, except for experimenting with the
+.BR mg_compression_dict (1)
+program.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-m\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-H
+This specifies that novel words will be coded character by character
+using Huffman codes.
+.TP
+.B \-B
+This specifies that the size of an auxiliary dictionary will be
+estimated.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using binary codes.  The binary code represents their occurrence
+position in the auxiliary dictionary.
+.TP
+.B \-D
+This specifies that the size of an auxiliary dictionary will be
+estimated.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using delta codes.  The delta code represents their occurrence position
+in the auxiliary dictionary.
+.TP
+.B \-Y
+This specifies that the size of an auxiliary dictionary will be
+estimated.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using a combination of gamma and binary codes.  The code represents
+their occurrence position in the auxiliary dictionary.  This generally
+produces better compression than
+.B \-B
+or
+.BR \-D .
+.TP
+.B \-M
+This specifies that the size of an auxiliary dictionary will be
+estimated.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using a combination of gamma and binary codes.  The code represents
+their occurrence position in the auxiliary dictionary.  This method is
+adaptive within documents, and generally produces better compression
+than
+.BR \-B ,
+.B \-D
+or
+.BR \-Y .
+.SH FILES
+.TP 20
+.B *.text.stats
+Statistics about the text.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_text_estimate.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_text_estimate.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_text_estimate.c	(revision 14757)
@@ -0,0 +1,584 @@
+/**************************************************************************
+ *
+ * mg_text_estimate.c -- Program to estimate the compressed text size
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "messages.h"
+#include "local_strings.h"
+#include "bitio_gen.h"
+#include "bitio_m.h"
+#include "bitio_m_stdio.h"
+#include "timing.h"
+#include "mgheap.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "locallib.h"
+#include "invf.h"
+#include "text.h"
+#include "words.h"
+#include "mg.h"
+#include "comp_dict.h"
+#include "hash.h"
+
+
+
+
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:14  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.4  1999/01/15 03:05:51  rjmcnab
+
+   Renamed lib/heap to be lib/mgheap (it was causing some problems with
+   some versions of the STL libraries which contained a heap.h)
+
+   Revision 1.3  1998/12/17 09:12:53  rjmcnab
+
+   Altered mg to process utf-8 encoded Unicode. The main changes
+   are in the parsing of the input, the casefolding, and the stemming.
+
+   Revision 1.2  1998/11/25 07:55:48  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:19  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:56:59  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:54  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+typedef struct stats_t
+  {
+    u_long freq, occur;
+    u_long len;
+  }
+stats_t;
+
+static u_long huff_count = 0;
+static u_long escape_count = 0;
+
+
+char mode = 'H';
+
+/* [RJM 07/97: 4G limit] */
+static double ReadInWordsStandard (char *name, double *num_bytes);
+static double ReadInWordsSpecial (char *name, double *num_bytes,
+				  double *num_extra_bytes,
+				  u_long *aux_compressed);
+
+
+
+
+int main (int argc, char **argv)
+{
+  char *stats_dict = NULL, *comp_dict = NULL;
+  ProgTime StartTime;
+  double num_bytes, num_extra_bytes = 0; /* [RJM 07/97: 4G limit] */
+  u_long aux_compressed;
+  int ch;
+  double bytes;
+  opterr = 0;
+  msg_prefix = argv[0];
+  while ((ch = getopt (argc, argv, "BMDYHh")) != -1)
+    switch (ch)
+      {
+      case 'B':
+	Message ("The compressed text size for this method cannot be\n"
+		 "estimated exactly, so an upper bound will be calculated.");
+	mode = ch;
+	break;
+      case 'M':
+	Message ("The compressed text size for this method cannot be\n"
+		 "estimated exactly, so an upper bound will be calculated.");
+	mode = 'Y';
+	break;
+      case 'D':
+      case 'Y':
+      case 'H':
+	mode = ch;
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-h] [B|M|D|Y|H] stats_dict comp_dict\n",
+		 argv[0]);
+	exit (1);
+      }
+
+  if (optind < argc)
+    stats_dict = argv[optind++];
+  else
+    stats_dict = NULL;
+  if (optind < argc)
+    comp_dict = argv[optind++];
+  else
+    {
+      fprintf (stderr, "usage: %s [-h] [B|M|D|Y|H] stats_dict comp_dict\n",
+	       argv[0]);
+      exit (1);
+    }
+
+
+
+  GetTime (&StartTime);
+
+  if (LoadCompressionDictionary (comp_dict) == COMPERROR)
+    exit (1);
+
+  if (mode == 'H')
+    bytes = ReadInWordsStandard (stats_dict, &num_bytes);
+  else
+    bytes = ReadInWordsSpecial (stats_dict, &num_bytes, &num_extra_bytes,
+				&aux_compressed);
+
+
+  Message ("Compressed Text %.2f Mb ( %.0f bytes   %0.3f %%)",
+	   bytes / 1024.0 / 1024, bytes, bytes * 100 / num_bytes);
+  Message ("Words portion of the dictionary %.2f Mb ( %.0f bytes   %0.3f %%)",
+	   Words_disk / 1024.0 / 1024, Words_disk * 1.0,
+	   (Words_disk * 100.0) / num_bytes);
+  if (mode == 'H')
+    Message ("Huffman info for chars in dictionary %.2f Mb ( %.0f bytes   %0.3f %%)",
+	     Chars_disk / 1024.0 / 1024, Chars_disk * 1.0,
+	     (Chars_disk * 100.0) / num_bytes);
+  else
+    {
+      Message ("Aux dictionary (Uncompressed) %.2f Mb ( %.0f bytes   %0.3f %%)",
+	       num_extra_bytes / 1024.0 / 1024, num_extra_bytes * 1.0,
+	       (num_extra_bytes * 100.0) / num_bytes);
+      Message ("Aux dictionary (Compressed)   %.2f Mb ( %.0f bytes   %0.3f %%)",
+	       aux_compressed / 1024.0 / 1024, aux_compressed * 1.0,
+	       (aux_compressed * 100.0) / num_bytes);
+    }
+  Message ("Words and non-words in the text %u", huff_count + escape_count);
+  Message ("Words and non-words coded by escapes %u ( %0.3f %%)", escape_count,
+	   escape_count * 100.0 / huff_count);
+  Message ("%s", ElapsedTime (&StartTime, NULL));
+  return 0;
+}
+
+
+
+
+
+static double 
+ReadInWordsStandard (char *name, double *num_bytes)
+{
+  compression_stats_header csh;
+  FILE *f;
+  u_long which;
+  double bytes, bits = 0;
+
+  f = open_named_file (name, "rb", MAGIC_STATS_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  fread (&csh, sizeof (csh), 1, f);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(csh.num_docs);
+  NTOHD(csh.num_bytes); /* [RJM 07/97: 4G limit] */
+
+  for (which = 0; which < 2; which++)
+    {
+      frags_stats_header fsh;
+      int j;
+      fread (&fsh, sizeof (fsh), 1, f);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(fsh.num_frags);
+      NTOHUL(fsh.mem_for_frags);
+
+      for (j = 0; j < fsh.num_frags; j++)
+	{
+	  int len, freq, res, occur_num;
+	  u_char Word[16];
+	  fread (&freq, sizeof (freq), 1, f);
+	  fread (&occur_num, sizeof (occur_num), 1, f);
+	  len = fgetc (f);
+
+	  /* [RPAP - Jan 97: Endian Ordering] */
+	  NTOHSI(freq);
+	  NTOHSI(occur_num);
+
+	  Word[0] = len;
+	  fread (Word + 1, len, 1, f);
+
+	  /* Search the hash table for Word */
+	  if (ht[which])
+	    {
+	      register unsigned long hashval, step;
+	      register int tsize = ht[which]->size;
+	      register u_char **wptr;
+	      HASH (hashval, step, Word, tsize);
+	      for (;;)
+		{
+		  register u_char *s1;
+		  register u_char *s2;
+		  register int len;
+		  wptr = ht[which]->table[hashval];
+		  if (wptr == NULL)
+		    {
+		      res = COMPERROR;
+		      break;
+		    }
+
+		  /* Compare the words */
+		  s1 = Word;
+		  s2 = *wptr;
+		  len = *s1 + 1;
+		  for (; len; len--)
+		    if (*s1++ != *s2++)
+		      break;
+
+		  if (len)
+		    {
+		      hashval += step;
+		      if (hashval >= tsize)
+			hashval -= tsize;
+		    }
+		  else
+		    {
+		      res = ht[which]->table[hashval] - ht[which]->words;
+		      break;
+		    }
+		}
+	    }
+	  else
+	    res = COMPERROR;
+
+	  /* Check that the word was found in the dictionary */
+	  if (res == COMPERROR)
+	    {
+	      escape_count += freq;
+	      if (cdh.dict_type == MG_COMPLETE_DICTIONARY)
+		Message ("Unknown word \"%.*s\"\n", *Word, Word + 1);
+	      if (cdh.dict_type == MG_PARTIAL_DICTIONARY)
+		{
+		  unsigned i;
+		  if (ht[which])
+		    {
+		      res = ht[which]->hd->num_codes - 1;
+		      bits += ht[which]->hd->clens[res] * freq;
+		    }
+		  bits += lens_huff[which].clens[Word[0]] * freq;
+		  for (i = 0; i < Word[0]; i++)
+		    bits += char_huff[which].clens[Word[i + 1]] * freq;
+		}
+	      if (cdh.dict_type == MG_SEED_DICTIONARY)
+		{
+		  unsigned i;
+		  if (ht[which])
+		    {
+		      res = ht[which]->hd->num_codes - 1;
+		      bits += ht[which]->hd->clens[res] * freq;
+		    }
+		  bits += lens_huff[which].clens[Word[0]] * freq;
+		  for (i = 0; i < Word[0]; i++)
+		    bits += char_huff[which].clens[Word[i + 1]] * freq;
+		}
+	    }
+	  else
+	    {
+	      bits += ht[which]->hd->clens[res] * freq;
+	      huff_count += freq;
+	    }
+	}
+    }
+  fclose (f);
+
+
+  /*
+   * The 5.5 bits added on per document consist of
+   *   1 bit for the word/non-word flag at the start of the document.
+   *   1 bit on average for document termination.
+   *   3.5 bits on average for padding to a byte boundary.
+   */
+  bits += 5.5 * csh.num_docs;
+
+  bytes = bits / 8 + sizeof (compressed_text_header) + sizeof (u_long);
+
+  *num_bytes = csh.num_bytes;
+
+  return bytes;
+}
+
+
+static int 
+stats_comp (const void *a, const void *b)
+{
+  return ((stats_t *) a)->occur - ((stats_t *) b)->occur;
+}
+
+
+
+
+
+static double 
+ReadInWordsSpecial (char *name, double *num_bytes,
+		    double *num_extra_bytes,
+		    u_long *aux_compressed)
+{
+  compression_stats_header csh;
+  FILE *f;
+  u_long magic, which;
+  double bytes, bits = 0;
+  double size[2];
+
+  if (!(f = fopen (name, "rb")))  /* [RPAP - Feb 97: WIN32 Port] */
+    FatalError (1, "Unable to open file \"%s\"\n", name);
+
+  if (fread (&magic, sizeof (magic), 1, f) != 1)
+    FatalError (1, "Unable to read magic number");
+
+  NTOHUL(magic);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  if (magic != MAGIC_STATS_DICT)
+    FatalError (1, "Bad magic number");
+
+  fread (&csh, sizeof (csh), 1, f);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(csh.num_docs);
+  NTOHD(csh.num_bytes); /* [RJM 07/97: 4G limit] */
+
+  for (which = 0; which < 2; which++)
+    {
+      stats_t *stats;
+      frags_stats_header fsh;
+      int j, num = 0;
+      long lens[16], chars[256];
+
+      bzero ((char *) lens, sizeof (lens));
+      bzero ((char *) chars, sizeof (chars));
+
+      fread (&fsh, sizeof (fsh), 1, f);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(fsh.num_frags);
+      NTOHUL(fsh.mem_for_frags);
+
+      stats = Xmalloc (fsh.num_frags * sizeof (*stats));
+      if (!stats)
+	FatalError (1, "Unable to allocate memory for stats");
+      for (j = 0; j < fsh.num_frags; j++)
+	{
+	  int len, res;
+	  u_char Word[16];
+	  fread (&stats[num].freq, sizeof (stats[num].freq), 1, f);
+	  fread (&stats[num].occur, sizeof (stats[num].occur), 1, f);
+	  len = fgetc (f);
+
+	  /* [RPAP - Jan 97: Endian Ordering] */
+	  NTOHSI(stats[num].freq);
+	  NTOHSI(stats[num].occur);
+
+	  stats[num].len = len + 1;
+
+	  Word[0] = len;
+	  fread (Word + 1, len, 1, f);
+
+	  /* Search the hash table for Word */
+	  if (ht[which])
+	    {
+	      register unsigned long hashval, step;
+	      register int tsize = ht[which]->size;
+	      register u_char **wptr;
+	      HASH (hashval, step, Word, tsize);
+	      for (;;)
+		{
+		  register u_char *s1;
+		  register u_char *s2;
+		  register int len;
+		  wptr = ht[which]->table[hashval];
+		  if (wptr == NULL)
+		    {
+		      res = COMPERROR;
+		      break;
+		    }
+
+		  /* Compare the words */
+		  s1 = Word;
+		  s2 = *wptr;
+		  len = *s1 + 1;
+		  for (; len; len--)
+		    if (*s1++ != *s2++)
+		      break;
+
+		  if (len)
+		    {
+		      hashval += step;
+		      if (hashval >= tsize)
+			hashval -= tsize;
+		    }
+		  else
+		    {
+		      res = ht[which]->table[hashval] - ht[which]->words;
+		      break;
+		    }
+		}
+	    }
+	  else
+	    res = COMPERROR;
+
+	  assert (stats[num].freq > 0);
+
+	  /* Check that the word was found in the dictionary */
+	  if (res == COMPERROR)
+	    {
+	      if (cdh.dict_type == MG_COMPLETE_DICTIONARY)
+		Message ("Unknown word \"%.*s\"\n", *Word, Word + 1);
+	      if ((cdh.dict_type == MG_PARTIAL_DICTIONARY ||
+		   cdh.dict_type == MG_SEED_DICTIONARY) &&
+		  ht[which])
+		{
+		  int k;
+		  res = ht[which]->hd->num_codes - 1;
+		  bits += ht[which]->hd->clens[res] * stats[num].freq;
+		  lens[Word[0]]++;
+		  for (k = 0; k < (int) Word[0]; k++)
+		    chars[Word[k + 1]]++;
+		}
+	      num++;
+	    }
+	  else
+	    {
+	      bits += ht[which]->hd->clens[res] * stats[num].freq;
+	    }
+	}
+
+      {
+	int j, num_buckets = 0;
+	int start[10], end[10];
+	long flens[16], fchars[256];
+
+	for (j = 0; j < 256; j++)
+	  if (!chars[j] && PESINAWORD (j) == which)
+	    fchars[j] = 1;
+	  else
+	    fchars[j] = chars[j];
+	for (j = 0; j < 16; j++)
+	  if (!lens[j])
+	    flens[j] = 1;
+	  else
+	    flens[j] = lens[j];
+
+	size[which] = Calculate_Huffman_Size (16, flens, lens) +
+	  Calculate_Huffman_Size (256, fchars, chars);
+
+
+	qsort (stats, num, sizeof (*stats), stats_comp);
+
+
+	if (mode == 'Y')
+	  {
+	    int k;
+	    num_buckets = 1;
+	    start[0] = 0;
+	    end[0] = cdh.num_words[which] - 1;
+	    Message ("There are %d novel %swords", num, which ? "" : "non-");
+	    while (end[num_buckets - 1] < num)
+	      {
+		start[num_buckets] = end[num_buckets - 1] + 1;
+		end[num_buckets] = start[num_buckets] +
+		  (end[num_buckets - 1] - start[num_buckets - 1]) * 2;
+		num_buckets++;
+	      }
+	    for (k = 0; k < num_buckets; k++)
+	      Message ("Bucket %d   %d <= x <= %d\n", k + 1, start[k], end[k]);
+	  }
+
+	for (j = 0; j < num; j++)
+	  {
+	    (*num_extra_bytes) += stats[j].len;
+	    switch (mode)
+	      {
+	      case 'D':
+		bits += BIO_Delta_Length (j + 1) * stats[j].freq;
+		break;
+	      case 'B':
+		bits += BIO_Binary_Length (j + 1, num) * stats[j].freq;
+		break;
+	      case 'Y':
+		{
+		  int k = 0;
+		  while (j > end[k])
+		    k++;
+		  if (!(j - start[k] + 1 >= 1 &&
+			j - start[k] + 1 <= end[k] - start[k] + 1))
+		    {
+		      Message ("k = %d, j = %d", k, j);
+		      assert (j - start[k] + 1 >= 1 &&
+			      j - start[k] + 1 <= end[k] - start[k] + 1);
+		    }
+		  else
+		    {
+		      bits += (BIO_Gamma_Length (k + 1) +
+			       BIO_Binary_Length (j - start[k] + 1,
+						  end[k] - start[k] + 1)) *
+			stats[j].freq;
+		    }
+		}
+	      }
+	  }
+	if (mode == 'B' && num)
+	  bits += BIO_Delta_Length (num) * csh.num_docs;
+      }
+      Xfree (stats);
+    }
+  fclose (f);
+
+  *aux_compressed = (size[0] + size[1]) / 8;
+
+  /*
+   * The 5.5 bits added on per document consist of
+   *   1 bit for the word/non-word flag at the start of the document.
+   *   1 bit on average for document termination.
+   *   3.5 bits on average for padding to a byte boundary.
+   */
+  bits += 5.5 * csh.num_docs;
+
+  bytes = bits / 8 + sizeof (compressed_text_header) + sizeof (u_long);
+
+  *num_bytes = csh.num_bytes;
+
+  return bytes;
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_text_merge.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_text_merge.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_text_merge.1	(revision 14757)
@@ -0,0 +1,76 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_text_merge 1 \*(Dt CITRI
+.SH NAME
+mg_text_merge \- Append one compressed text file to another
+.SH SYNOPSIS
+.B mg_text_merge
+[
+.B \-h
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+This program takes two
+.BR mg (1)
+database inverted files and stemmed
+dictionaries, named "old" and "new" respectively, and creates
+a merged stemmed dictionary and inverted file.
+It is part of the
+.BR mgmerge (1)
+addition to the
+.BR mg (1)
+package.
+The two compressed text files are
+.IR "name" .old.text
+and
+.IR "name" .new.text.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.old.text
+The old compressed text.
+.TP
+.B *.new.text
+The new compressed text that will be appended
+.TP
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mgmerge (1),
+.BR mg_get_merge (1),
+.BR mg_invf_merge (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mgquery (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_text_merge.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_text_merge.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_text_merge.c	(revision 14757)
@@ -0,0 +1,249 @@
+/**************************************************************************
+ *
+ * mg_text_merge.c --- merge  *.text, *.text.idx files
+ *                     part of the mgmerge utility
+ * Copyright (C) 1995 Shane Hudson (shane@cosc.canterbury.ac.nz)
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ * Last edited:  November 11 1994
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "messages.h"
+#include "timing.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "locallib.h"
+#include "mg.h"
+#include "mg_merge.h"
+#include "mg_files.h"
+#include "text.h"
+
+
+/**** GLOBALS ****/
+FILE *text[3], *idx[3];
+
+typedef char FileName[256];
+FileName old_name, new_name, merge_name;
+
+long magicsize;			/* == where the header in a file begins */
+
+compressed_text_header cth[3];
+
+/*=======================================================================
+ * init_merge_text(): open files, set up global variables, etc
+ *=======================================================================*/
+int 
+init_merge_text ()
+{
+
+  /* open .text files */
+  text[OLD] = open_file (old_name, TEXT_SUFFIX, "r+b",
+			 MAGIC_TEXT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+  magicsize = ftell (text[OLD]);
+  fread (&cth[OLD], sizeof (cth[OLD]), 1, text[OLD]);
+
+  text[NEW] = open_file (new_name, TEXT_SUFFIX, "rb+",
+			 MAGIC_TEXT, MG_ABORT);
+  fread (&cth[NEW], sizeof (cth[NEW]), 1, text[NEW]);
+
+  /* open .text.idx files */
+  idx[OLD] = open_file (old_name, TEXT_IDX_SUFFIX, "rb+",
+			MAGIC_TEXI, MG_ABORT);
+  fread (&cth[OLD], sizeof (cth[OLD]), 1, idx[OLD]);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(cth[OLD].num_of_docs);
+  NTOHD(cth[OLD].num_of_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(cth[OLD].num_of_words);
+  NTOHUL(cth[OLD].length_of_longest_doc);
+  NTOHD(cth[OLD].ratio);
+
+  idx[NEW] = open_file (new_name, TEXT_IDX_SUFFIX, "rb+",
+			MAGIC_TEXI, MG_ABORT);
+  fread (&cth[NEW], sizeof (cth[NEW]), 1, idx[NEW]);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(cth[NEW].num_of_docs);
+  NTOHD(cth[NEW].num_of_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(cth[NEW].num_of_words);
+  NTOHUL(cth[NEW].length_of_longest_doc);
+  NTOHD(cth[NEW].ratio);
+
+  idx[MERGE] = create_file (merge_name, TEXT_IDX_SUFFIX, "wb",
+			    MAGIC_TEXI, MG_ABORT);
+  return OK;
+}
+
+
+/*=======================================================================
+ * process_merge_text(): merge the files
+ *=======================================================================*/
+int 
+process_merge_text (void)
+{
+  int i;
+  u_long data, offset;
+  byte c;
+
+  /* update and write merged header to .text and .text.idx files */
+  /* they have the exact same header */
+  cth[MERGE].num_of_docs = cth[OLD].num_of_docs
+    + cth[NEW].num_of_docs;
+  cth[MERGE].num_of_bytes = cth[OLD].num_of_bytes
+    + cth[NEW].num_of_bytes;
+  cth[MERGE].num_of_words = cth[OLD].num_of_words;
+  cth[MERGE].length_of_longest_doc =
+    (cth[OLD].length_of_longest_doc > cth[NEW].length_of_longest_doc
+     ? cth[OLD].length_of_longest_doc
+     : cth[NEW].length_of_longest_doc);
+  cth[MERGE].ratio = ((cth[OLD].num_of_bytes * cth[OLD].ratio) +
+		      (cth[NEW].num_of_bytes * cth[NEW].ratio))
+    / cth[MERGE].num_of_bytes;
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(cth[MERGE].num_of_docs);
+  HTOND(cth[MERGE].num_of_bytes); /* [RJM 07/97: 4G limit] */
+  HTONUL(cth[MERGE].num_of_words);
+  HTONUL(cth[MERGE].length_of_longest_doc);
+  HTOND(cth[MERGE].ratio);
+
+  fwrite (&cth[MERGE], sizeof (cth[MERGE]), 1, idx[MERGE]);
+  fseek (text[OLD], magicsize, 0);
+  fwrite (&cth[MERGE], sizeof (cth[MERGE]), 1, text[OLD]);
+
+  /*
+   *  Update *.text.idx:  need to know where each new doc starts
+   *  in the appended .text file
+   */
+  for (i = 0; i < cth[OLD].num_of_docs; i++)
+    {
+      fread (&data, sizeof (u_long), 1, idx[OLD]);
+      fwrite (&data, sizeof (u_long), 1, idx[MERGE]);
+    }
+
+  /* offset is the amount to add to each entry from idx[NEW] */
+  fread (&offset, sizeof (u_long), 1, idx[OLD]);
+  NTOHUL(offset);  /* [RPAP - Jan 97: Endian Ordering] */
+  offset -= (4 + sizeof (cth[OLD]));	/* 4 for the magic number */
+
+  for (i = 0; i < cth[NEW].num_of_docs; i++)
+    {
+      fread (&data, sizeof (u_long), 1, idx[NEW]);
+      NTOHUL(data);  /* [RPAP - Jan 97: Endian Ordering] */
+      data += offset;
+      HTONUL(data);  /* [RPAP - Jan 97: Endian Ordering] */
+      fwrite (&data, sizeof (u_long), 1, idx[MERGE]);
+    }
+  /* write last u_long in idx[MERGE] (= length of file) */
+  fread (&data, sizeof (u_long), 1, idx[NEW]);
+  NTOHUL(data);  /* [RPAP - Jan 97: Endian Ordering] */
+  data += offset;
+  HTONUL(data);  /* [RPAP - Jan 97: Endian Ordering] */
+  fwrite (&data, sizeof (u_long), 1, idx[MERGE]);
+
+/******* update .text *******/
+  /* simply cat's the files together, except for the headers 
+   * and magic numbers, of course
+   */
+  fseek (text[OLD], 0L, 2);
+  while (!feof (text[NEW]))
+    {
+      fread (&c, sizeof (c), 1, text[NEW]);
+      if (!feof (text[NEW]))
+	fwrite (&c, sizeof (c), 1, text[OLD]);
+    }
+
+  return OK;
+}
+
+
+
+/*=======================================================================
+ * done_merge_text(): close files.
+ *=======================================================================*/
+int 
+done_merge_text (void)
+{
+  fclose (idx[MERGE]);
+  fclose (text[OLD]);
+  fclose (idx[OLD]);
+  fclose (text[NEW]);
+  fclose (idx[NEW]);
+
+  fprintf (stderr, "mg_text_merge: %ld documents added to %s\n",
+	   cth[NEW].num_of_docs, merge_name);
+
+  return OK;
+}
+
+
+/*=======================================================================
+ * usage()
+ *=======================================================================*/
+void 
+usage (char *progname)
+{
+  fprintf (stderr, "usage:  %s -f collection_name\n", progname);
+  exit (1);
+}
+
+
+/*=======================================================================
+ * main()
+ *=======================================================================*/
+int main (int argc, char *argv[])
+{
+  char *progname;
+  ProgTime start;
+  int ch;			/* for command line processing */
+
+  progname = argv[0];
+  msg_prefix = argv[0];
+  merge_name[0] = '\0';
+
+  while ((ch = getopt (argc, argv, "f:d:h")) != -1)
+    switch (ch)
+      {
+      case 'f':
+	strcpy (merge_name, optarg);
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 'h':
+      case '?':
+      default:
+	usage (progname);
+      }
+
+  if (merge_name[0] == '\0')
+    usage (progname);
+  strcpy (old_name, merge_name);
+  strcat (old_name, ".old");
+  strcpy (new_name, merge_name);
+  strcat (new_name, ".new");
+
+  GetTime (&start);
+  init_merge_text ();
+  process_merge_text ();
+  done_merge_text ();
+  Message ("%s\n", ElapsedTime (&start, NULL));
+  return 0;
+}
Index: /indexers/branches/3.03a/mg/src/text/mg_weights_build.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_weights_build.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_weights_build.1	(revision 14757)
@@ -0,0 +1,112 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mg_weights_build 1 \*(Dt CITRI
+.SH NAME
+mg_weights_build \- builds the approximate weights file
+.SH SYNOPSIS
+.B mg_weights_build
+[
+.B \-h
+]
+[
+.B \-s
+]
+[
+.BI \-b " num"
+]
+[
+.BI \-d " directory"
+]
+.if n .ti +9n
+.BI \-f " name"
+.SH DESCRIPTION
+.B mg_weights_build
+is the program that generates the approximate weights file and the
+interleaved text index and exact weights file.  To do this, it uses
+the text index and either the exact weights file, or the inverted file
+and stemmed dictionary.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-s
+Save the weights generated from the
+.I *.invf
+and
+.I *.invf.dict
+file in a
+.I *.weight
+file.
+.TP
+.BI \-b " num"
+This specifies the number of bits of precision that should be used for
+the approximate weights.  If not specified, it defaults to 8.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection is.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.dict
+Compressed stemmed dictionary.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.text.idx.wgt
+Interleaved index into the compressed documents and document weights.
+.TP
+.B *.weight.approx
+Approximate document weights.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/text/mg_weights_build.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mg_weights_build.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mg_weights_build.c	(revision 14757)
@@ -0,0 +1,514 @@
+/**************************************************************************
+ *
+ * mg_weights_build.c -- Program to build the document weights file
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "messages.h"
+#include "local_strings.h"
+#include "bitio_gen.h"
+#include "bitio_m.h"
+#include "bitio_m_stdio.h"
+#include "timing.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "locallib.h"
+#include "invf.h"
+#include "text.h"
+#include "words.h"
+
+#define MAXBITS (sizeof(unsigned long) * 8)
+
+/*
+   $Log$
+   Revision 1.2  2004/05/24 21:12:18  kjdon
+   changed a message
+
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:16  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:49  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:22  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.4  1994/11/29  00:32:05  tes
+   * Committing the new merged files and changes.
+   *
+   * Revision 1.3  1994/10/20  03:57:00  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:55  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+unsigned char bits = 8;
+static char *file_name = "";
+static char *text_file_name = "";
+static unsigned long NumPara = 0;
+static unsigned long StaticNumOfDocs = 0;
+
+unsigned long get_NumPara (void);
+unsigned long get_StaticNumOfDocs (void);
+void GenerateWeights (void);
+void Make_weight_approx (void);
+void Make_text_idx_wgt (void);
+
+
+int main (int argc, char **argv)
+{
+  ProgTime StartTime;
+  int ch;
+  opterr = 0;
+  msg_prefix = argv[0];
+  while ((ch = getopt (argc, argv, "f:t:d:b:sh")) != -1) /* [RJM 10/98 - Text Filename] */
+    switch (ch)
+      {
+      case 'f':		/* input file */
+	file_name = optarg;
+	if (strlen(text_file_name) == 0) text_file_name = optarg;
+	break;
+      /* [RJM 10/98 - Text Filename] */
+      case 't':		/* text input file */
+	text_file_name = optarg;
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 'b':
+	bits = atoi (optarg);
+	if (bits > 32)
+	  {
+	    fprintf (stderr, "b may only take values 0-32\n");
+	    exit (1);
+	  }
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-f input_file]"
+		 "[-d data directory] [-b bits] [-s] [-h]\n", argv[0]);
+	exit (1);
+      }
+  GetTime (&StartTime);
+
+  GenerateWeights ();
+
+  Make_weight_approx ();
+
+  Make_text_idx_wgt ();
+
+  Message ("%s", ElapsedTime (&StartTime, NULL));
+
+  return 0;
+}
+
+
+
+
+unsigned long 
+get_NumPara (void)
+{
+  struct invf_dict_header idh;
+  FILE *invf_dict;
+  if (NumPara)
+    return (NumPara);
+  invf_dict = open_file (file_name, INVF_DICT_SUFFIX, "rb", MAGIC_STEM_BUILD,
+			 MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+  fread ((char *) &idh, sizeof (idh), 1, invf_dict);
+  fclose (invf_dict);
+  NTOHUL2(idh.num_of_docs, NumPara);  /* [RPAP - Jan 97: Endian Ordering] */
+  return NumPara;
+}
+
+
+
+unsigned long 
+get_StaticNumOfDocs (void)
+/* the static number of documents is the N parameter used to
+ * decode document gaps in the inverted file encoded using
+ * the Bblock method.
+ */
+{
+  struct invf_dict_header idh;
+  FILE *invf_dict;
+  if (StaticNumOfDocs)
+    return (StaticNumOfDocs);
+  invf_dict = open_file (file_name, INVF_DICT_SUFFIX, "rb", MAGIC_STEM_BUILD,
+			 MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+  fread ((char *) &idh, sizeof (idh), 1, invf_dict);
+  fclose (invf_dict);
+  NTOHUL2(idh.static_num_of_docs, StaticNumOfDocs);  /* [RPAP - Jan 97: Endian Ordering] */
+  return StaticNumOfDocs;
+}
+
+
+
+void GenerateWeights (void) {
+  FILE *dict, *invf, *f, *idx;
+  struct invf_dict_header idh;
+  struct invf_file_header ifh;
+  int i;
+  double logN;
+  float *DocWeights;
+
+  /* make sure the globals NumPara and StaticNumOfDocs are loaded */
+  get_NumPara ();
+  get_StaticNumOfDocs ();
+
+  /* check to see if the weights file has already been built */
+  if ((f = open_file (file_name, WEIGHTS_SUFFIX, "rb", MAGIC_WGHT,
+		      MG_CONTINUE)) != NULL) {
+      fclose (f);
+      return;
+  }
+  Message ("The file \"%s.weight\" does not exist.", file_name);
+  Message ("Building the weight data from the file \"%s.invf\".", file_name);
+
+  logN = log ((double) NumPara);
+
+  /* allocate memory for the weights */
+  if (!(DocWeights = Xmalloc (sizeof (float) * (NumPara + 1))))
+      FatalError (1, "No memory for doc weights");
+  bzero ((char *) DocWeights, sizeof (float) * (NumPara + 1));
+
+  /* open the .invf.dict file and read in its header */
+  dict = open_file (file_name, INVF_DICT_SUFFIX, "rb", MAGIC_STEM_BUILD,
+		    MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+  fread ((char *) &idh, sizeof (idh), 1, dict);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(idh.lookback);
+  NTOHUL(idh.dict_size);
+  NTOHUL(idh.total_bytes);
+  NTOHUL(idh.index_string_bytes);
+  NTOHD(idh.input_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(idh.num_of_docs);
+  NTOHUL(idh.static_num_of_docs);
+  NTOHUL(idh.num_of_words);
+  NTOHUL(idh.stemmer_num);
+  NTOHUL(idh.stem_method);
+
+  /* open .invf.idx */
+  idx = open_file (file_name, INVF_IDX_SUFFIX, "rb", MAGIC_INVI,
+		   MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  /* open .invf and read in its header */
+  invf = open_file (file_name, INVF_SUFFIX, "rb", MAGIC_INVF,
+		    MG_ABORT);
+  fread ((char *) &ifh, sizeof (ifh), 1, invf);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(ifh.no_of_words);
+  NTOHUL(ifh.no_of_ptrs);
+  NTOHUL(ifh.skip_mode);
+  for (i = 0; i <= 15; i++)
+    NTOHUL(ifh.params[i]);
+  NTOHUL(ifh.InvfLevel);
+
+  /* make sure the inverted file does not contain skips and is not level 1 */
+  if (ifh.skip_mode != 0)
+    FatalError (0, "Can\'t make weights file from a skipped inverted file.");
+  if (ifh.InvfLevel == 1)
+    FatalError (0, "Can\'t make weights file from level 1 inverted file.");
+
+  DECODE_START (invf)
+
+    /* process each word adding its contributions to the document weights */
+    for (i = 0; i < ifh.no_of_words; i++)
+    {
+      u_char dummy1, dummy2[MAXSTEMLEN + 1];
+      unsigned long fcnt, wcnt, blk, CurrDoc, p, j;
+      float idf;
+
+      /* give a little feedback every 4096 words */
+      if ((i & 0xfff) == 0)
+	fprintf (stderr, ".");
+
+      /* read an entry for a word, just to get p value */
+      dummy1 = fgetc (dict);
+      dummy1 = fgetc (dict);
+      fread (dummy2, sizeof (u_char), dummy1, dict);
+      fread ((char *) &fcnt, sizeof (fcnt), 1, dict);
+      fread ((char *) &wcnt, sizeof (wcnt), 1, dict);
+
+      dummy2[dummy1] = '\0';
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(fcnt);
+      NTOHUL(wcnt);
+
+      p = fcnt;
+
+      idf = logN - log ((double) fcnt);
+      blk = BIO_Bblock_Init (StaticNumOfDocs, p);
+      CurrDoc = 0;
+
+      /* check the inverted file index entry for this word */
+      {
+	unsigned long loc;
+	fread ((char *) &loc, sizeof (loc), 1, idx);
+	NTOHUL(loc);  /* [RPAP - Jan 97: Endian Ordering] */
+	if (ftell (invf) != loc)
+	  {
+	    FatalError (1, "Word %d  %d != %d", i, ftell (invf), loc);
+	  }
+      }
+
+      for (j = 0; j < p; j++)
+	{
+	  unsigned long x, tf;
+	  BBLOCK_DECODE (x, blk);
+	  CurrDoc += x;
+
+	  if (CurrDoc > idh.num_of_docs) {
+	    FatalError (1, "CurrDoc = %d, number of documents = %d", 
+			CurrDoc, idh.num_of_docs);
+	  }	  
+
+	  if (ifh.InvfLevel >= 2)
+	    {
+	      double weight;
+	      GAMMA_DECODE (tf);
+	      weight = tf * idf;
+	      DocWeights[CurrDoc - 1] += weight * weight;
+	    }
+	}
+      
+      while (__btg)
+	DECODE_BIT;
+    }
+
+  DECODE_DONE
+
+  fclose (dict);
+  fclose (invf);
+  fprintf (stderr, "\n");
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = 0; i < NumPara; i++)
+    HTONF(DocWeights[i]);
+
+  f = create_file (file_name, WEIGHTS_SUFFIX, "wb", MAGIC_WGHT,
+		   MG_ABORT);
+
+  fwrite ((char *) DocWeights, sizeof (float), NumPara, f);
+  fclose (f);
+  Xfree (DocWeights);
+}
+
+
+
+
+
+
+
+
+
+
+
+void 
+Make_weight_approx (void)
+{
+  int i, pos, max;
+  unsigned long buf;
+  double U, L, B;
+  FILE *approx, *exact;
+
+  exact = open_file (file_name, WEIGHTS_SUFFIX, "rb", MAGIC_WGHT,
+		     MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  /* calculate U and L */
+  L = 1e300;
+  U = 0;
+  for (i = 0; i < NumPara; i++)
+    {
+      float wgt;
+      fread ((char *) &wgt, sizeof (wgt), 1, exact);
+      NTOHF(wgt);  /* [RPAP - Jan 97: Endian Ordering] */
+      wgt = sqrt (wgt);
+      if (wgt > U)
+	U = wgt;
+      if (wgt > 0 && wgt < L)
+	L = wgt;
+
+    }
+  fseek (exact, sizeof (u_long), SEEK_SET);
+
+  B = pow (U / L, pow (2.0, -(double) bits));
+
+  fprintf (stderr, "L = %f\n", L);
+  fprintf (stderr, "U = %f\n", U);
+  fprintf (stderr, "B = %f\n", B);
+
+
+
+  approx = create_file (file_name, APPROX_WEIGHTS_SUFFIX, "wb",
+			MAGIC_WGHT_APPROX, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  fwrite ((char *) &bits, sizeof (bits), 1, approx);
+  HTOND(L);  /* [RPAP - Jan 97: Endian Ordering] */
+  HTOND(B);  /* [RPAP - Jan 97: Endian Ordering] */
+  fwrite ((char *) &L, sizeof (L), 1, approx);
+  fwrite ((char *) &B, sizeof (B), 1, approx);
+  NTOHD(L);  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHD(B);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  max = bits == 32 ? 0xffffffff : (1 << bits) - 1;
+  for (buf = pos = i = 0; i < NumPara; i++)
+    {
+      unsigned long fx;
+      float wgt;
+      fread ((char *) &wgt, sizeof (wgt), 1, exact);
+      NTOHF(wgt);  /* [RPAP - Jan 97: Endian Ordering] */
+      wgt = sqrt (wgt);
+      if (wgt == 0)
+	{
+	  wgt = L;
+#ifndef QUIET
+	  Message ("Warning: Document %d had a weight of 0.", i);
+#endif
+	}
+      fx = (int) floor (log (wgt / L) / log (B));
+
+      if (fx > max)
+	fx = max;
+
+      buf |= (fx << pos);
+      pos += bits;
+
+      if (pos >= MAXBITS)
+	{
+	  HTONUL(buf);
+	  fwrite ((char *) &buf, sizeof (buf), 1, approx);
+	  buf = fx >> (bits - (pos - MAXBITS));
+	  pos = pos - MAXBITS;
+	}
+    }
+  if (pos > 0)
+    {
+      /* [RPAP - Jan 97: Endian Ordering] */
+      HTONUL(buf);
+      fwrite ((char *) &buf, sizeof (buf), 1, approx);
+    }
+
+  fclose (approx);
+  fclose (exact);
+}
+
+
+
+
+
+void 
+Make_text_idx_wgt (void)
+{
+  compressed_text_header cth;
+  int i;
+  FILE *idx_wgt, *idx, *para, *exact;
+
+  idx_wgt = create_file (file_name, TEXT_IDX_WGT_SUFFIX, "wb", MAGIC_TEXI_WGT,
+			 MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  /* [RJM 10/98 - Text Filename] */
+  idx = open_file (text_file_name, TEXT_IDX_SUFFIX, "rb", MAGIC_TEXI,
+		   MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+  if (fread (&cth, sizeof (cth), 1, idx) != 1)
+    FatalError (1, "Unable to read header of index file");
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(cth.num_of_docs);
+  NTOHD(cth.num_of_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(cth.num_of_words);
+  NTOHUL(cth.length_of_longest_doc);
+  NTOHD(cth.ratio);
+
+  exact = open_file (file_name, WEIGHTS_SUFFIX, "rb", MAGIC_WGHT,
+		     MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  get_NumPara ();
+  if (cth.num_of_docs != NumPara)
+    {
+      Message ("The number of documents %d does not equal "
+	       "the number of paragraphs %d.", cth.num_of_docs, NumPara);
+      Message ("Using the \"%s.invf.paragraph\" file\n", file_name);
+      para = open_file (file_name, INVF_PARAGRAPH_SUFFIX, "rb", MAGIC_PARAGRAPH,
+			MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+    }
+  else
+    para = NULL;
+
+  {
+    struct
+      {
+	unsigned long Start;
+	float Weight;
+      }
+    data;
+    for (i = 0; i < cth.num_of_docs; i++)
+      {
+	int count;
+	fread ((char *) &data.Start, sizeof (unsigned long), 1, idx);
+	if (para && i < cth.num_of_docs)
+	  {
+	    /* [RPAP - Jan 97: Endian Ordering] */
+	    fread ((char *) &count, sizeof (count), 1, para);
+	    NTOHSI(count);
+	  }
+	else
+	  count = 1;
+	while (count--)
+	  {
+	    fread ((char *) &data.Weight, sizeof (float), 1, exact);
+	    NTOHF(data.Weight);  /* [RPAP - Jan 97: Endian Ordering] */
+	    data.Weight = sqrt (data.Weight);
+	    HTONF(data.Weight);  /* [RPAP - Jan 97: Endian Ordering] */
+	    fwrite ((char *) &data, sizeof (data), 1, idx_wgt);
+	  }
+      }
+    /* Write out the extra entry for the idx file */
+    fread ((char *) &data.Start, sizeof (unsigned long), 1, idx);
+    data.Weight = 0;
+    fwrite((char*)&data, sizeof(data), 1, idx_wgt);
+  }
+
+  fclose (idx_wgt);
+  fclose (idx);
+  fclose (exact);
+  if (para)
+    fclose (para);
+}
Index: /indexers/branches/3.03a/mg/src/text/mgdictlist.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mgdictlist.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mgdictlist.1	(revision 14757)
@@ -0,0 +1,72 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgdictlist 1 \*(Dt CITRI
+.SH NAME
+mgdictlist \- list the contents of a dictionary
+.SH SYNOPSIS
+.B mgdictlist
+[
+.B \-q
+]
+.I filename
+.SH DESCRIPTION
+.B mgdictlist
+lists the contents of either a compressed compression dictionary, a
+text statistics file, or a compressed stemmed dictionary.  Unlike all
+the other programs in the
+.BR mg (1)
+suite, it is necessary to specify the complete pathname of the
+dictionary to list.
+.SH OPTIONS
+The
+.I filename
+must be last.
+.TP "\w'\fIfilename\fP'u+2n"
+.B \-q
+Generate an abbreviated output (machine-readable rather than
+human-readable).
+.TP
+.I filename
+This is the name of the dictionary to list.
+.B mgdictlist
+automatically detects whether the file is a compressed compression
+dictionary, text statistics file, or a compressed stemmed dictionary.
+.SH FILES
+.TP 20
+.B *.text.dict
+Text statistics file.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.invf.build
+Compressed stemmed dictionary.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/text/mgdictlist.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mgdictlist.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mgdictlist.c	(revision 14757)
@@ -0,0 +1,408 @@
+/**************************************************************************
+ *
+ * mgdictlist.c -- Program to list a dictionary
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "messages.h"
+#include "memlib.h"
+#include "local_strings.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "text.h"
+#include "invf.h"
+#include "locallib.h"
+#include "words.h"
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:17  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:49  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:24  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.4  1994/11/29  00:32:07  tes
+   * Committing the new merged files and changes.
+   *
+   * Revision 1.3  1994/10/20  03:57:01  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:56  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+
+int quick = 0;
+int no_of_words[2];
+u_long maxcodelen[2];
+
+char *dictname = "";
+
+
+
+
+void 
+DumpStemDict (FILE * f)
+{
+  struct invf_dict_header idh;
+  int i;
+  u_char prev[MAXSTEMLEN + 1];
+
+  fread (&idh, sizeof (idh), 1, f);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(idh.lookback);
+  NTOHUL(idh.dict_size);
+  NTOHUL(idh.total_bytes);
+  NTOHUL(idh.index_string_bytes);
+  NTOHD(idh.input_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(idh.num_of_docs);
+  NTOHUL(idh.static_num_of_docs);
+  NTOHUL(idh.num_of_words);
+  NTOHUL(idh.stemmer_num);
+  NTOHUL(idh.stem_method);
+
+  if (quick)
+    printf ("%ld\n", idh.dict_size);
+  else
+    {
+      printf ("# lookback           = %lu\n", idh.lookback);
+      printf ("# dict size          = %lu\n", idh.dict_size);
+      printf ("# total bytes        = %lu\n", idh.total_bytes);
+      printf ("# index string bytes = %lu\n", idh.index_string_bytes);
+      printf ("# input bytes        = %.0f\n", idh.input_bytes); /* [RJM 07/97: 4G limit] */
+      printf ("# num of docs        = %lu\n", idh.num_of_docs);
+      printf ("# static num of docs = %lu\n", idh.static_num_of_docs);
+      printf ("# num of words       = %lu\n", idh.num_of_words);
+      printf ("#\n");
+    }
+
+  for (i = 0; i < idh.dict_size; i++)
+    {
+      register unsigned long copy, suff;
+      unsigned long wcnt, fcnt;
+
+      /* build a new word on top of prev */
+      copy = getc (f);
+      suff = getc (f);
+      *prev = copy + suff;
+      fread (prev + copy + 1, sizeof (u_char), suff, f);
+
+      /* read other data, but no need to store it */
+      fread (&fcnt, sizeof (fcnt), 1, f);
+      fread (&wcnt, sizeof (wcnt), 1, f);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(fcnt);
+      NTOHUL(wcnt);
+
+      if (!quick)
+	{
+	  printf ("%d: %8ld ", i, wcnt);
+	  printf ("/ %5ld ", fcnt);
+	  printf ("%2d %2ld\t\"", *prev, copy);
+	}
+      printf ("%s", word2str (prev));
+      if (quick)
+	printf (" %ld %ld\n", wcnt, fcnt);
+      else
+	{
+	  putchar ('"');
+	  putchar ('\n');
+	}
+    }
+}
+
+
+
+
+void 
+ReadInWords (FILE * f)
+{
+  comp_frags_header cfh;
+  u_long *codes;
+  u_char prev[MAXSTEMLEN + 1];
+  int i;
+
+  if (Read_cfh (f, &cfh, NULL, NULL) == -1)
+    FatalError (1, "Unable to read in the dictionary");
+
+  printf ("#\n");
+  printf ("#   max code len       = %u\n", cfh.hd.maxcodelen);
+  printf ("#   total bytes        = %lu\n", cfh.uncompressed_size);
+  printf ("#\n");
+
+  if (!(codes = Generate_Huffman_Codes (&cfh.hd, NULL)))
+    FatalError (1, "no memory for huffman codes\n");
+
+  for (i = 0; i < cfh.hd.num_codes; i++)
+    {
+      register int val, copy, j, k;
+      char code[33];
+      val = fgetc (f);
+      copy = (val >> 4) & 0xf;
+      val &= 0xf;
+
+      fread (prev + copy + 1, sizeof (u_char), val, f);
+      *prev = val + copy;
+
+      for (k = 0, j = cfh.hd.clens[i] - 1; j >= 0; j--, k++)
+	code[k] = '0' + ((codes[i] >> j) & 1);
+      code[k] = '\0';
+
+      printf ("%d: %2d : %*s : \"%s\"\n", i, cfh.hd.clens[i],
+	      cfh.hd.maxcodelen, code, word2str (prev));
+    }
+  Xfree (codes);
+  Xfree (cfh.hd.clens);
+}
+
+
+void 
+ReadCharHuffman (FILE * f, char *title)
+{
+  int i;
+  huff_data hd;
+  u_long *codes;
+
+  if (Read_Huffman_Data (f, &hd, NULL, NULL) == -1)
+    FatalError (1, "Unable to read huffman data");
+
+  if (!(codes = Generate_Huffman_Codes (&hd, NULL)))
+    FatalError (1, "no memory for huffman codes\n");
+
+  printf ("#\n# %s\n#\n", title);
+  for (i = 0; i < hd.num_codes; i++)
+    if (hd.clens[i])
+      {
+	int j, k;
+	char code[33];
+	for (k = 0, j = hd.clens[i] - 1; j >= 0; j--, k++)
+	  code[k] = '0' + ((codes[i] >> j) & 1);
+	code[k] = '\0';
+	printf ("%2d : %*s : \"%s\"\n", hd.clens[i],
+		hd.maxcodelen, code, char2str (i));
+      }
+  Xfree (codes);
+  Xfree (hd.clens);
+}
+
+
+void 
+ReadLenHuffman (FILE * f, char *title)
+{
+  int i;
+  huff_data hd;
+  u_long *codes;
+
+  if (Read_Huffman_Data (f, &hd, NULL, NULL) == -1)
+    FatalError (1, "Unable to read huffman data");
+
+  if (!(codes = Generate_Huffman_Codes (&hd, NULL)))
+    FatalError (1, "no memory for huffman codes\n");
+
+  printf ("#\n# %s\n#\n", title);
+  for (i = 0; i < hd.num_codes; i++)
+    if (hd.clens[i])
+      {
+	int j, k;
+	char code[33];
+	for (k = 0, j = hd.clens[i] - 1; j >= 0; j--, k++)
+	  code[k] = '0' + ((codes[i] >> j) & 1);
+	code[k] = '\0';
+	printf ("%2d : %*s : %d\n", hd.clens[i],
+		hd.maxcodelen, code, i);
+      }
+  Xfree (codes);
+  Xfree (hd.clens);
+}
+
+
+
+
+
+void 
+DumpTextDict (FILE * f)
+{
+  struct compression_dict_header cdh;
+  int which;
+
+  if (Read_cdh (f, &cdh, NULL, NULL) == -1)
+    FatalError (1, "Unable to read dictionary header");
+  switch (cdh.dict_type)
+    {
+    case MG_COMPLETE_DICTIONARY:
+      printf ("# COMPLETE DICTIONARY\n");
+      break;
+    case MG_PARTIAL_DICTIONARY:
+      printf ("# PARTIAL DICTIONARY\n");
+      break;
+    case MG_SEED_DICTIONARY:
+      printf ("# SEED DICTIONARY\n");
+      break;
+    }
+  printf ("# num words          = %lu\n", cdh.num_words[1]);
+  printf ("# num word chars     = %lu\n", cdh.num_word_chars[1]);
+  printf ("# num non-words      = %lu\n", cdh.num_words[0]);
+  printf ("# num non-word chars = %lu\n", cdh.num_word_chars[0]);
+  printf ("# lookback           = %lu\n", cdh.lookback);
+
+  for (which = 0; which < 2; which++)
+    switch (cdh.dict_type)
+      {
+      case MG_COMPLETE_DICTIONARY:
+	{
+	  ReadInWords (f);
+	}
+	break;
+      case MG_PARTIAL_DICTIONARY:
+	{
+	  if (cdh.num_words[which])
+	    ReadInWords (f);
+
+	  ReadCharHuffman (f, "Characters");
+	  ReadLenHuffman (f, "Lengths");
+	}
+	break;
+      case MG_SEED_DICTIONARY:
+	{
+	  if (cdh.num_words[which])
+	    ReadInWords (f);
+
+	  ReadCharHuffman (f, "Characters");
+	  ReadLenHuffman (f, "Lengths");
+	}
+	break;
+      }
+}
+
+
+
+
+void 
+DumpStatsDict (FILE * f)
+{
+  int i;
+  compression_stats_header csh;
+
+  fread (&csh, sizeof (csh), 1, f);
+
+  for (i = 0; i < 2; i++)
+    {
+      int j;
+      frags_stats_header fsh;
+
+      fread (&fsh, sizeof (fsh), 1, f);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(fsh.num_frags);
+      NTOHUL(fsh.mem_for_frags);
+
+      if (!quick)
+	printf ("#\n# num %9s      = %lu\n#\n", i ? "words" : "non-words",
+		fsh.num_frags);
+
+      for (j = 0; j < fsh.num_frags; j++)
+	{
+	  u_char Word[16];
+	  u_long freq, occur_num;
+
+	  fread (&freq, sizeof (freq), 1, f);
+	  fread (&occur_num, sizeof (occur_num), 1, f);
+
+	  /* [RPAP - Jan 97: Endian Ordering] */
+	  NTOHUL(freq);
+	  NTOHUL(occur_num);
+
+	  Word[0] = fgetc (f);
+	  fread (Word + 1, Word[0], 1, f);
+	  printf ("%d: %7ld : %7ld : \"%s\"\n", j, freq,
+		  occur_num, word2str (Word));
+	}
+    }
+}
+
+
+int main (int argc, char **argv)
+{
+  FILE *fp;
+  unsigned long magic = 0;
+
+  if (argc < 2)
+    FatalError (1, "A file name must be specified");
+  dictname = argv[1];
+  if (strcmp (dictname, "-q") == 0)
+    {
+      quick = 1;
+      if (argc < 3)
+	FatalError (1, "A file name must be specified");
+      dictname = argv[2];
+    }
+  if (!(fp = fopen (dictname, "rb")))  /* [RPAP - Feb 97: WIN32 Port] */
+    FatalError (1, "Unable to open \"%s\"", dictname);
+
+  fread (&magic, sizeof (magic), 1, fp);
+
+  NTOHUL(magic);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  switch (magic)
+    {
+    case MAGIC_STEM_BUILD:
+      if (!quick)
+	printf ("# Contents of STEM file \"%s\"\n#\n", dictname);
+      DumpStemDict (fp);
+      break;
+    case MAGIC_DICT:
+      if (!quick)
+	printf ("# Contents of DICT file \"%s\"\n#\n", dictname);
+      DumpTextDict (fp);
+      break;
+    case MAGIC_STATS_DICT:
+      if (!quick)
+	printf ("# Contents of STATS file \"%s\"\n#\n", dictname);
+      DumpStatsDict (fp);
+      break;
+    default:
+      FatalError (1, "Bad magic number. \"%s\" cannot be dumped", dictname);
+    }
+  fclose (fp);
+  return 0;
+}
Index: /indexers/branches/3.03a/mg/src/text/mgquery.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mgquery.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mgquery.1	(revision 14757)
@@ -0,0 +1,693 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgquery 1 \*(Dt CITRI
+.SH NAME
+mgquery \- query program for the mg system
+.SH SYNOPSIS
+.B mgquery
+[
+.B \-h
+]
+[
+.B \-D
+]
+[
+.BI \-f " name"
+]
+[
+.BI \-d " directory"
+]
+.if n .ti +9n
+[
+.I collection-name
+]
+.SH DESCRIPTION
+.B mgquery
+enables users to make Boolean or ranked queries from a data base
+generated by the
+.BR mg (1)
+system.  It accepts queries from
+.I stdin
+and sends the retrieved documents to
+.IR stdout .
+Information on the resource usage of
+.B mgquery
+as it processes queries can be obtained interactively.
+.SH OPTIONS
+Options may appear in any order, but the
+.IR collection-name ,
+if specified, must be last.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-D
+This option causes the entire text to be decompressed and sent to
+.IR stdout .
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection that will be
+used.  If a collection with the specified base
+.I name
+does not exist, an error message will be displayed and
+.B mgquery
+will exit.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.SH USAGE
+Prior to processing the command line arguments, the
+.B mgquery
+program attempts to read in a startup script called
+.IR ./.mgrc .
+If that fails, it attempts to read in the file
+.IR $HOME/.mgrc .
+The startup file can only contain commands\(emno queries are
+permitted in the
+.I .mgrc
+file.  Lines starting with \*(lq\fB#\fP\*(rq in the file are comments.
+The most common use for the
+.I .mgrc
+file is to personalise the initial values of the predefined parameters
+with
+.B .set
+commands.
+.LP
+The input to
+.B mgquery
+consists of a series of input lines.  The backslash
+character
+.RB (\*(lq \e \*(rq)
+is used at the end of lines to indicate
+that input continues on the next line.
+.LP
+Input lines on which the first character is a dot
+.RB (\*(lq . \*(rq)
+are commands to the
+.B mgquery
+program.  Input lines that do not start with a dot are queries.
+.LP
+A query consists of two parts.  One part is a Boolean or ranked query
+that identifies documents.  The second part is a post-processing
+pattern matching operation.  Any text between the first speech mark
+(\*(lq) and the last speech mark (\*(rq) is considered to be a
+post-processing pattern.
+.SH COMMANDS
+The
+.B mgquery
+program can accept the following commands.
+.TP 17
+.B .help
+Display several pages of help text.
+.TP
+.B .quit
+Quit the program.
+.TP
+.B .warranty
+Display the
+.BR mg (1)
+warranty.
+.TP
+.B .conditions
+Display the conditions of use and distribution of
+.BR mg (1).
+.TP
+.BI ".set " "name value"
+Set the parameter
+.I name
+to the specified
+.IR value .
+If the parameter is a Boolean
+.I value
+and the
+.I value
+is omitted, the parameter will be inverted (i.e., if it was
+.IR true ,
+then it will change to
+.IR false ;
+if it was
+.IR false ,
+then it will change to
+.IR true ).
+.TP
+.BI ".unset " name
+Delete the parameter
+.I name
+from the currently-defined parameters.
+.TP
+.B .reset
+Reset the parameters to the state that they had after the processing
+of the
+.B mgquery
+command line.
+.TP
+.B .display
+Display the values of all the currently-defined parameters.
+.TP
+.B .push
+Push the currently-defined parameters onto a stack.
+.TP
+.B .pop
+Pops a set of parameters off the stack, replacing the currently-defined
+ones.
+.TP
+.BI ".output " arg
+This is used to specify where to send the text of the documents.  Once
+the
+.B .output
+command is specified, all subsequent output will be sent to the place
+specified by
+.IR arg .
+If
+.I arg
+is not specified subsequent output will be directed to
+.IR stdout .
+.I Arg
+may be any of the following.
+.RS
+.TP 13
+.BI "> " filename
+Send output to the specified file.
+.TP
+.BI ">> " filename
+Append output to the specified file.
+.TP
+.BI "| " command
+Pipe the output to
+.IR command ,
+which is executed by
+.IR sh .
+.RE
+.TP
+.BI ".input " arg
+This is used to specify where input (queries and commands) comes
+from.  Once the
+.B .input
+command is specified all subsequent input will be come from the place
+specified by
+.IR arg .
+If
+.I arg
+is not specified subsequent input will come from
+.IR stdin .
+.RS
+.TP 13
+.BI "< " filename
+Get input from the specified file.
+.TP
+.BI "| " command
+The input comes from the standard output of
+.IR command ,
+which is executed by
+.IR sh .
+.RE
+.SH PARAMETERS
+The following parameters are predefined and have special
+significance.  Each parameter will be followed by its default
+value.  Parameters are initialised before the
+.I .mgrc
+file is read or the command line arguments are processed.
+.TP 17
+.BI accumulator_method " `array'"
+This parameter is used during ranking, and specifies how the
+weight for each document should be accumulated.  The following
+methods are available:
+.IR array ,
+.IR splay_tree ,
+.IR hash_table ,
+and
+.IR list .
+.TP
+.BI briefstats " `off'"
+This is a Boolean parameter that determines whether the
+totals for disk, memory and time usage statistics will be
+displayed at the end of each query.
+.IR Note :
+this takes precedence over the parameters
+.BR diskstats ,
+.BR memstats " and " timestats .
+This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI buffer " `1048576'"
+When the documents are being read in, they are read into a
+buffer of this size and then displayed from this buffer.  If
+the documents are larger than this buffer, the buffer is
+expanded automatically.  Having a large buffer gives a very
+slight performance improvement, because it allows the order of
+disk operations to be optimised.  The buffer size is measured
+in bytes.
+.TP
+.BI diskstats " `off'"
+This is a Boolean parameter that determines whether the disk
+usage statistics for the preceding query will be displayed
+after each query.  This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI doc_sepstr " `---------------------------------- %n\en\'"
+This specifies the string that will be used to separate
+documents when they are displayed for `Boolean' or `docnums'
+queries.  The standard C escape character sequences
+may be used to place special characters in the
+string.  For example, a newline would be `\en'.  To include a `%',
+use the sequence `%%'.  To include the
+.BR mg (1)
+document number, use the sequence `%n'.  The following escape character
+sequences are available
+.nf
+.ta 1.7iL
+.B Sequence	Meaning
+`\e\e'	backslash
+`\eb'	backspace
+`\ef'	formfeed
+`\en'	newline
+`\er'	carriage return
+`\et'	tab
+`\e"'	speech marks
+`\e''	quote mark
+`\ex\fIhh\fP'	ASCII code in hexadecimal
+`\ennn'	ASCII code in octal
+.fi
+.TP
+.BI expert " `false'"
+If this is
+.IR true ,
+then much of the dialogue output is suppressed.  This parameter may
+take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI hash_tbl_size " `1000'"
+One of the options during ranking queries is to use a hash
+table to accumulate the weights for each document.  The hash
+table is a simple chained type.  This parameter specifies the
+size of the hash table and may take any value between 8 and
+268435456 (2^28).
+.TP
+.BI heads_length " `50'"
+When the mode is
+.BR heads ,
+this specifies the number of characters that will be output for each
+document.
+.TP
+.BI maxdocs " `all'"
+The maximum number of documents to display in response to a
+query.  This parameter may take on a numeric value between 1
+and 429467295 (2^32 - 1) or the word
+.IR all .
+.TP
+.BI maxparas " `1000'"
+The maximum number of paragraphs to identify during a ranked
+query with paragraph indexing.  After the paragraphs have been
+identified, the paragraphs are converted into documents, and
+because some of the paragraphs may refer to the same documents
+the final number of answers may be less than
+.BR maxparas .
+The
+.B maxdocs
+parameter will then be applied.  This parameter may take on a numeric
+value between 1 and 429467295 (2^32 - 1).
+.TP
+.BI max_accumulators " `50000'"
+This parameter limits the number of different paragraph and
+document numbers to be accumulated during ranked queries when
+the parameter
+.B accumulator_method
+is set to
+.IR splay_tree ,
+.IR hash_table ,
+or
+.IR list .
+This parameter may take any value between 8 and 268435456 (2^28).
+.TP
+.BI max_terms " `all'"
+This parameter limits the number of terms that will actually
+be used during a ranked query.  If more terms than the number
+specified by
+.B max_terms
+are entered, then the extra terms will be discarded.  If
+.B sorted_terms
+is on, then the limiting will be done after the terms have been
+sorted.  This parameter may take any value between 1 and 429467295
+(2^32 - 1), or the word
+.IR all.
+.TP
+.BI memstats " `off'"
+This is a Boolean parameter that determines whether the memory
+usage statistics for the preceding query will be displayed
+after each query.  This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI mgdir " `.'"
+This is set to the directory where the
+.BR mg (1)
+data files may be found.  If
+the environment variable
+.B MGDATA
+exists, then this is instead initialised to the value of
+.BR MGDATA .
+The value of this parameter may be changed, either in the
+.I .mgrc
+file with a
+.BI ".set mgdir "directory
+command, or from the command line using the
+.BI \-d " directory"
+option.  Once the \*(lq\fB>\fP\*(rq prompt appears, changing this
+parameter will have no effect.
+.TP
+.BI mgname " `bible'"
+This is set to the name of the
+.BR mg (1)
+collection that is to be used for the session.  The value of this
+parameter may be changed, either in the
+.I .mgrc
+file with a
+.BI ".set mgname "name
+command, or from the command line using the
+.BI \-f " name"
+option.  Once the \*(lq\fB>\fP\*(rq prompt appears, changing this
+parameter will have no effect.
+.TP
+.BI mode " `text'"
+This specifies how documents should be displayed when they
+are retrieved.  It may take six different values:
+.IR text ,
+.IR hilite ,
+.IR docnums ,
+.IR heads ,
+.IR silent ,
+or
+.IR count .
+.I text
+displays the contents of the document.
+.I hilite
+displays the contents of the document and highlights any of the 
+stemmed query terms.
+.I docnums
+displays only the document numbers.
+.I heads
+is used to print out the head of each document.
+.I silent
+retrieves all the documents but displays nothing except how many
+documents were retrieved.  This mode is intended to be used in timing
+experiments.
+.I count
+does the minimum
+amount of work required to determine how many documents would
+be retrieved, but does not retrieve them.
+.TP
+.BI optimise_type " `1'"
+There are three types of boolean query optimisation (parse tree
+rearrangement). Type 0 leaves parse tree unaltered. Type 1 optimises
+for AND of terms and AND of OR of terms. Type 2 converts the tree
+into DNF (an experiment :-).
+.TP
+.BI pager " `more'"
+This is the name of the program that will be used to display
+the help and the retrieved documents.  If the environment
+variable
+.B PAGER
+is defined, then
+.B pager
+takes on that value.
+.TP
+.BI hilite_style " `bold'"
+This specifies the type of highlighting method.
+It may take one of two different values:
+.IR bold,
+or
+.IR underline.
+.TP
+.BI para_sepstr " `\en######## PARAGRAPH %n ########\en'"
+This specifies the string that will be used to separate paragraphs.
+The standard C escape character sequences may be used to place special
+characters in the string.  For example, a newline would be written
+as `\en'.  To include a `%', use the sequence `%%'.  To include the
+paragraph number within the document, use the sequence `%n'.
+.TP
+.BI para_start " `***** Weight = %w *****\en'"
+This specifies the string that will be used at the head of paragraphs
+for a paragraph-level index following a ranked query.  The standard
+C-language escape character sequences may be used to place special
+characters in the string.  For example, a newline would be written as
+`\en'.  To include a `%', use the sequence `%%'.  To include the
+paragraph weight, use the sequence `%w'.
+.TP
+.BI qfreq " `true'"
+This determine whether the ranked queries will take into account the
+number of times each query term is specified.  When this is
+.IR true ,
+the number of times a term appears in the query is used in the
+ranking.  When this is
+.IR false ,
+all query terms are assumed to occur only once.  This parameter may
+take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI query  " `Boolean'"
+This specifies the type of queries that are to be specified.
+It can take four different values:
+.IR Boolean ,
+.IR ranked ,
+.IR docnums " or " approx-ranked.
+.I Boolean
+is for Boolean queries.
+The
+.BR yacc (1)
+grammar for Boolean queries is as follows.
+.IP
+.nf
+        query   : or;
+.IP
+        or      : or '|' and
+                | and ;
+.IP
+        and     : and '&' not
+                | and not
+                | not ;
+.IP
+        not     : term
+                | '!' not ;
+.IP
+        term    : TERM
+                | '(' or ')' ;
+.fi
+.IP
+.IR ranked " and " approx-ranked
+are for queries ranked by the cosine measure.
+.I approx-ranked
+uses only the low-precision document lengths, and therefore only
+produces an approximation to full cosine ranking.
+.IP
+.nf
+        query   : TERM
+                | query TERM ;
+.fi
+.IP
+.I docnums
+allows the entry of document numbers.  Multiple numbers separated by
+spaces may be specified, or ranges separated by hyphens.
+.IP
+.nf
+        query   : range
+                | query range ;
+.IP
+        range   : num
+                | num '-' num ;
+.fi
+.TP
+.BI ranked_doc_sepstr " `-------------------------------- %n %w\en'"
+This specifies the string that will be used to separate documents when
+they are displayed for `ranked' or `approx-ranked' queries.  The
+standard C escape character sequences may be used to place special
+characters in the string.  For example, a newline would be written as
+`\en'.  To include a `%', use the sequence `%%'.  To include the
+.BR mg (1)
+document number, use the sequence `%n'.  To include the document
+weight, use the sequence `%w'.
+.TP
+.BI sizestats " `false'"
+If this is
+.IR true ,
+then various numbers are output at the end of each query indicating
+what went on during the query.  This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI skip_dump " `skips.%d'"
+If this parameter is set, then a file will be produced in the current
+directory during ranked queries on skipped inverted files when
+.B accumulator_method
+is set to
+.IR splay_tree ,
+.IR hash_table ,
+or
+.IR list .
+The name of the file is the value of this parameter.  A `%d' in the
+file name will be replaced with the process id of
+.BR mgquery .
+This file will contain information about the usage of skips during the
+query processing.  This option is expensive; use
+.B .unset skip_dump
+to obtain optimal performance.
+.TP
+.BI sorted_terms " `on'"
+This specifies whether or not the terms should be sorted into
+decreasing occurrence in documents so that the least-often occurring
+terms are processed first when ranked queries are being done.  When
+this is
+.IR true ,
+the terms are sorted.  When this is
+.IR false ,
+the terms are not sorted, and are instead processed in order of
+occurrence.  This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI stop_at_max_accum " `on'"
+This specifies what should happen when the maximum number of
+accumulators set by
+.B max_accumulators
+is reached.  When this is
+.IR true ,
+the processing of terms is stopped at the completion of the current
+term.  When this is
+.IR false ,
+processing continues but no new accumulators are created.  This
+parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI terminator " `'"
+This specifies the string that will be output after the last document
+from the previous query has been output.  The standard C escape
+character sequences may be used to place special characters in the
+string.  For example, a newline would be written as `\en'.  To include
+a `%', use the sequence `%%'.
+.TP
+.BI timestats " `false'"
+If this is
+.IR true ,
+then the time to process a query is displayed in both real time and
+CPU time.  This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.TP
+.BI verbatim " `off'"
+This is a Boolean parameter that determines whether the program
+should attempt to do a regular-expression match on the retrieved
+text.  If verbatim is
+.I on
+and a post-processing string is specified with the query, then the
+post-processing string will be searched for in the documents just
+before they are displayed.  If the string is found, the document will
+be displayed; if not, the document will not be displayed.  If verbatim
+is
+.IR off ,
+the post-processing string will be considered a regular expression
+as in
+.BR egrep (1)
+or
+.BR vi (1).
+E.g., if verbatim is
+.I on,
+\*(lq\fBand.*the\fP\*(rq will look for the 8-character sequence
+\*(lq\fBand.*the\fP\*(rq.  If verbatim is
+.IR off ,
+\*(lq\fBand.*the\fP\*(rq will look for the sequence
+\*(lq\fBand\fP\*(rq followed somewhere later in the document by the
+sequence \*(lq\fBthe\fP\*(rq.  This parameter may take the values
+.IR yes ", " no ", "
+.IR true ", " false ", "
+.IR on " or " off .
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.I .mgrc
+.B mgquery
+startup file
+.TP
+.B help.mg
+Help file for
+.BR mgquery .
+The contents of this file is displayed with the
+.B .help
+command.
+.TP
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.dict
+The `on-disk' stemmed dictionary.
+.TP
+.B *.text
+Compressed documents.
+.TP
+.B *.text.dict
+Compression dictionary.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.text.idx.wgt
+Interleaved index into the compressed documents and document weights.
+.TP
+.B *.weight.approx
+Approximate document weights.
+.SH "SEE ALSO"
+.na
+.BR egrep (1),
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgstat (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1),
+.BR vi (1),
+.BR yacc (1).
Index: /indexers/branches/3.03a/mg/src/text/mgquery.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mgquery.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mgquery.c	(revision 14757)
@@ -0,0 +1,1502 @@
+/**************************************************************************
+ *
+ * mgquery.c -- The   M G Q U E R Y   program
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.2  2004/06/22 04:17:51  kjdon
+   fixed a couple of compiler warnings
+
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:18  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.3  1999/01/08 00:33:46  rjmcnab
+
+   Enabled mg and the library software to read in more than one index
+   at a time.
+
+   Revision 1.2  1998/11/25 07:55:49  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:29  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:57:02  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:41:58  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+#include "sysfuncs.h"
+
+#if defined(HAVE_SYS_PROCFS_H) && defined(HAVE_PR_BRKSIZE) && \
+    (__STDC__ == 0)
+/* STDC test was included to allow cc -Xc on SunOS 5 to work */
+#define USE_PROCESS_MEM
+#endif
+
+#ifdef USE_PROCESS_MEM
+# include <sys/procfs.h>
+#endif
+
+#ifdef HAVE_GETRUSAGE
+# ifdef HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# endif
+# include <sys/resource.h>
+#endif
+
+#ifndef HAVE_GETPAGESIZE
+# include "getpagesize.h"
+#endif
+ 
+#if WITH_REGEX
+# include <regex.h>
+#else
+# include <rx.h>
+#endif
+
+
+#include <stdarg.h>
+#include <signal.h>
+
+#include "messages.h"
+#include "timing.h"
+#include "memlib.h"
+#include "local_strings.h"  /* [RPAP - Feb 97: Term Frequency] */
+
+#include "filestats.h"
+#include "invf.h"
+#include "text.h"
+#include "mg.h"
+#include "lists.h"
+#include "backend.h"
+#include "environment.h"
+#include "globals.h"
+#include "read_line.h"
+#include "mg_errors.h"
+#include "commands.h"
+#include "text_get.h"
+#include "term_lists.h"
+#include "query_term_list.h"
+
+
+FILE *OutFile = NULL, *InFile = NULL;
+int OutPipe = 0, InPipe = 0;
+int Quitting = 0;
+
+/* [RPAP - Feb 97: NZDL Additions] */
+#if defined(PARADOCNUM) ||  defined(NZDL)
+int GetDocNumFromParaNum(query_data *qd, int paranum) {
+  int Documents = qd->td->cth.num_of_docs;
+  int *Paragraph = qd->paragraph;
+  int low = 1, high = Documents;
+  int mid = (low+high)/2;
+
+  while ((mid = (low+high)/2) >=1 && mid <= Documents)
+    {
+      if (paranum > Paragraph[mid])
+	low = mid+1;
+      else if (paranum <= Paragraph[mid-1])
+	high = mid-1;
+      else
+	return mid;
+    }
+  FatalError(1, "Bad paragraph number.\n");
+}
+#endif
+
+#ifdef TREC_MODE
+char *trec_ids = NULL;
+long *trec_paras = NULL;
+#endif
+
+static volatile int PagerRunning = 0;
+static volatile int Ctrl_C = 0;
+
+
+/*****************************************************************************/
+
+typedef enum
+  {
+    S_Time, S_Mem, S_Size, S_File
+  }
+S_Type;
+
+static struct Stat
+  {
+    S_Type typ;
+    char *name;
+    char *text;
+  }
+ *Stats = NULL;
+static int NumStats = 0;
+
+static void 
+Clear_Stats (void)
+{
+  if (Stats)
+    {
+      int i;
+      for (i = 0; i < NumStats; i++)
+	{
+	  if (Stats[i].name)
+	    Xfree (Stats[i].name);
+	  if (Stats[i].text)
+	    Xfree (Stats[i].text);
+	}
+      Xfree (Stats);
+      Stats = NULL;
+      NumStats = 0;
+    }
+}
+
+static void 
+Add_Stats (S_Type typ, char *name, char *fmt,...)
+{
+  char buf[1024];
+  va_list args;
+  va_start (args, fmt);
+  vsprintf (buf, fmt, args);
+  if (Stats)
+    Stats = Xrealloc (Stats, (++NumStats) * sizeof (*Stats));
+  else
+    Stats = Xmalloc ((++NumStats) * sizeof (*Stats));
+  Stats[NumStats - 1].typ = typ;
+  Stats[NumStats - 1].name = Xstrdup (name);
+  Stats[NumStats - 1].text = Xstrdup (buf);
+}
+
+static void 
+Display_Stats (FILE * f)
+{
+  static char *sep = "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
+  "-=-=-=-=-=-=-=-=-=-=-";
+  char *names[] =
+  {"Time:  ", "Memory:", "Sizes: ", "Disk:  ", "       "};
+  int i, last_typ = -1;
+  size_t len = 0;
+  if (NumStats == 0)
+    return;
+  fprintf (f, "%s\n", sep);
+  for (i = 0; i < NumStats; i++)
+    if (strlen (Stats[i].name) > len)
+      len = strlen (Stats[i].name);
+  for (i = 0; i < NumStats; i++)
+    {
+      int typ = 4;
+      if (Stats[i].typ != last_typ)
+	typ = last_typ = Stats[i].typ;
+      fprintf (f, "%s %-*s %s\n", names[typ], (int) len, Stats[i].name, Stats[i].text);
+    }
+  fprintf (f, "%s\n", sep);
+}
+
+/*****************************************************************************/
+
+
+static void 
+QueryTimeStats (ProgTime * Start, ProgTime * invf, ProgTime * text)
+{
+  if (!BooleanEnv (GetEnv ("briefstats"), 0))
+    {
+      Add_Stats (S_Time, "invf", ElapsedTime (Start, invf));
+      Add_Stats (S_Time, "text", ElapsedTime (invf, text));
+    }
+  Add_Stats (S_Time, "total", ElapsedTime (Start, text));
+}
+
+static void 
+StartUpTimeStats (InitQueryTimes * iqt)
+{
+  if (!BooleanEnv (GetEnv ("briefstats"), 0))
+    {
+      Add_Stats (S_Time, "dict [stem]", ElapsedTime (&iqt->Start,
+						     &iqt->StemDict));
+      Add_Stats (S_Time, "weights", ElapsedTime (&iqt->StemDict,
+						 &iqt->ApproxWeights));
+      Add_Stats (S_Time, "dict [text]", ElapsedTime (&iqt->ApproxWeights,
+						     &iqt->CompDict));
+      Add_Stats (S_Time, "Inverted", ElapsedTime (&iqt->CompDict,
+						  &iqt->Invf));
+      Add_Stats (S_Time, "Compressed", ElapsedTime (&iqt->Invf,
+						    &iqt->Text));
+    }
+  Add_Stats (S_Time, "total", ElapsedTime (&iqt->Start, &iqt->Text));
+}
+
+
+
+
+#ifdef USE_PROCESS_MEM
+static u_long 
+process_mem (void)
+{
+  prstatus_t pr;
+  static int fd = -1;
+  if (fd == -1)
+    {
+      char buf[128];
+      sprintf (buf, "/proc/%ld", (long) getpid ());
+      fd = open (buf, O_RDONLY);
+    }
+  if (fd == -1 || ioctl (fd, PIOCSTATUS, &pr) == -1)
+    return 0;
+  return pr.pr_brksize;
+}
+#endif
+
+
+
+
+static void 
+MemStats (query_data * qd)
+{
+  if (!BooleanEnv (GetEnv ("briefstats"), 0))
+    {
+#ifdef HAVE_GETRUSAGE
+      struct rusage rusage;
+      getrusage (RUSAGE_SELF, &rusage);
+
+      Add_Stats (S_Mem, "process mem", "%7.3f Mb",
+	    (double) (rusage.ru_maxrss * getpagesize () / 1024.0 / 1024.0));
+#endif
+#ifdef USE_PROCESS_MEM
+      Add_Stats (S_Mem, "process mem", "%7.3f Mb",
+		 (double) (process_mem () / 1024.0 / 1024.0));
+#endif
+      Add_Stats (S_Mem, "dict [stem]", "%7.1f kB",
+		 (double) qd->sd->MemForStemDict / 1024);
+      Add_Stats (S_Mem, "dict [text]", "%7.1f kB",
+		 (double) qd->cd->MemForCompDict / 1024);
+      if (qd->awd)
+	Add_Stats (S_Mem, "weights", "%7.1f kB",
+		   (double) qd->awd->MemForWeights / 1024);
+    }
+  if (qd->awd)
+    Add_Stats (S_Mem, "total [peak]", "%7.1f kB",
+	       (double) (qd->max_mem_in_use + qd->sd->MemForStemDict +
+		   qd->cd->MemForCompDict + qd->awd->MemForWeights) / 1024);
+  else
+    Add_Stats (S_Mem, "total [peak]", "%7.1f kB",
+	       (double) (qd->max_mem_in_use + qd->sd->MemForStemDict +
+			 qd->cd->MemForCompDict) / 1024);
+
+}
+
+
+
+static void 
+SizeStats (query_data * qd)
+{
+  Add_Stats (S_Size, "skips", "%7d", qd->hops_taken);
+  Add_Stats (S_Size, "pointers", "%7d", qd->num_of_ptrs);
+  Add_Stats (S_Size, "accumulators", "%7d", qd->num_of_accum);
+  Add_Stats (S_Size, "terms", "%7d", qd->num_of_terms);
+  Add_Stats (S_Size, "answers", "%7d", qd->num_of_ans);
+  Add_Stats (S_Size, "index lookups", "%7d", qd->text_idx_lookups);
+}
+
+static void 
+TotalSizeStats (query_data * qd)
+{
+  Add_Stats (S_Size, "skips", "%7d", qd->tot_hops_taken);
+  Add_Stats (S_Size, "pointers", "%7d", qd->tot_num_of_ptrs);
+  Add_Stats (S_Size, "accumulators", "%7d", qd->tot_num_of_accum);
+  Add_Stats (S_Size, "terms", "%7d", qd->tot_num_of_terms);
+  Add_Stats (S_Size, "answers", "%7d", qd->tot_num_of_ans);
+  Add_Stats (S_Size, "index lookups", "%7d", qd->tot_text_idx_lookups);
+}
+
+
+static void 
+StatFile (File * F)
+{
+  static unsigned long NumBytes = 0, NumSeeks = 0, NumReads = 0;
+  if (F) 
+    {
+      if ((int) F != -1)
+	{
+	  if (!BooleanEnv (GetEnv ("briefstats"), 0))
+	    Add_Stats (S_File, F->name, "%7.1f kB (%3d seeks, %7d reads)",
+		       (double) F->Current.NumBytes / 1024, F->Current.NumSeeks,
+		       F->Current.NumReads);
+	  NumBytes += F->Current.NumBytes;
+	  NumSeeks += F->Current.NumSeeks;
+	  NumReads += F->Current.NumReads;
+	}
+      else
+	{
+	  Add_Stats (S_File, "total", "%7.1f kB (%3d seeks, %7d reads)",
+		     (double) NumBytes / 1024, NumSeeks, NumReads);
+	  NumSeeks = NumReads = NumBytes = 0;
+	}
+    }
+}
+
+
+static void 
+File_Stats (query_data * qd)
+{
+  StatFile (qd->File_comp_dict);
+  StatFile (qd->File_fast_comp_dict);
+  StatFile (qd->File_text_idx_wgt);
+  StatFile (qd->File_text);
+  StatFile (qd->File_stem);
+
+  /* [RPAP - Jan 97: Stem Index Change] */
+  if (qd->sd->sdh.indexed)
+    {
+      StatFile (qd->File_stem1);
+      StatFile (qd->File_stem2);
+      StatFile (qd->File_stem3);
+    }
+
+  StatFile (qd->File_invf);
+  StatFile (qd->File_weight_approx);
+  StatFile (qd->File_text_idx);
+  StatFile ((File *) (-1));
+}
+
+
+char *
+get_query (query_data * qd)
+{
+  char *line, *LinePtr;
+  WritePrompt ();
+  do
+    {
+      do
+	{
+	  line = GetMultiLine ();
+	  if (line == NULL)
+	    {
+	      if (stdin == InFile)
+		return (NULL);	/* EOF */
+	      if (InPipe)
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+		_pclose (InFile);
+#else
+		pclose (InFile);
+#endif
+	      else
+		fclose (InFile);
+	      InPipe = 0;
+	      InFile = stdin;
+	    }
+	}
+      while (line == NULL);
+      LinePtr = ProcessCommands (line, qd);
+      if (CommandsErrorStr)
+	fprintf (stderr, "%s\n", CommandsErrorStr);
+    }
+  while (*LinePtr == '\0' && !Quitting);
+  return (LinePtr);
+}
+
+
+/* This is executed when a SIGPIPE is detected
+   i.e. If some one quits out of the PAGER, this is executed */
+#ifdef HAVE_SIGCONTEXT
+static RETSIGTYPE 
+SIGPIPE_handler (int sig, int code,
+		 struct sigcontext *scp, char *addr)
+#else
+static RETSIGTYPE 
+SIGPIPE_handler (int sig)
+#endif
+{
+  /* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+  signal (sig, SIG_IGN);
+#else
+  signal (SIGPIPE, SIG_IGN);
+#endif
+  PagerRunning = 0;
+}
+
+/* This is executed when a SIGINT (i.e. CTRL-C) is detected */
+#ifdef  HAVE_SIGCONTEXT
+static RETSIGTYPE 
+SIGINT_handler (int sig, int code,
+		struct sigcontext *scp, char *addr)
+#else
+static RETSIGTYPE 
+SIGINT_handler (int sig)
+#endif
+{
+  Ctrl_C = 1;
+}
+
+
+
+static char *post_proc = NULL;
+
+
+
+void 
+GetPostProc (char *line)
+{
+  char *start, *finish;
+  if (post_proc)
+    {
+      Xfree (post_proc);
+      post_proc = NULL;
+    }
+  start = strchr (line, '\"');
+  finish = strrchr (line, '\"');
+  if (start != finish)
+    {
+      /* found a pattern */
+      *finish = '\0';
+      post_proc = Xstrdup (start + 1);
+      strcpy (start, finish + 1);
+      if (BooleanEnv (GetEnv ("verbatim"), 1) == 0)
+	{
+	  char *s;
+	  s = re_comp (post_proc);
+	  if (!s)
+	    {
+	      Xfree (post_proc);
+	      post_proc = NULL;
+	    }
+	}
+    }
+  else if (start != NULL)
+    {
+      /* found a single speech mark. Delete It. */
+      strcpy (start, start + 1);
+    }
+}
+
+int 
+PostProc (char *UDoc, int verbatim)
+{
+  if (!post_proc)
+    return 1;
+
+  if (verbatim) {
+    return (strstr (UDoc, post_proc) != NULL);
+  }
+  return re_exec ((char *) UDoc);
+}
+
+
+
+static DocEntry *
+in_chain (int para, int ip, DocEntry * dc)
+{
+  while (dc)
+    {
+      if (dc->DocNum - ip == para)
+	return dc;
+      dc = dc->Next;
+    }
+  return NULL;
+}
+
+/* num should be greater than or equal to 1 */
+int 
+RawDocOutput (query_data * qd, u_long num, FILE * Output)
+{
+  static u_long last_pos = 0;
+  static u_char *c_buffer = 0;
+  static int buf_len = -1;
+  static u_char *uc_buffer = 0;
+  u_long pos, len;
+  int ULen;
+
+  FetchDocStart (qd, num, &pos, &len);
+
+  if ((int) len > buf_len)
+    {
+      if (c_buffer)
+	{
+	  Xfree (c_buffer);
+	  Xfree (uc_buffer);
+	}
+      if (!(c_buffer = Xmalloc (len)))
+	return -1;
+      if (!(uc_buffer = Xmalloc ((int) (qd->td->cth.ratio * 1.01 *
+					len) + 100)))
+	return -1;
+      buf_len = len;
+    }
+  if (last_pos != pos)
+    Fseek (qd->td->TextFile, pos, 0);
+  Fread (c_buffer, 1, len, qd->td->TextFile);
+  last_pos = pos + len;
+  DecodeText (qd->cd, c_buffer, len, uc_buffer, &ULen);
+  fwrite (uc_buffer, ULen, sizeof (u_char), Output);
+  return 0;
+}
+
+
+void 
+StringOut (FILE * Output, char *string,
+	   int intvalid, unsigned long intval,
+	   int floatvalid, double floatval)
+{
+  char *s;
+  for (s = string; *s; s++)
+    if (*s == '%' &&
+	(*(s + 1) == 'n' || *(s + 1) == 'w' || *(s + 1) == '%'))
+      {
+	s++;
+	switch (*s)
+	  {
+	  case 'n':
+	    if (intvalid)
+	      fprintf (Output, "%lu", intval);
+	    else
+	      fprintf (Output, "%%n");
+	    break;
+	  case 'w':
+	    if (floatvalid)
+	      fprintf (Output, "%f", floatval);
+	    else
+	      fprintf (Output, "%%w");
+	    break;
+	  case '%':
+	    fputc ('%', Output);
+	  }
+      }
+    else
+      fputc (*s, Output);
+}
+
+
+void 
+HeaderOut (FILE * Output, u_char * UDoc, unsigned long ULen, int heads_length)
+{
+  int i, space = 1, num = 0;
+  for (i = 0; i < ULen && num < heads_length; i++)
+    {
+      char c = UDoc[i];
+      if (c == '\02')
+	break;
+
+      if (isspace (c) || c == '\01' || c == '\03')
+	{
+	  if (!space)
+	    {
+	      fputc (' ', Output);
+	      num++;
+	    }
+	  space = 1;
+	}
+      else
+	{
+	  space = 0;
+	  fputc (c, Output);
+	  num++;
+	}
+    }
+}
+
+/* [RPAP - Feb 97: NZDL Additions] */
+#if defined(PARADOCNUM) || defined(NZDL)
+void PrintDocNum(FILE *output, char query_type,
+		 int docnum, int indexnum, float weight)
+{
+  if (query_type == 'R' || query_type == 'A')
+    fprintf(output, "%7d.%-7d  %6.4f\n", docnum, indexnum, weight);
+  else
+    fprintf(output, "%7d.%-7d\n", docnum, indexnum);
+}
+#endif
+
+static int 
+ProcessDocs (query_data * qd, int num, int verbatim,
+	     char OutputType, FILE * Output)
+{
+  int max_buf = 0;
+  int DocCount = 0;
+  char *doc_sepstr = NULL;
+  char *para_sepstr = NULL;
+  char *para_start = NULL;
+  int heads_length = atoi (GetDefEnv ("heads_length", "50"));
+  char QueryType = get_query_type ();
+  int need_text = (OutputType == OUTPUT_TEXT || OutputType == OUTPUT_HILITE ||
+		   OutputType == OUTPUT_HEADERS || OutputType == OUTPUT_SILENT || 
+		   post_proc); /* [RJM June 1997 -- fixing post retrieval scan] */
+
+  if (OutputType == OUTPUT_TEXT || OutputType == OUTPUT_HILITE)
+    {
+      if (QueryType == QUERY_APPROX || QueryType == QUERY_RANKED)
+	{
+	  doc_sepstr = de_escape_string (
+				    Xstrdup (GetDefEnv ("ranked_doc_sepstr",
+			   "---------------------------------- %n %w\\n")));
+	}
+      else
+	{
+	  doc_sepstr = de_escape_string (
+					  Xstrdup (GetDefEnv ("doc_sepstr",
+			      "---------------------------------- %n\\n")));
+	}
+      para_sepstr = de_escape_string (
+				       Xstrdup (GetDefEnv ("para_sepstr",
+				  "\\n######## PARAGRAPH %n ########\\n")));
+
+      para_start = de_escape_string (
+				      Xstrdup (GetDefEnv ("para_start",
+					    "***** Weight = %w *****\\n")));
+    }
+
+  if (need_text)
+    {
+      max_buf = atoi (GetDefEnv ("buffer", "1048576"));
+    }
+
+  do
+    {
+      u_char *UDoc = NULL;
+      unsigned long ULen;
+
+      if (need_text)
+	{
+	  /* load the compressed text */
+	  if (LoadCompressedText (qd, max_buf))
+	    {
+	      Message ("Unable to load compressed text.");
+	      FatalError (1, "This is probably due to lack of memory.");
+	    }
+
+	  /* uncompress the loaded text */
+	  UDoc = GetDocText (qd, &ULen);
+	  if (UDoc == NULL)
+	    FatalError (1, "UDoc is unexpectedly NULL");
+	}
+
+      if (!UDoc || PostProc ((char *) UDoc, verbatim))
+	{
+	  switch (OutputType)
+	    {
+	    case OUTPUT_COUNT:
+	    case OUTPUT_SILENT:
+	      break;
+	    case OUTPUT_DOCNUMS:	/* This prints out the docnums string */
+	      if (PagerRunning)
+		{
+
+/* [RPAP - Feb 97: NZDL Additions] */
+#if defined(PARADOCNUM) || defined(NZDL)
+		  int doc_num = GetDocNum(qd);
+
+		  if (qd->paragraph)
+		    {
+		      if (qd->id->ifh.InvfLevel == 3 &&
+			  (QueryType == 'R' || QueryType == 'A'))
+			{
+			  /* Print weights for each paragraph in document */
+			  
+
+			  int true_doc_num = GetDocNumFromParaNum(qd, doc_num);
+
+			  /* Get number of paragraphs in this document */
+
+			  int num_paragraphs = 
+			    qd->paragraph[true_doc_num]-qd->paragraph[true_doc_num-1];
+
+			  int init_para = FetchInitialParagraph(qd->td,
+								doc_num);
+			  DocEntry *de, *doc_chain = GetDocChain(qd);
+			  int i;
+
+			  for (i = 0; i < num_paragraphs; i++)
+			    {
+			      if ((de = in_chain(i, init_para, doc_chain)))
+				PrintDocNum(Output, QueryType,
+					    true_doc_num, init_para+i,
+					    de->Weight);
+			    }
+			}
+		      else
+			PrintDocNum(Output, QueryType,
+				    GetDocNumFromParaNum(qd, GetDocNum(qd)),
+				    GetDocNum(qd),
+				    GetDocWeight(qd));
+		    }
+		  else
+		    {
+		      PrintDocNum(Output, QueryType,
+				  doc_num, doc_num, GetDocWeight(qd));
+		    }
+#else
+		fprintf (Output, "%7d   %6.4f   %7lu\n", GetDocNum (qd),
+			 GetDocWeight (qd), GetDocCompLength (qd));
+#endif
+		}
+	      break;
+	    case OUTPUT_HEADERS:	/* This prints out the headers of the documents */
+	      if (PagerRunning)
+		fprintf (Output, "%d ", GetDocNum (qd));
+	      HeaderOut (Output, UDoc, ULen, heads_length);
+	      if (PagerRunning)
+		fputc ('\n', Output);
+	      break;
+#if TREC_MODE
+	    case OUTPUT_EXTRAS:	/* This prints out the docnums string */
+	      if (PagerRunning && trec_ids)
+		{
+		  long DN, PN = GetDocNum (qd) - 1;
+		  if (trec_paras)
+		    DN = trec_paras[PN];
+		  else
+		    DN = PN;
+		  fprintf (Output, "%-14.14s  %8ld  %10.5f\n",
+			   &trec_ids[DN * 14], PN + 1, GetDocWeight (qd));
+		}
+	      break;
+#endif
+	    case OUTPUT_TEXT:
+	    case OUTPUT_HILITE:
+	      {
+		int j, para = -1, curr_para = 0;
+		int init_para = -1;
+		DocEntry *de, *doc_chain = NULL;
+		register char ch = ' ';
+		register char lch = '\n';
+
+/* [RPAP - Feb 97: NZDL Additions] */
+#if defined(PARADOCNUM) || defined(NZDL)
+		if (qd->id->ifh.InvfLevel == 3)
+		  {
+		    init_para = FetchInitialParagraph(qd->td, GetDocNum(qd));
+		    
+		    StringOut(Output, para_sepstr, 
+			      1, init_para+curr_para,
+			      0, 0);
+
+		  }
+		else
+		  StringOut(Output, doc_sepstr, 
+			    1, GetDocNum(qd),
+			    QueryType == 'A' || QueryType == 'R',
+			    GetDocWeight(qd));
+
+#else
+		int p_on = 0;
+
+		if (PagerRunning)
+		  {
+		    StringOut (Output, doc_sepstr,
+			       1, GetDocNum (qd),
+			       QueryType == 'A' || QueryType == 'R',
+			       GetDocWeight (qd));
+		  }
+		if (qd->id->ifh.InvfLevel == 3)
+		  {
+		    init_para = FetchInitialParagraph (qd->td, GetDocNum (qd));
+		    doc_chain = GetDocChain (qd);
+		    para = GetDocNum (qd) - init_para;
+
+		    StringOut (Output, para_sepstr,
+			       1, curr_para + 1,
+			       0, 0);
+
+		    if ((de = in_chain (0, init_para, doc_chain)))
+		      StringOut (Output, para_start,
+				 0, 0,
+				 1, de->Weight);
+
+		    if (doc_chain->DocNum - init_para == 0)
+		      p_on = 1;
+		  }
+#endif
+		for (j = 0; j < ULen; j++)
+		  {
+		    ch = UDoc[j];
+		    switch (ch)
+		      {
+		      case '\02':
+			break;
+		      case '\01':
+			ch = '\n';
+		      case '\03':
+/* [RPAP - Feb 97: NZDL Additions] */
+#if defined(PARADOCNUM) || defined(NZDL)
+			/* print paragraph numbers only if this is
+			   a level 3 index */
+			if (qd->id->ifh.InvfLevel == 3)
+			  {
+			    curr_para++;
+			    StringOut(Output, para_sepstr, 
+				      1, init_para+curr_para,
+				      0, 0);
+			  }
+#else
+			p_on = 0;
+			curr_para++;
+			StringOut (Output, para_sepstr,
+				   1, curr_para + 1,
+				   0, 0);
+			lch = *(strchr (para_sepstr, '\0') - 1);
+			if ((de = in_chain (curr_para, init_para, doc_chain)))
+			  StringOut (Output, para_start,
+				     0, 0,
+				     1, de->Weight);
+			if (doc_chain &&
+			    doc_chain->DocNum - init_para == curr_para)
+			  p_on = 1;
+#endif
+			break;
+		      default:
+			{
+			  if (PagerRunning)
+			    {
+			      fputc (ch, Output);
+/* [RPAP - Feb 97: NZDL Additions] */
+#if !defined(PARADOCNUM) && !defined(NZDL)
+			      if (p_on && isprint (ch))
+				{
+				  fputc ('\b', Output);
+				  fputc ('_', Output);
+				}
+#endif
+			    }
+
+			  lch = ch;
+			}
+		      }
+		  }
+		if (PagerRunning && lch != '\n')
+		  fputc ('\n', Output);
+/* [RPAP - Feb 97: NZDL Additions] */
+#if !defined(PARADOCNUM) && !defined(NZDL)
+		p_on = 0;
+#endif
+	      }
+	    }
+	  if (PagerRunning)
+	    fflush (Output);
+
+	  DocCount++; /* moved within if statement [RJM June 1997 -- fixing post retrieval scan] */
+	}
+    }
+  while (NextDoc (qd) && PagerRunning && (!Ctrl_C));
+
+  if (need_text)
+    {
+      FreeTextBuffer (qd);
+    }
+
+  if (OutputType == OUTPUT_TEXT || OutputType == OUTPUT_HILITE)
+    {
+      Xfree (doc_sepstr);
+      Xfree (para_sepstr);
+      Xfree (para_start);
+    }
+
+  return (DocCount);
+}
+
+
+void 
+output_terminator (FILE * out)
+{
+  char *terminator = Xstrdup (GetDefEnv ("terminator", ""));
+  de_escape_string (terminator);
+  fputs (terminator, out);
+  Xfree (terminator);
+}
+
+
+
+
+/* MoreDocs () */
+/* Displays all documents in list  DocList. */
+/* Documents are fetched, then decompressed and displayed according to the */
+/* format implied in  FormString(). */
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+# define HILITE_PAGER "mg_hilite_words.exe"
+#else
+# define HILITE_PAGER "mg_hilite_words"
+#endif
+
+#define MAX_HILITE_PAGER_STR 80	/* for command & its options */
+
+static void 
+MoreDocs (query_data * qd, char *Query, char OutputType)
+{
+  static char terms_str[MAXTERMSTRLEN + 1];
+  int DocCount = 0;		/* number of actual matches */
+  FILE *Output = NULL;
+  int using_pipe = 0;
+  char *pager = NULL;
+
+  Ctrl_C = 0;
+
+  qd->num_of_ans = qd->DL->num;
+
+  /* [RPAP - Feb 97: WIN32 Port] */
+#ifndef __WIN32__
+  signal (SIGPIPE, SIGPIPE_handler);
+#endif
+  signal (SIGINT, SIGINT_handler);
+
+  PagerRunning = 1;
+  if (isatty (fileno (OutFile)) && GetEnv ("pager") &&
+      OutputType != OUTPUT_HILITE &&
+      OutputType != OUTPUT_SILENT && OutputType != OUTPUT_COUNT)
+    {
+      pager = GetEnv ("pager");
+    }
+  else if (isatty (fileno (OutFile)) && OutputType == OUTPUT_HILITE)
+    {
+      /* concat the pager and its word argument strings */
+      ConvertTermsToString (qd->TL, terms_str);
+      pager = Xmalloc (MAX_HILITE_PAGER_STR + strlen (terms_str) + 1);
+      if (!pager)
+	{
+	  fprintf (stderr, "Unable to allocate memory for highlighting\n");
+	  return;
+	}
+      sprintf (pager, "%s --style=%s --pager=%s --stem_method=%ld --stemmer=%ld %s",
+	       HILITE_PAGER,
+	       GetEnv ("hilite_style"),
+	       GetEnv ("pager"),
+	       qd->sd->sdh.stem_method,
+	       qd->sd->sdh.stemmer_num,
+	       terms_str);
+
+    }
+  else
+    {
+      Output = OutFile;
+    }
+
+/* [RPAP - Feb 97: NZDL Additions] */
+#if defined(OUTPUTSTEMMEDWORDS) || defined(NZDL)
+  if (!isatty(fileno(OutFile)) && get_query_type() != QUERY_DOCNUMS)
+    {
+      ConvertTermsToString(qd->TL, terms_str);
+      fprintf(Output, "%s\n", terms_str);
+    }
+#endif
+  if (pager)
+    {
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+      Output = _popen (pager, "w");
+#else
+      Output = popen (pager, "w");
+#endif
+      using_pipe = (Output != NULL);
+      if (!using_pipe)
+	{
+	  fprintf (stderr, "Unable to run \"%s\"\n", pager);
+	  return;
+	}
+    }
+
+
+  if (qd->DL->num > 0)
+    {
+      if (OutputType == OUTPUT_COUNT && !post_proc)
+	DocCount = qd->DL->num;
+      else {
+	DocCount = ProcessDocs (qd, qd->DL->num,
+				BooleanEnv (GetEnv ("verbatim"), 1),
+				OutputType, Output);
+      }
+    }
+
+  if (PagerRunning)
+    {
+      output_terminator (Output);
+      fflush (Output);
+    }
+
+  if (OutputType == OUTPUT_HILITE && pager)
+    free (pager);		/* as needed to malloc to create the pager string */
+
+  if (using_pipe)
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+    _pclose (Output);
+#else
+    pclose (Output);
+#endif
+
+  if (qd->DL->num == 0)
+    fprintf (stderr, "No entries correspond to that query.\n");
+  else
+    {
+      if (OutputType == OUTPUT_COUNT)
+	fprintf (stderr, "%d documents match.\n", DocCount);
+      else
+	fprintf (stderr, "%d documents retrieved.\n", DocCount);
+    }
+
+  signal (SIGINT, SIG_DFL);
+}
+
+
+void 
+start_up_stats (query_data * qd, InitQueryTimes iqt)
+{
+  Clear_Stats ();
+  if (BooleanEnv (GetEnv ("timestats"), 0) ||
+      BooleanEnv (GetEnv ("briefstats"), 0))
+    StartUpTimeStats (&iqt);
+
+  if (BooleanEnv (GetEnv ("diskstats"), 0) ||
+      BooleanEnv (GetEnv ("briefstats"), 0))
+    File_Stats (qd);
+
+  if (BooleanEnv (GetEnv ("memstats"), 0) ||
+      BooleanEnv (GetEnv ("briefstats"), 0))
+    MemStats (qd);
+
+}
+
+
+void 
+shut_down_stats (query_data * qd, ProgTime * start,
+		 ProgTime * invf, ProgTime * text)
+{
+  Clear_Stats ();
+  if (BooleanEnv (GetEnv ("timestats"), 0) ||
+      BooleanEnv (GetEnv ("briefstats"), 0))
+    QueryTimeStats (start, invf, text);
+
+  if (BooleanEnv (GetEnv ("diskstats"), 0) ||
+      BooleanEnv (GetEnv ("briefstats"), 0))
+    {
+      TransFileStats (qd);
+      File_Stats (qd);
+    }
+
+  if (BooleanEnv (GetEnv ("sizestats"), 0))
+    TotalSizeStats (qd);
+}
+
+
+
+char *wordfreqword2str (u_char * s)
+{
+  static char buf[1024];
+  int i, len = (int) *s++;
+
+  for (i = 0; i < len; i++)
+    {
+      buf[i] = (char)s[i];
+    }
+  buf[len] = '\0';
+
+  return buf;
+}
+
+
+/* [RPAP - Feb 97: Term Frequency] */
+/*********************************
+ * PrintQueryTermFreq
+ *
+ * Prints the query terms and their respective frequencies within the collection
+ *********************************/
+void
+PrintQueryTermFreqs (QueryTermList *qtl)
+{
+  int i;
+
+  /* Print the number of terms */
+  fprintf (OutFile, "%d\n", qtl->num);
+
+  /* Print the terms and their respective frequency within the collection */
+  for (i = 0; i < qtl->num; i++)
+    if (qtl->QTE[i].stem_method == -1)
+      /* Using default stem method - don't print stem method beside term */
+      fprintf (OutFile, "%s %d\n", wordfreqword2str (qtl->QTE[i].Term), qtl->QTE[i].Count);
+    else
+      /* Term was forced with a stem, print stem method with term */
+      fprintf (OutFile, "%s#%d %d\n", wordfreqword2str (qtl->QTE[i].Term), qtl->QTE[i].stem_method, qtl->QTE[i].Count);
+}
+
+
+void 
+query (void)
+{
+  ProgTime TotalStartTime, TotalInvfTime, TotalTextTime;
+  InitQueryTimes iqt;
+  query_data *qd;
+
+  TotalStartTime.RealTime = TotalStartTime.CPUTime = 0;
+  TotalInvfTime.RealTime = TotalInvfTime.CPUTime = 0;
+  TotalTextTime.RealTime = TotalTextTime.CPUTime = 0;
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+  qd = InitQuerySystem (GetDefEnv ("mgdir", ".\\"),
+                        GetDefEnv ("mgname", ""),
+			GetDefEnv ("textname", NULL), /* [RJM 06/97: text filename] */
+			&iqt);
+#else
+  qd = InitQuerySystem (GetDefEnv ("mgdir", "./"),
+                        GetDefEnv ("mgname", ""),
+			GetDefEnv ("textname", NULL), /* [RJM 06/97: text filename] */
+                        &iqt);
+#endif
+
+  if (!qd)
+    FatalError (1, mg_errorstrs[mg_errno], mg_error_data);
+  start_up_stats (qd, iqt);
+
+
+  while (1)
+    {
+      ProgTime StartTime, InvfTime, TextTime;
+      char QueryType;
+      char OutputType;
+      char *line;
+      ResetFileStats (qd);
+      qd->max_mem_in_use = qd->mem_in_use = 0;
+
+      qd->tot_hops_taken += qd->hops_taken;
+      qd->tot_num_of_ptrs += qd->num_of_ptrs;
+      qd->tot_num_of_accum += qd->num_of_accum;
+      qd->tot_num_of_terms += qd->num_of_terms;
+      qd->tot_num_of_ans += qd->num_of_ans;
+      qd->tot_text_idx_lookups += qd->text_idx_lookups;
+      qd->hops_taken = qd->num_of_ptrs = 0;
+      qd->num_of_accum = qd->num_of_ans = qd->num_of_terms = 0;
+      qd->text_idx_lookups = 0;
+
+      Display_Stats (stderr);
+      Clear_Stats ();
+      line = get_query (qd);
+      if (!line || Quitting)
+	break;
+
+      GetPostProc (line);
+
+      GetTime (&StartTime);
+
+      FreeQueryDocs (qd);
+
+      QueryType = get_query_type ();
+      OutputType = get_output_type ();
+      /* No point in hiliting words on a docnum query */
+      if (OutputType == OUTPUT_HILITE && QueryType == QUERY_DOCNUMS)
+	OutputType = OUTPUT_TEXT;
+
+      switch (QueryType)
+	{
+	case QUERY_BOOLEAN:
+	  {
+	    char *maxdocs;
+	    BooleanQueryInfo bqi;
+	    maxdocs = GetDefEnv ("maxdocs", "all");
+	    bqi.MaxDocsToRetrieve = strcmp (maxdocs, "all") ? atoi (maxdocs) : -1;
+	    /* [RPAP - Jan 97: Stem Index Change] */
+	    if (qd->sd->sdh.indexed)
+	      BooleanQuery (qd, line, &bqi, (BooleanEnv (GetEnv ("casefold"), 0) |
+					     (BooleanEnv (GetEnv ("stem"), 0) << 1)));
+	    else
+	      BooleanQuery (qd, line, &bqi, qd->sd->sdh.stem_method);
+
+	    break;
+	  }
+	case QUERY_APPROX:
+	case QUERY_RANKED:
+	  {
+	    char *maxdocs;
+	    char *maxterms;
+	    char *maxaccum;
+	    RankedQueryInfo rqi;
+	    maxdocs = GetDefEnv ("maxdocs", "all");
+	    maxterms = GetDefEnv ("max_terms", "all");
+	    maxaccum = GetDefEnv ("max_accumulators", "all");
+	    rqi.Sort = BooleanEnv (GetEnv ("sorted_terms"), 0);
+	    rqi.QueryFreqs = BooleanEnv (GetEnv ("qfreq"), 1);
+	    rqi.Exact = QueryType == QUERY_RANKED;
+	    rqi.MaxDocsToRetrieve = strcmp (maxdocs, "all") ? atoi (maxdocs) : -1;
+	    rqi.MaxTerms = strcmp (maxterms, "all") ? atoi (maxterms) : -1;
+	    rqi.MaxParasToRetrieve = rqi.MaxDocsToRetrieve;
+	    if (qd->id->ifh.InvfLevel == 3 && GetEnv ("maxparas"))
+	      rqi.MaxParasToRetrieve = atoi (GetEnv ("maxparas"));
+	    rqi.AccumMethod = toupper (*GetDefEnv ("accumulator_method", "A"));
+	    rqi.MaxAccums = strcmp (maxaccum, "all") ? atoi (maxaccum) : -1;
+	    rqi.HashTblSize = IntEnv (GetEnv ("hash_tbl_size"), 1000);
+	    rqi.StopAtMaxAccum = BooleanEnv (GetEnv ("stop_at_max_accum"), 0);
+	    rqi.skip_dump = GetEnv ("skip_dump");
+	    RankedQuery (qd, line, &rqi);
+	    break;
+	  }
+	case QUERY_DOCNUMS:
+	  {
+	    DocnumsQuery (qd, line);
+	    break;
+	  }
+	}
+
+      GetTime (&InvfTime);
+
+      /* [RPAP - Feb 97: Term Frequency] */
+      if (qd->QTL && BooleanEnv (GetEnv ("term_freq"), 0))
+	PrintQueryTermFreqs (qd->QTL);
+
+      if (qd->DL)
+	MoreDocs (qd, line, OutputType);
+
+      GetTime (&TextTime);
+
+      if (BooleanEnv (GetEnv ("timestats"), 0) ||
+	  BooleanEnv (GetEnv ("briefstats"), 0))
+	QueryTimeStats (&StartTime, &InvfTime, &TextTime);
+
+      if (BooleanEnv (GetEnv ("diskstats"), 0) ||
+	  BooleanEnv (GetEnv ("briefstats"), 0))
+	File_Stats (qd);
+
+      if (BooleanEnv (GetEnv ("memstats"), 0) ||
+	  BooleanEnv (GetEnv ("briefstats"), 0))
+	MemStats (qd);
+
+      if (BooleanEnv (GetEnv ("sizestats"), 0))
+	SizeStats (qd);
+
+      TotalInvfTime.RealTime += InvfTime.RealTime - StartTime.RealTime;
+      TotalInvfTime.CPUTime += InvfTime.CPUTime - StartTime.CPUTime;
+      TotalTextTime.RealTime += TextTime.RealTime - StartTime.RealTime;
+      TotalTextTime.CPUTime += TextTime.CPUTime - StartTime.CPUTime;
+    }
+
+  if (isatty (fileno (InFile)) && !Quitting)
+    fprintf (stderr, "\n");
+
+  shut_down_stats (qd, &TotalStartTime, &TotalInvfTime, &TotalTextTime);
+
+  Display_Stats (stderr);
+
+}
+
+
+void 
+search_for_collection (char *name)
+{
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+  char *dir = GetDefEnv ("mgdir", ".\\");
+#else
+  char *dir = GetDefEnv ("mgdir", "./");
+#endif
+  char buffer[512];
+  struct stat stat_buf;
+  if (strrchr (dir, '/') && *(strrchr (dir, '/') + 1) != '\0')
+    {
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+      sprintf (buffer, "%s", dir);
+#else
+      sprintf (buffer, "%s/", dir);
+#endif
+      SetEnv ("mgdir", buffer, NULL);
+      dir = GetEnv ("mgdir");
+    }
+
+  sprintf (buffer, "%s.text", name);
+  if (stat (buffer, &stat_buf) != -1)
+    {
+      if ((stat_buf.st_mode & S_IFREG) != 0)
+	{
+	  /* The name is a directory */
+	  SetEnv ("mgname", name, NULL);
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+          SetEnv ("mgdir", ".\\", NULL);
+#else
+	  SetEnv ("mgdir", "./", NULL);
+#endif
+	  return;
+	}
+    }
+
+  sprintf (buffer, "%s%s", dir, name);
+  if (stat (buffer, &stat_buf) != -1)
+    {
+      if ((stat_buf.st_mode & S_IFDIR) != 0)
+	{
+	  /* The name is a directory */
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+          sprintf (buffer, "%s%s", name, name);
+#else
+	  sprintf (buffer, "%s/%s", name, name);
+#endif
+	  SetEnv ("mgname", buffer, NULL);
+	  return;
+	}
+    }
+
+  /* Look in the current directory last */
+  if (stat (name, &stat_buf) != -1)
+    {
+      if ((stat_buf.st_mode & S_IFDIR) != 0)
+	{
+	  /* The name is a directory */
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+          sprintf (buffer, "%s%s", name, name);
+          SetEnv ("mgdir", ".\\", NULL);
+#else
+	  sprintf (buffer, "%s/%s", name, name);
+          SetEnv ("mgdir", "./", NULL);
+#endif
+	  SetEnv ("mgname", buffer, NULL);
+	  return;
+	}
+    }
+
+  SetEnv ("mgname", name, NULL);
+}
+
+/* main () */
+/* Initialises global variables based on command line switches, and opens */
+/* files.  Then calls  query ()  to perform the querying. */
+int main (int argc, char **argv)
+{
+  ProgTime StartTime;
+  int decomp = 0;
+  int ch;
+
+  msg_prefix = argv[0];
+  GetTime (&StartTime);
+
+  /* Initialise the environment with default values */
+
+  InitEnv ();
+
+  read_mgrc_file ();
+
+  OutFile = stdout;
+  InFile = stdin;
+
+  opterr = 0;
+  /* [RJM 06/97: text filename] */
+  while ((ch = getopt (argc, argv, "Df:d:t:h")) != -1) {
+    switch (ch) {
+      case 'f':
+	SetEnv ("mgname", optarg, NULL);
+	break;
+      case 'd':
+	SetEnv ("mgdir", optarg, NULL);
+	break;
+      case 't': /* [RJM 06/97: text filename] */
+	SetEnv ("textname", optarg, NULL);
+	break;
+      case 'D':
+	decomp = 1;
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-D] [-f base name of collection] "
+		 "[-t base name of files for text] " /* [RJM 06/97: text filename] */
+		 "[-d data directory] [collection]\n", argv[0]);
+	exit (1);
+    }      
+  }
+
+  PushEnv ();
+
+  if (decomp == 0)
+    {
+
+      Init_ReadLine ();
+
+      /* write a first prompt, let the user start thinking */
+      if (!BooleanEnv (GetEnv ("expert"), 0) && isatty (fileno (InFile)))
+	{
+	  fprintf (stderr, "\n\n\t     FULL TEXT RETRIEVAL QUERY PROGRAM\n");
+	  fprintf (stderr, "%24s%s\n\n", "", *"21 Mar 1994" == '%' ? __DATE__ : "21 Mar 1994");
+	  fprintf (stderr, "\n");
+	  fprintf (stderr, "  mgquery version " VERSION ", Copyright (C) 1994 Neil Sharman\n");
+	  fprintf (stderr, "  mgquery comes with ABSOLUTELY NO WARRANTY; for details type `.warranty'\n");
+	  fprintf (stderr, "  This is free software, and you are welcome to redistribute it\n");
+	  fprintf (stderr, "  under certain conditions; type `.conditions' for details.\n");
+	  fprintf (stderr, "\n");
+	}
+    }
+  if (optind < argc)
+    search_for_collection (argv[optind]);
+
+  if (decomp == 0)
+    {
+      query ();
+    }
+  else
+    {
+      int i;
+      InitQueryTimes iqt;
+      query_data *qd;
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+      qd = InitQuerySystem (GetDefEnv ("mgdir", ".\\"),
+                            GetDefEnv ("mgname", ""),
+                            GetDefEnv ("textname", NULL), /* [RJM 06/97: text filename] */
+                            &iqt);
+#else
+      qd = InitQuerySystem (GetDefEnv ("mgdir", "./"),
+			    GetDefEnv ("mgname", ""),
+                            GetDefEnv ("textname", NULL), /* [RJM 06/97: text filename] */
+			    &iqt);
+#endif
+      if (!qd)
+	FatalError (1, mg_errorstrs[mg_errno], mg_error_data);
+
+
+      start_up_stats (qd, iqt);
+
+      Display_Stats (stderr);
+      for (i = 0; i < qd->td->cth.num_of_docs; i++)
+	{
+	  RawDocOutput (qd, i + 1, stdout);
+	  putc ('\2', stdout);
+	}
+      Message ("%s", ElapsedTime (&StartTime, NULL));
+
+      FinishQuerySystem (qd);
+    }
+
+  UninitEnv ();
+  return 0;
+}
Index: /indexers/branches/3.03a/mg/src/text/mgstat.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mgstat.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mgstat.1	(revision 14757)
@@ -0,0 +1,131 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgstat 1 \*(Dt CITRI
+.SH NAME
+mgstat \- print out statistics about a document collection
+.SH SYNOPSIS
+.B mgstat
+[
+.B \-h
+]
+[
+.B \-E
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mgstat
+prints out various statistics about an existing
+.BR mg (1)
+document collection.  Depending on the size of the collection, sizes
+will be printed in either kilobytes or megabytes.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stdout .
+.TP
+.B \-E
+This option forces sizes to be printed in bytes rather than kilobytes
+or megabytes.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.text
+Compressed documents.
+.TP
+.B *.invf
+Inverted file.
+.TP
+.B *.text.idx.wgt
+Interleaved index into the compressed documents and document weights.
+.TP
+.B *.weight.approx
+Approximate document weights.
+.TP
+.B *.invf.dict.blocked
+Compressed stemmed dictionary and index into the inverted file merged
+into an inverted file.
+.TP
+.B *.text.dict.fast
+Fast loading compression dictionary.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.invf.dict
+Compressed stemmed dictionary.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.TP
+.B *.text.stats
+Statistics about the text.
+.TP
+.B *.text.dict.aux
+Auxiliary compression dictionary.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.B *.invf.chunk
+Maps stemmed terms from occurrence order to lexical order.
+.TP
+.B *.invf.chunk.trans
+Describes where the source text is broken up into chunks for the
+inversion pass.
+.TP
+.B *.invf.dict.hash
+A perfect hash function for the terms in the stemmed dictionary.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_compression_dict (1),
+.BR mg_fast_comp_dict (1),
+.BR mg_get (1),
+.BR mg_invf_dict (1),
+.BR mg_invf_dump (1),
+.BR mg_invf_rebuild (1),
+.BR mg_passes (1),
+.BR mg_perf_hash_build (1),
+.BR mg_text_estimate (1),
+.BR mg_weights_build (1),
+.BR mgbilevel (1),
+.BR mgbuild (1),
+.BR mgdictlist (1),
+.BR mgfelics (1),
+.BR mgquery (1),
+.BR mgtic (1),
+.BR mgticbuild (1),
+.BR mgticdump (1),
+.BR mgticprune (1),
+.BR mgticstat (1).
Index: /indexers/branches/3.03a/mg/src/text/mgstat.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mgstat.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mgstat.c	(revision 14757)
@@ -0,0 +1,406 @@
+/**************************************************************************
+ *
+ * mgstat.c -- Program to generate statistics on a text collection
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "locallib.h"
+#include "mg.h"
+#include "words.h"
+#include "invf.h"
+#include "text.h"
+#include "longlong.h"
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.2  2001/09/21 12:46:42  kjm18
+   updated mg to be in line with mg_1.3f. Now uses long long for some variables
+   to enable indexing of very large collections.
+
+   Revision 1.1  1999/08/10 21:18:19  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:50  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:31  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.2  1994/09/20  04:41:59  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+char *search_for_collection (char *name);
+int process_file (char *, char *, int);
+void ProcessDict (char *);
+void ProcessStem (char *);
+long ProcessStemBlk (char *name);  /* [RPAP - Jan 97: Stem Index Change] */
+
+static mg_ullong inputbytes = 0;
+static mg_ullong total = 0;
+
+
+
+
+
+int main (int argc, char **argv)
+{
+  mg_ullong sub_total;
+  int fast;
+  char *file_name = "";
+  int ch;
+  int exact = 0;
+  long indexed = 0; /* [RPAP - Jan 97: Stem Index Change] */
+  opterr = 0;
+  while ((ch = getopt (argc, argv, "Ehf:d:")) != -1)
+    switch (ch)
+      {
+      case 'E':
+	exact = 1;
+	break;
+      case 'f':		/* input file */
+	file_name = optarg;
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-f input_file]"
+		 "[-d data directory] [-h]\n", argv[0]);
+	exit (1);
+      }
+
+  if (optind < argc)
+    file_name = search_for_collection (argv[optind]);
+
+  ProcessDict (file_name);
+  ProcessStem (file_name);
+  indexed = ProcessStemBlk (file_name); /* [RPAP - Jan 97: Stem Index Change] */
+
+  {
+    char Name[256];
+    char *s;
+    sprintf (Name, FILE_NAME_FORMAT, get_basepath (), file_name, "");
+    s = strrchr (Name, '/');
+    if (s)
+      *s = '\0';
+    printf ("\nThe collection is in \"%s\"\n", Name);
+  }
+
+
+  printf ("\n\t\tFiles required by mgquery\n");
+  process_file (file_name, TEXT_SUFFIX, exact);
+  process_file (file_name, INVF_SUFFIX, exact);
+  process_file (file_name, TEXT_IDX_WGT_SUFFIX, exact);
+  process_file (file_name, APPROX_WEIGHTS_SUFFIX, exact);
+  process_file (file_name, INVF_DICT_BLOCKED_SUFFIX, exact);
+
+  /* [RPAP - Jan 97: Stem Index Change] */
+  if (indexed)
+    {
+      process_file (file_name, INVF_DICT_BLOCKED_1_SUFFIX, exact);
+      process_file (file_name, INVF_DICT_BLOCKED_2_SUFFIX, exact);
+      process_file (file_name, INVF_DICT_BLOCKED_3_SUFFIX, exact);
+    }
+
+  fast = process_file (file_name, TEXT_DICT_FAST_SUFFIX, exact);
+  if (!fast)
+    {
+      process_file (file_name, TEXT_DICT_SUFFIX, exact);
+      process_file (file_name, TEXT_DICT_AUX_SUFFIX, exact);
+    }
+
+
+  process_file (NULL, "SUB TOTAL", exact);
+  sub_total = total;
+  total = 0;
+
+  printf ("\n\t\tFiles NOT required by mgquery\n");
+  if (fast)
+    {
+      process_file (file_name, TEXT_DICT_SUFFIX, exact);
+      process_file (file_name, TEXT_DICT_AUX_SUFFIX, exact);
+    }
+  process_file (file_name, INVF_DICT_SUFFIX, exact);
+  process_file (file_name, INVF_IDX_SUFFIX, exact);
+  process_file (file_name, TEXT_STATS_DICT_SUFFIX, exact);
+  process_file (file_name, TEXT_IDX_SUFFIX, exact);
+  process_file (file_name, WEIGHTS_SUFFIX, exact);
+  process_file (file_name, INVF_CHUNK_SUFFIX, exact);
+  process_file (file_name, INVF_CHUNK_TRANS_SUFFIX, exact);
+  process_file (file_name, INVF_DICT_HASH_SUFFIX, exact);
+  process_file (file_name, INVF_PARAGRAPH_SUFFIX, exact);
+  process_file (NULL, "SUB TOTAL", exact);
+  total += sub_total;
+  printf ("\n");
+  process_file (NULL, "TOTAL", exact);
+  return 0;
+
+}
+
+
+
+char *
+search_for_collection (char *name)
+{
+  char *dir = get_basepath ();
+  static char buffer[512];
+  struct stat stat_buf;
+
+  /* Look in the current directory first */
+  if (stat (name, &stat_buf) != -1)
+    {
+      if (S_ISDIR(stat_buf.st_mode))
+	{
+	  /* The name is a directory */
+	  sprintf (buffer, "%s/%s", name, name);
+	  set_basepath (".");
+	  return buffer;
+	}
+    }
+
+  sprintf (buffer, "%s.text", name);
+  if (stat (buffer, &stat_buf) != -1)
+    {
+      if (S_ISREG(stat_buf.st_mode))
+	{
+	  /* The name is a directory */
+	  set_basepath (".");
+	  return name;
+	}
+    }
+  sprintf (buffer, "%s/%s", dir, name);
+  if (stat (buffer, &stat_buf) != -1)
+    {
+      if (S_ISDIR(stat_buf.st_mode))
+	{
+	  /* The name is a directory */
+	  sprintf (buffer, "%s/%s", name, name);
+	  return buffer;
+	}
+    }
+  return name;
+}
+
+
+
+
+
+
+void 
+ProcessDict (char *name)
+{
+  FILE *f;
+  compression_dict_header cdh;
+  int have_cdh = 0;
+  compressed_text_header cth;
+  int have_cth = 0;
+
+  if ((f = open_file (name, TEXT_DICT_SUFFIX, "rb", MAGIC_DICT, MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      Read_cdh (f, &cdh, NULL, NULL);
+      fclose (f);
+      have_cdh = 1;
+    }
+
+  if ((f = open_file (name, TEXT_SUFFIX, "rb", MAGIC_TEXT, MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      fread ((char *) &cth, sizeof (cth), 1, f);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(cth.num_of_docs);
+      NTOHD(cth.num_of_bytes); /* [RJM 07/97: 4G limit] */
+      NTOHUL(cth.num_of_words);
+      NTOHUL(cth.length_of_longest_doc);
+      NTOHD(cth.ratio);
+
+      fclose (f);
+      have_cth = 1;
+    }
+
+  if (have_cth)
+    {
+      inputbytes = cth.num_of_bytes;
+      printf ("Input bytes                        : %10" ULL_FS ", %8.2f Mbyte\n",
+	      cth.num_of_bytes, (double) cth.num_of_bytes / 1024 / 1024);
+      printf ("Documents                          : %10lu\n", cth.num_of_docs);
+      printf ("Words in collection [dict]         : %10lu\n", cth.num_of_words);
+      printf ("Longest doc in collection [dict]   : %10lu characters\n",
+	      cth.length_of_longest_doc);
+      printf ("Maximum ratio                      : %10.2f\n", cth.ratio);
+    }
+
+  if (have_cdh)
+    {
+      printf ("Words in dict                      : %10lu\n", cdh.num_words[1]);
+      printf ("Non-words in dict                  : %10lu\n", cdh.num_words[0]);
+      printf ("Total chars of distinct words      : %10lu\n", cdh.num_word_chars[1]);
+      printf ("Total chars of distinct non-words  : %10lu\n", cdh.num_word_chars[0]);
+    }
+
+}
+
+
+
+
+
+
+
+
+void 
+ProcessStem (char *name)
+{
+  FILE *f;
+  struct invf_dict_header idh;
+
+  if (!(f = open_file (name, INVF_DICT_SUFFIX, "rb",
+		       MAGIC_STEM_BUILD, MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return;
+  fread ((char *) &idh, sizeof (idh), 1, f);
+  printf ("Words in collection [stem]         : %10ld\n", NTOHUL(idh.num_of_words));  /* [RPAP - Jan 97: Endian Ordering] */
+  printf ("Words in stem                      : %10ld\n", NTOHUL(idh.dict_size));  /* [RPAP - Jan 97: Endian Ordering] */
+  printf ("Indexed fragments                  : %10ld\n", NTOHUL(idh.num_of_docs));  /* [RPAP - Jan 97: Endian Ordering] */
+  printf ("Total chars of stem words          : %10ld\n", NTOHUL(idh.total_bytes));  /* [RPAP - Jan 97: Endian Ordering] */
+  fclose (f);
+}
+
+
+
+
+
+/* [RPAP - Jan 97: Stem Index Change] */
+long 
+ProcessStemBlk (char *name)
+{
+  FILE *f;
+  struct stem_dict_header sdh;
+
+  if (!(f = open_file (name, INVF_DICT_BLOCKED_SUFFIX, "rb",
+		       MAGIC_STEM, MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return 0;
+  fread ((char *) &sdh, sizeof (sdh), 1, f);
+  fclose (f);
+  return NTOHUL(sdh.indexed);  /* [RPAP - Jan 97: Endian Ordering] */
+}
+
+
+
+
+int 
+process_file (char *name, char *ext, int exact)
+{
+  static double scale = 0;
+  static char *units;
+  struct stat buf;
+  if (scale == 0)
+    {
+      /* So can get output in Mb or Kb, */
+      /* will divide by a scale of 1024(Kb) or 1024*1024(Mb) */
+      /* Note: if inputbytes==0, then use 1024 as default */
+      scale = inputbytes > 10 * 1000 * 1000 ? 1024 * 1024 : 1024;
+      units = scale == 1024 ? "Kb" : "Mb";
+    }
+  if (name)
+    {
+      char Name[256];
+      sprintf (Name, FILE_NAME_FORMAT, get_basepath (), name, ext);
+      if (!stat (Name, &buf))
+	{
+	  char fname[256];
+	  char *nam = strrchr (name, '/');
+	  nam = nam ? nam + 1 : name;
+	  sprintf (fname, "%s%s", nam, ext);
+
+	  if (inputbytes == 0.0)
+	    {
+	      if (exact)
+		printf ("%s%*s: %10ld bytes   %7.3f%%\n", fname,
+			35 - (int) strlen (fname), "",
+			buf.st_size,
+			100.0 * buf.st_size / inputbytes);
+	      else
+		printf ("%s%*s: %8.2f %s   %7.3f%%\n", fname,
+			35 - (int) strlen (fname), "",
+			buf.st_size / scale,
+			units,
+			100.0 * buf.st_size / inputbytes);
+	    }
+	  else
+	    {
+	      if (exact)
+		printf ("%s%*s: %10ld bytes\n", fname,
+			35 - (int) strlen (fname), "",
+			buf.st_size);
+	      else
+		printf ("%s%*s: %8.2f %s\n", fname,
+			35 - (int) strlen (fname), "",
+			buf.st_size / scale,
+			units);
+	    }
+	  total += buf.st_size;
+	  return 1;
+	}
+      else
+	return 0;
+    }
+  else
+    {
+      if (inputbytes == 0.0)
+	{
+	  if (exact)
+	    printf ("%-34s : %10" ULL_FS " bytes   %7.3f%%\n", ext,
+		    total,
+		    100.0 * total / inputbytes);
+	  else
+	    printf ("%-34s : %8.2f %s   %7.3f%%\n", ext,
+		    total / scale, units,
+		    100.0 * total / inputbytes);
+	}
+      else
+	{
+	  if (exact)
+	    printf ("%-34s : %10" ULL_FS " bytes\n", ext, total);
+	  else
+	    printf ("%-34s : %8.2f %s\n", ext,
+		    total / scale, units);
+	}
+    }
+  return 1;
+
+}
Index: /indexers/branches/3.03a/mg/src/text/mgstemidxlist.1
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mgstemidxlist.1	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mgstemidxlist.1	(revision 14757)
@@ -0,0 +1,86 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $Id$
+.\"------------------------------------------------------------
+.TH mgstemidxlist 1 \*(Dt CITRI
+.SH NAME
+mgstemidxlist \- dumps the stem index file to STDOUT in ASCII format
+.SH SYNOPSIS
+.B mgstemidxlist
+[
+.B \-h
+]
+[
+.BI \-d " directory"
+]
+.B \-s 1|2|3
+.BI \-f " name"
+.SH DESCRIPTION
+.B mgstemidxlist
+is a utility program which passes through the stem index and displays
+the information.  (This program was used for debugging but is included
+for completeness!)  The header information is printed out, then for each
+block in the file the block header is displayed.  For each word in the
+stem index, the output is formatted as:
+
+.RS
+.I number_of_references \*(lqword\*(rq
+.br
+.RS
+.I "->  number_of_cases block 3-in-4_block offset"
+.br
+.I "->  ..."
+.RE
+.RE
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B -s 1|2|3
+The stem index file with the associated stem method.
+.br
+1 = casefolded and non-stemmed
+.br
+2 = non-casefolded and stemmed
+.br
+3 = casefolded and stemmed
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the
+.BR mg (1)
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 25
+.B *.invf.dict.blocked.1
+Stem index with stem index method 1.
+.TP
+.B *.invf.dict.blocked.2
+Stem index with stem index method 2.
+.TP
+.B *.invf.dict.blocked.3
+Stem index with stem index method 3.
+.SH "SEE ALSO"
+.na
+.BR mg (1),
+.BR mg_invf_dict (1),
+.BR mg_stem_idx (1).
Index: /indexers/branches/3.03a/mg/src/text/mgstemidxlist.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/mgstemidxlist.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/mgstemidxlist.c	(revision 14757)
@@ -0,0 +1,245 @@
+/**************************************************************************
+ *
+ * mgstemidxlist.c -- Text dumper for the stem indexes
+ * Copyright (C) 1997  Ross Peeters
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "messages.h"
+#include "memlib.h"
+#include "local_strings.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "mg.h"
+#include "invf.h"
+#include "words.h"
+#include "backend.h"
+
+void
+read_3_in_4 (FILE * idbi)
+{
+  unsigned long i;
+  stemmed_idx *si;
+  u_char *buffer;
+  int block = 0;
+
+  if (!(si = Xmalloc (sizeof (stemmed_idx))))
+    {
+      return;
+    }
+
+  si->MemForStemIdx = 0;
+
+  fread (&(si->sih), sizeof (si->sih), 1, idbi);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(si->sih.lookback);
+  NTOHUL(si->sih.block_size);
+  NTOHUL(si->sih.num_blocks);
+  NTOHUL(si->sih.blocks_start);
+  NTOHUL(si->sih.index_chars);
+  NTOHUL(si->sih.num_of_words);
+
+  if (!(buffer = Xmalloc (si->sih.index_chars)))
+    {
+      Xfree (si);
+      return;
+    };
+  si->MemForStemIdx += si->sih.index_chars;
+
+  if (!(si->index = Xmalloc (si->sih.num_blocks * sizeof (*si->index))))
+    {
+      Xfree (si);
+      Xfree (buffer);
+      return;
+    };
+  si->MemForStemIdx += si->sih.num_blocks * sizeof (*si->index);
+
+  if (!(si->pos = Xmalloc (si->sih.num_blocks * sizeof (*si->pos))))
+    {
+      Xfree (si->index);
+      Xfree (si);
+      Xfree (buffer);
+      return;
+    };
+  si->MemForStemIdx += si->sih.num_blocks * sizeof (*si->pos);
+
+  if (!(si->buffer = Xmalloc (si->sih.block_size * sizeof (*si->buffer))))
+    {
+      Xfree (buffer);
+      Xfree (si->index);
+      Xfree (si->buffer);
+      Xfree (si);
+      return;
+    };
+  si->MemForStemIdx += si->sih.block_size * sizeof (*si->buffer);
+
+  si->active = -1;
+
+  for (i = 0; i < si->sih.num_blocks; i++)
+    {
+      register u_char len;
+      si->index[i] = buffer;
+      len = fgetc (idbi);
+      *buffer++ = len;
+      fread (buffer, sizeof (u_char), len, idbi);
+      buffer += len;
+      fread (&si->pos[i], sizeof (*si->pos), 1, idbi);
+      NTOHUL(si->pos[i]);  /* [RPAP - Jan 97: Endian Ordering] */
+    }
+
+  printf ("# lookback     = %lu\n", si->sih.lookback);
+  printf ("# block_size   = %lu\n", si->sih.block_size);
+  printf ("# num_blocks   = %lu\n", si->sih.num_blocks);
+  printf ("# blocks_start = %lu\n", si->sih.blocks_start);
+  printf ("# index_chars  = %lu\n", si->sih.index_chars);
+  printf ("# num_of_words = %lu\n", si->sih.num_of_words);
+
+  block = 0;
+  while (block < si->sih.num_blocks)
+    {
+      unsigned long *first_word;
+      unsigned short *num_words;
+      unsigned short *index;
+      long res;
+      u_char *base;
+      int num_indexes;
+
+      /* Read in next block */
+      fseek (idbi, si->pos[block] + si->sih.blocks_start, 0);
+      fread (si->buffer, si->sih.block_size, sizeof (u_char), idbi);
+      si->active = si->pos[block];
+
+      first_word = (unsigned long *) (si->buffer);
+      NTOHUL(*first_word);  /* [RPAP - Jan 97: Endian Ordering] */
+      num_words = (unsigned short *) (first_word + 1);
+      NTOHUS(*num_words);  /* [RPAP - Jan 97: Endian Ordering] */
+      index = num_words + 1;
+      num_indexes = ((*num_words - 1) / si->sih.lookback) + 1;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (i = 0; i < num_indexes; i++)
+	NTOHUS(index[i]);
+
+      base = (u_char *) (index + num_indexes);
+      base += index[0];
+
+      printf ("\n# block      = %d\n", block);
+      printf ("# first_word = %lu\n", *first_word);
+      printf ("# num_words  = %u\n", *num_words);
+
+      res = 0;
+      while (res < *num_words)
+	{
+	  unsigned copy, suff;
+	  u_char prev[MAXSTEMLEN + 1];
+	  unsigned int num_entries, num_cases, blk;
+	  unsigned short blk_index, offset;
+
+	  /* Read word entry */
+	  copy = *base++;
+	  suff = *base++;
+	  bcopy ((char *) base, (char *) (prev + copy + 1), suff);
+	  *prev = copy + suff;
+	  base += suff;
+	  bcopy ((char *) base, (char *) &num_entries, sizeof (num_entries));
+	  base += sizeof (num_entries);
+	  NTOHUI(num_entries);  /* [RPAP - Jan 97: Endian Ordering] */
+	  printf ("%u \"%s\"\n", num_entries, word2str (prev));
+
+	  /* For all the PosEntries for the word... */
+	  for (i = 0; i < num_entries; i++)
+	    {
+	      bcopy ((char *) base, (char *) &num_cases, sizeof (num_cases));
+	      NTOHUI(num_cases);  /* [RPAP - Jan 97: Endian Ordering] */
+	      base += sizeof (num_cases);
+	      bcopy ((char *) base, (char *) &blk, sizeof (blk));
+	      NTOHUI(blk);  /* [RPAP - Jan 97: Endian Ordering] */
+	      base += sizeof (blk);
+	      bcopy ((char *) base, (char *) &blk_index, sizeof (blk_index));
+	      NTOHUS(blk_index);  /* [RPAP - Jan 97: Endian Ordering] */
+	      base += sizeof (blk_index);
+	      bcopy ((char *) base, (char *) &offset, sizeof (offset));
+	      NTOHUS(offset);  /* [RPAP - Jan 97: Endian Ordering] */
+	      base += sizeof (offset);
+
+	      printf ("    -> %4u %4u %4u %4u\n", num_cases, blk, blk_index, offset);
+	    }
+	  res++;
+	}
+      block++;
+    }
+  fclose (idbi);
+}
+
+int
+main (int argc, char **argv)
+{
+  FILE *idbi;
+  char *filename = "";
+  int ch;
+  int stem_method = 0;
+
+  msg_prefix = argv[0];
+  opterr = 0;
+  while ((ch = getopt (argc, argv, "f:d:hs:")) != -1)
+    switch (ch)
+      {
+      case 'f':		/* input file */
+	filename = optarg;
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 's':
+	stem_method = atoi (optarg);
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-d data directory] [-h] -s 1|2|3 -f name\n", argv[0]);
+	exit (1);
+      }
+
+  /* Open required files */
+  switch (stem_method)
+    {
+    case (1):
+      idbi = open_file (filename, INVF_DICT_BLOCKED_1_SUFFIX, "rb", MAGIC_STEM_1,
+			MG_ABORT);
+      break;
+    case (2):
+      idbi = open_file (filename, INVF_DICT_BLOCKED_2_SUFFIX, "rb", MAGIC_STEM_2,
+			MG_ABORT);
+      break;
+    case (3):
+      idbi = open_file (filename, INVF_DICT_BLOCKED_3_SUFFIX, "rb", MAGIC_STEM_3,
+			MG_ABORT);
+      break;
+    default:
+      FatalError (1, "Stem method must be 1, 2 or 3\n");
+    }
+
+  if (!idbi)
+    FatalError (1, "Could NOT open file");
+
+  read_3_in_4 (idbi);
+
+  return 0;
+}
Index: /indexers/branches/3.03a/mg/src/text/query.docnums.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/query.docnums.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/query.docnums.c	(revision 14757)
@@ -0,0 +1,100 @@
+/**************************************************************************
+ *
+ * query.docnums.c -- Docnums query evaluation
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "filestats.h"
+#include "timing.h"
+
+#include "mg.h"
+#include "invf.h"
+#include "text.h"
+#include "lists.h"
+#include "backend.h"
+
+
+static DocList *
+AddToDocList (DocList * Docs, int res)
+{
+  int j;
+  /* Search the list for the word */
+  for (j = 0; j < Docs->num; j++)
+    if (Docs->DE[j].DocNum == res)
+      break;
+
+  /* Increment the weight if the word is in the list */
+  if (j < Docs->num)
+    Docs->DE[j].Weight++;
+  else
+    {
+      /* Create a new entry in the list for the new document */
+      Docs = ResizeDocList (Docs, Docs->num + 1);
+      Docs->DE[Docs->num].DocNum = res;
+      Docs->DE[Docs->num].Weight = 1;
+      Docs->DE[Docs->num].SeekPos = 0;
+      Docs->DE[Docs->num].Len = 0;
+      Docs->DE[Docs->num].CompTextBuffer = NULL;
+      Docs->DE[Docs->num].Next = NULL;
+      Docs->num++;
+    }
+  return (Docs);
+}
+
+void 
+DocnumsQuery (query_data * qd, char *QueryLine)
+{
+  DocList *Docs = MakeDocList (0);
+  unsigned long start = 0, finish;
+  int range = 0; /* is there a range or not ? */
+
+  /* find the start of the first word */
+  while (*QueryLine)
+    {
+      char *end;
+      finish = strtol (QueryLine, &end, 10);
+      if (end != (char *) QueryLine && finish >= 1 &&
+	  finish <= qd->sd->sdh.num_of_docs)
+	{
+	  unsigned long i;
+	  if (!range)
+	    start = finish;
+	  else
+	    range = 0;
+	  for (i = start; i <= finish; i++)
+	    Docs = AddToDocList (Docs, i);
+	  while (*end == ' ' || *end == '\t' || *end == '\n')
+	    end++;
+	  if (*end == '-')
+	    {
+	      start = finish;
+	      range = 1;
+	      end++;
+	    }
+	}
+      else
+	break;
+      QueryLine = end;
+    }
+  FreeQueryDocs (qd);
+
+  qd->DL = Docs;
+}
Index: /indexers/branches/3.03a/mg/src/text/query.ranked.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/query.ranked.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/query.ranked.c	(revision 14757)
@@ -0,0 +1,994 @@
+/**************************************************************************
+ *
+ * query.ranked.c -- Ranked query evaluation
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "filestats.h"
+#include "messages.h"
+#include "timing.h"
+#include "sptree.h"
+
+#include "mg.h"
+#include "invf.h"
+#include "text.h"
+#include "lists.h"
+#include "backend.h"
+#include "stem_search.h"
+#include "weights.h"
+#include "text_get.h"
+#include "invf_get.h"
+#include "words.h"
+#include "stemmer.h"
+#include "locallib.h"
+#include "environment.h"
+#include "term_lists.h"
+#include "local_strings.h"
+#include "query_term_list.h"  /* [RPAP - Feb 97: Term Frequency] */
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:20  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:50  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:34  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.4  1994/11/25  03:47:46  tes
+   * Committing files before adding the merge stuff.
+   *
+   * Revision 1.3  1994/10/20  03:57:03  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:42:04  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+/*************************************************************************/
+
+typedef struct HeapEntry
+  {
+    float Weight;
+    float *OrgWeight;
+    int DocNum;
+    u_long SeekPos;		/* position in the text file in bytes */
+    u_long Len;			/* length of the document in bytes */
+  }
+HeapEntry;
+
+typedef int (*HeapComp) (HeapEntry *, HeapEntry *);
+
+typedef struct Heap
+  {
+    int NumItems;
+    int MaxSize;
+    HeapComp HC;
+    HeapEntry HE[1];
+  }
+Heap;
+
+
+Heap *
+Heap_Make (int size, HeapComp hc)
+{
+  Heap *H;
+  H = Xmalloc (sizeof (Heap) + (size - 1) * sizeof (HeapEntry));
+  if (!H)
+    return NULL;
+  H->NumItems = 0;
+  H->MaxSize = size;
+  H->HC = hc;
+  return H;
+}
+
+int 
+Heap_Size (Heap * H)
+{
+  return sizeof (Heap) + H->MaxSize * sizeof (HeapEntry);
+}
+
+HeapEntry *
+Heap_GetHead (Heap * H)
+{
+  if (H && H->NumItems)
+    return &H->HE[0];
+  else
+    return NULL;
+}
+
+
+
+void 
+Heap_Heapify (Heap * H, int i)
+{
+  register int curr, child;
+  curr = i;
+  child = curr * 2;
+  while (child <= H->NumItems)
+    {
+      if (child < H->NumItems && H->HC (&H->HE[child], &H->HE[child - 1]) > 0)
+	child++;
+      if (H->HC (&H->HE[curr - 1], &H->HE[child - 1]) < 0)
+	{
+	  HeapEntry temp = H->HE[child - 1];
+	  H->HE[child - 1] = H->HE[curr - 1];
+	  H->HE[curr - 1] = temp;
+	  curr = child;
+	  child = 2 * child;
+	}
+      else
+	break;
+    }
+}
+
+
+void 
+Heap_Build (Heap * H)
+{
+  register int i;
+  for (i = H->NumItems / 2; i > 0; i--)
+    Heap_Heapify (H, i);
+}
+
+
+void 
+Heap_Sort (Heap * H)
+{
+  register int i;
+  for (i = H->NumItems; i > 1; i--)
+    {
+      HeapEntry temp = H->HE[0];
+      H->HE[0] = H->HE[i - 1];
+      H->HE[i - 1] = temp;
+      H->NumItems--;
+      Heap_Heapify (H, 1);
+    }
+}
+
+
+void 
+Heap_DeleteHead (Heap * H)
+{
+  H->HE[0] = H->HE[--H->NumItems];
+  Heap_Heapify (H, 1);
+}
+
+int 
+Heap_Lesser (HeapEntry * a, HeapEntry * b)
+{
+  return (a->Weight > b->Weight ? -1 :
+	  (a->Weight == b->Weight ? 0 : 1));
+}
+
+
+int 
+Heap_Greater (HeapEntry * a, HeapEntry * b)
+{
+  return (a->Weight > b->Weight ? 1 :
+	  (a->Weight == b->Weight ? 0 : -1));
+}
+
+int 
+Make_Exact_Root (query_data * qd, Heap * H)
+{
+  int num = 0;
+  HeapEntry *he = H->HE;
+  while (he->SeekPos == 0)
+    {
+      he->Weight = he->Weight *
+	GetLowerApproxDocWeight (qd->awd, he->DocNum - 1) /
+	FetchDocStart (qd, he->DocNum, &he->SeekPos, &he->Len);
+      Heap_Heapify (H, 1);
+      num++;
+    }
+  return num;
+}
+
+void 
+Heap_Dump (Heap * H, int num)
+{
+  int i, l, lines, r;
+  if (num > H->NumItems)
+    num = H->NumItems;
+  lines = (num + 3) / 4;
+  for (l = 0; l < lines; l++)
+    for (r = 0; r < 4; r++)
+      {
+	i = lines * r + l;
+	if (i < num)
+	  fprintf (stderr, "[%2d] %7.4f", i, H->HE[i].Weight);
+	fprintf (stderr, r == 3 ? "\n" : "        ");
+      }
+  fprintf (stderr, "\n");
+}
+
+/*************************************************************************/
+
+
+
+
+
+
+int 
+doc_count_comp (const void *A, const void *B)
+{
+  const TermEntry *a = A;
+  const TermEntry *b = B;
+  return (a->WE.doc_count - b->WE.doc_count);
+}
+
+/* =========================================================================
+ * Function: ParseRankedQuery
+ * Description:
+ *      Takes a string query line and extracts the terms in the query
+ *      which exist in the stemmed dictionary.
+ *      Optionally sorts the terms into ascending order by doc. number.
+ * Input:
+ *      stemmed dictionary, query line, sort-flag
+ * Output:
+ *      A list of terms.
+ * ========================================================================= */
+
+/* [RPAP - Jan 97: Stem Index Change] */
+static TermList *
+ParseRankedQuery (stemmed_dict * sd, char *QueryLine, int Sort, int indexed,
+		  QueryTermList **query_term_list)  /* [RPAP - Feb 97: Term Frequency] */
+{
+  u_char Word[MAXSTEMLEN + 1];
+  u_char sWord[MAXSTEMLEN + 1];
+  u_char *end, *s_in;
+  int default_stem_method = 0;
+  TermList *Terms = MakeTermList(0);
+
+  s_in = (u_char *) QueryLine;
+  end = s_in + strlen ((char *) s_in) - 1;
+  *query_term_list = MakeQueryTermList(0);  /* [RPAP - Feb 97: Term Frequency] */
+
+  if (indexed)
+    default_stem_method = BooleanEnv (GetEnv ("casefold"), 0) | (BooleanEnv (GetEnv ("stem"), 0) << 1);
+  else
+    default_stem_method = sd->sdh.stem_method;
+
+  while (s_in <= end)
+    {
+      int j;
+      long num_entries, word_num;
+      unsigned long count, doc_count, invf_ptr, invf_len;
+      int weight_to_apply, stem_to_apply;
+      int method_using = -1;
+
+      /* 0=optional, 1=mustmatch */
+      int require_match = 0; /* [RJM 07/97: Ranked Required Terms] */
+
+      /* Skip over the non word separator taking note of any parameters */
+      PARSE_RANKED_NON_STEM_WORD (require_match, s_in, end); /* [RJM 07/97: Ranked Required Terms] */
+      if (s_in > end) break;
+
+      /* Get a word and stem it */
+      PARSE_STEM_WORD (Word, s_in, end);
+
+      /* Extract any parameters */
+      weight_to_apply = 1;
+      stem_to_apply = default_stem_method;
+      while (s_in <= end)
+	{
+	  int stem_param, weight_param, param_type;
+	  char param[MAXPARAMLEN + 1];
+
+	  param_type = 0;
+	  PARSE_OPT_TERM_PARAM (param, param_type, s_in, end);
+	  if (!param_type)
+	    break;
+
+	  switch (param_type)
+	    {
+	    case (WEIGHTPARAM):
+	      weight_param = atoi (param);
+	      if (errno != ERANGE && weight_param > 0)
+		weight_to_apply = weight_param;
+	      break;
+
+	    case (STEMPARAM):
+	      stem_param = atoi (param);
+	      if (errno != ERANGE && indexed && stem_param >= 0 && stem_param <= 3)
+		method_using = stem_to_apply = stem_param;
+	      break;
+	    }
+	}
+
+      bcopy ((char *) Word, (char *) sWord, *Word + 1);
+      stemmer (stem_to_apply, sd->sdh.stemmer_num, sWord);
+
+      if (!indexed || stem_to_apply == 0)
+	{
+	  /* Look for the word in the already identified terms */
+	  for (j = 0; j < Terms->num; j++)
+	    if (compare (Terms->TE[j].Word, Word) == 0)
+	      break;
+
+	  /* Increment the weight if the word is in the list */
+	  /* Update the require match attribute */
+	  if (j < Terms->num)
+	    {
+	      Terms->TE[j].Count = ((Terms->TE[j].Count + weight_to_apply > INT_MAX) ?
+				    INT_MAX : (Terms->TE[j].Count + weight_to_apply));
+	      Terms->TE[j].require_match = require_match; /* [RJM 07/97: Ranked Require match] */
+	      AddQueryTerm (query_term_list, Word, Terms->TE[j].WE.count, method_using);  /* [RPAP - Feb 97: Term Frequency] */
+	    }
+	  else
+	    {
+	      /* Look for it in the stemmed dictionary */
+	      if ((word_num = FindWord (sd, sWord, &count, &doc_count,
+					&invf_ptr, &invf_len)) != -1)
+		{
+		  /* Search the list for the word */
+		  for (j = 0; j < Terms->num; j++)
+		    if (Terms->TE[j].WE.word_num == word_num)
+		      break;
+
+		  /* Increment the weight if the word is in the list */
+		  if (j < Terms->num)
+		    {
+		      Terms->TE[j].Count = ((Terms->TE[j].Count + weight_to_apply > INT_MAX) ?
+					    INT_MAX : (Terms->TE[j].Count + weight_to_apply));
+		      Terms->TE[j].require_match = require_match; /* [RJM 07/97: Ranked Require match] */
+		      AddQueryTerm (query_term_list, Word, Terms->TE[j].WE.count, method_using);  /* [RPAP - Feb 97: Term Frequency] */
+		    }
+		  else
+		    {
+		      /* Create a new entry in the list for the new word */
+		      TermEntry te;
+
+		      te.WE.word_num = word_num;
+		      te.WE.count = count;
+		      te.WE.doc_count = doc_count;
+		      te.WE.max_doc_count = doc_count;
+		      te.WE.invf_ptr = invf_ptr;
+		      te.WE.invf_len = invf_len;
+		      te.Count = weight_to_apply;
+		      te.Word = copy_string (Word);
+		      if (!te.Word)
+			FatalError (1, "Could NOT create memory to add term");
+		      te.Stem = NULL;
+		      te.require_match = require_match;
+
+		      AddTermEntry (&Terms, &te);
+
+		      /* [RPAP - Feb 97: Term Frequency] */
+		      AddQueryTerm (query_term_list, Word, count, method_using);
+		    }
+		}
+	      /* [RPAP - Feb 97: Term Frequency] */
+	      else
+		AddQueryTerm (query_term_list, Word, 0, method_using);
+	    }
+	}
+      else
+	{
+	  int total_count = 0;  /* [RPAP - Feb 97: Term Frequency] */
+	  TermList *tempList = MakeTermList (0);
+	  if ((num_entries = FindWords (sd, sWord, stem_to_apply, &tempList)) > 0)
+	    {
+	      int i;
+	      u_long max_doc_count = 0;
+
+	      /* get the maximum doc count */
+	      for (i = 0; i < tempList->num; i++)
+		{
+		  if (tempList->TE[i].WE.doc_count > max_doc_count)
+		    max_doc_count = tempList->TE[i].WE.doc_count;
+		  total_count += tempList->TE[i].WE.count;  /* [RPAP - Feb 97: Term Frequency] */
+		}
+
+	      for (i = 0; i < tempList->num; i++)
+		{
+		  /* Look for the word(s) in the already identified terms */
+		  for (j = 0; j < Terms->num; j++) 
+		    {
+		      if (compare (Terms->TE[j].Word, tempList->TE[i].Word) == 0)
+			{
+			  /* found the word */
+			  /* Modify weight */
+			  Terms->TE[j].Count = ((Terms->TE[j].Count + weight_to_apply > INT_MAX) ?
+						INT_MAX : (Terms->TE[j].Count + weight_to_apply));
+			  if (Terms->TE[j].WE.max_doc_count < max_doc_count)
+			    Terms->TE[j].WE.max_doc_count = max_doc_count;
+			  break;
+			}
+		    }
+
+		  if (j == Terms->num)
+		    {
+		      /* word was not found */
+		      tempList->TE[i].WE.max_doc_count = max_doc_count;
+		      tempList->TE[i].Count = weight_to_apply;
+
+		      /* We cannot require a term to match if it is expanded */
+		      /* into multiple terms :-( */
+		      tempList->TE[i].require_match = 0; /* [RJM 07/97: Ranked Required Terms] */
+
+		      AddTermEntry (&Terms, &tempList->TE[i]);
+		    }
+		}
+	    }
+	  /* [RPAP - Feb 97: Term Frequency] */
+	  AddQueryTerm (query_term_list, Word, total_count, method_using);
+
+	  if (tempList != NULL) Xfree(tempList); /* [RJM 07/98: Memory Leak] */
+	} /* end indexed */
+    } /* end while */
+
+  if (Sort)
+    /* Sort the terms in ascending order by doc_count */
+    qsort (Terms->TE, Terms->num, sizeof (TermEntry), doc_count_comp);
+  return (Terms);
+}
+
+
+
+
+static int 
+DE_comp (void *a, void *b)
+{
+  return ((DocEntry *) a)->SeekPos - ((DocEntry *) b)->SeekPos;
+}
+
+
+
+
+
+/*
+ * This function is given a list of term numbers and it returns a list
+ * of document numbers based on the cosine document weighting system.
+ * This puts the entries in an array.
+ * inverted file.
+ * If MaxDocs == -1 then it means all 
+ */
+static DocList *
+CosineGet (query_data * qd, TermList * Terms, RankedQueryInfo * rqi) {
+  DocList *Docs;
+  float *AccumulatedWeights = NULL;
+  Splay_Tree *ST = NULL;
+  Splay_Tree *Para_ST = NULL;
+  Hash_Table *HT = NULL;
+  List_Table *LT = NULL;
+  Heap *H;
+  HeapEntry *he;
+  register float *fptr = NULL;
+  register Invf_Doc_Entry *ide = NULL;
+  register Invf_Doc_EntryH *ideh = NULL;
+  int BackEnd, NumExact, MaxExact, NumParas;
+  int MaxDocs = 0, MaxParas = 0;
+  int i;
+  Invf_Doc_Entry_Pool ide_pool;
+  ide_pool.pool = NULL;
+
+  qd->hops_taken = qd->num_of_ptrs = qd->num_of_accum = 0;
+
+  switch (rqi->AccumMethod)
+    {
+    case 'S':
+      ST = CosineDecodeSplay (qd, Terms, rqi, &ide_pool);
+      if (!ST)
+	return NULL;
+      break;
+    case 'A':
+      AccumulatedWeights = CosineDecode (qd, Terms, rqi);
+      if (!AccumulatedWeights)
+	return NULL;
+      break;
+    case 'H':
+      HT = CosineDecodeHash (qd, Terms, rqi);
+      if (!HT)
+	return NULL;
+      break;
+    case 'L':
+      LT = CosineDecodeList (qd, Terms, rqi);
+      if (!LT)
+	return NULL;
+      break;
+    }
+
+#if 0
+  if (rqi->UseSplayTree)
+    {
+
+      AccumulatedWeights = CosineDecode (qd, Terms, rqi);
+      fptr = AccumulatedWeights;
+      ide = SP_get_first (ST);
+      for (i = 0; i < qd->sd->sdh.num_of_docs; i++)
+	{
+	  if (AccumulatedWeights[i] != 0)
+	    {
+	      if (i != ide->DocNum)
+		fprintf (stderr, "Sum mismatch for %d %f %d %f\n", i + 1,
+			 AccumulatedWeights[i], ide->DocNum + 1, ide->Sum);
+	      ide = SP_get_next (ST);
+	    }
+	}
+    }
+#endif
+
+  switch (rqi->AccumMethod)
+    {
+    case 'S':
+      MaxParas = ST->no_of_items;
+      break;
+    case 'A':
+      {				/* count the number of non-zero document weights */
+	register int i = qd->sd->sdh.num_of_docs;
+	register float *d;
+	MaxParas = 0;
+	for (d = AccumulatedWeights; i; i--, d++)
+	  if (*d)
+	    MaxParas++;
+      }
+      break;
+    case 'H':
+      MaxParas = HT->num + HT->Suplimentary_Num;
+      break;
+    case 'L':
+      MaxParas = LT->num;
+      break;
+    }
+
+  if (rqi->MaxParasToRetrieve != -1 && MaxParas > rqi->MaxParasToRetrieve)
+    MaxParas = rqi->MaxParasToRetrieve;
+  MaxDocs = MaxParas;
+
+  /* Allocate memory for the heap */
+  Docs = MakeDocList (MaxDocs);
+  ChangeMemInUse (qd, sizeof (DocEntry) * MaxDocs);
+
+  H = Heap_Make (MaxDocs, Heap_Lesser);
+
+
+  /* Get the sums from the array divide the sums by the 
+     document weights which we retrieve from the ".idx.wgt" file and put
+     the resulting data into a heap */
+
+
+  he = H->HE;
+  H->NumItems = MaxDocs;
+  switch (rqi->AccumMethod)
+    {
+    case 'S':
+      {
+	ide = SP_get_first (ST);
+	for (i = 0; i < H->NumItems; i++, ide = SP_get_next (ST), he++)
+	  {
+	    he->DocNum = ide->DocNum + 1;
+	    he->OrgWeight = &ide->Sum;
+	    qd->num_of_accum++;
+	  }
+      }
+      break;
+    case 'A':
+      {
+	fptr = AccumulatedWeights;
+	for (i = 0; i < H->NumItems; i++, fptr++, he++)
+	  {
+	    he->DocNum = i + 1;
+	    he->OrgWeight = fptr;
+	    if (*fptr)
+	      qd->num_of_accum++;
+	  }
+      }
+      break;
+    case 'H':
+      {
+	ideh = HT->Head;
+	for (i = 0; i < H->NumItems; i++, ideh = ideh->next, he++)
+	  {
+	    he->DocNum = ideh->IDE.DocNum + 1;
+	    he->OrgWeight = &ideh->IDE.Sum;
+	    qd->num_of_accum++;
+	  }
+      }
+      break;
+    case 'L':
+      {
+	ide = LT->IDE;
+	for (i = 0; i < H->NumItems; i++, ide++, he++)
+	  {
+	    he->DocNum = ide->DocNum + 1;
+	    he->OrgWeight = &ide->Sum;
+	    qd->num_of_accum++;
+	  }
+      }
+      break;
+    }
+
+  he = H->HE;
+  for (i = 0; i < H->NumItems; i++, he++)
+    {
+      *he->OrgWeight /= GetLowerApproxDocWeight (qd->awd, he->DocNum - 1);
+      he->Weight = *he->OrgWeight;
+      *he->OrgWeight = 0;
+      he->SeekPos = he->Len = 0;
+    }
+
+  Heap_Build (H);
+
+  he = H->HE;
+  switch (rqi->AccumMethod)
+    {
+    case 'S':
+      {
+	for (i = MaxDocs; i < ST->no_of_items; i++, ide = SP_get_next (ST))
+	  {
+	    ide->Sum /= GetLowerApproxDocWeight (qd->awd, ide->DocNum);
+	    qd->num_of_accum++;
+	    if (ide->Sum <= he->Weight)
+	      continue;
+	    *he->OrgWeight = he->Weight;
+	    he->DocNum = ide->DocNum + 1;
+	    he->Weight = ide->Sum;
+	    he->OrgWeight = &ide->Sum;
+	    *he->OrgWeight = 0;
+	    Heap_Heapify (H, 1);
+	  }
+      }
+      break;
+    case 'A':
+      {
+	for (i = MaxDocs; i < qd->sd->sdh.num_of_docs; i++, fptr++)
+	  {
+	    if (!*fptr)
+	      continue;
+	    qd->num_of_accum++;
+	    *fptr /= GetLowerApproxDocWeight (qd->awd, i);
+	    if (*fptr <= he->Weight)
+	      continue;
+	    *he->OrgWeight = he->Weight;
+	    he->DocNum = i + 1;
+	    he->Weight = *fptr;
+	    he->OrgWeight = fptr;
+	    *he->OrgWeight = 0;
+	    Heap_Heapify (H, 1);
+	  }
+      }
+      break;
+    case 'H':
+      {
+	for (; ideh; ideh = ideh->next)
+	  {
+	    qd->num_of_accum++;
+	    ideh->IDE.Sum /=
+	      GetLowerApproxDocWeight (qd->awd, ideh->IDE.DocNum);
+	    if (ideh->IDE.Sum <= he->Weight)
+	      continue;
+	    *he->OrgWeight = he->Weight;
+	    he->DocNum = ideh->IDE.DocNum + 1;
+	    he->Weight = ideh->IDE.Sum;
+	    he->OrgWeight = &ideh->IDE.Sum;
+	    *he->OrgWeight = 0;
+	    Heap_Heapify (H, 1);
+	  }
+      }
+      break;
+    case 'L':
+      {
+	for (i = MaxDocs; i < LT->num; i++, ide++)
+	  {
+	    qd->num_of_accum++;
+	    ide->Sum /=
+	      GetLowerApproxDocWeight (qd->awd, ide->DocNum);
+	    if (ide->Sum <= he->Weight)
+	      continue;
+	    *he->OrgWeight = he->Weight;
+	    he->DocNum = ide->DocNum + 1;
+	    he->Weight = ide->Sum;
+	    he->OrgWeight = &ide->Sum;
+	    *he->OrgWeight = 0;
+	    Heap_Heapify (H, 1);
+	  }
+      }
+      break;
+    }
+
+
+  if (rqi->Exact && qd->id->ifh.InvfLevel != 3)
+    {
+      HeapEntry *he = H->HE;
+
+      for (i = 0; i < H->NumItems; i++, he++)
+	{
+	  he->Weight = he->Weight *
+	    GetLowerApproxDocWeight (qd->awd, he->DocNum - 1) /
+	    FetchDocStart (qd, he->DocNum, &he->SeekPos, &he->Len);
+	}
+
+      Heap_Build (H);
+
+      he = H->HE;
+
+      switch (rqi->AccumMethod)
+	{
+	case 'S':
+	  {
+	    ide = SP_get_first (ST);
+	    for (i = 0; i < ST->no_of_items; i++, ide = SP_get_next (ST))
+	      {
+		u_long SeekPos, Len;
+		float Weight;
+		if (!ide->Sum)
+		  continue;
+		if (ide->Sum <= he->Weight)
+		  continue;
+		Weight = ide->Sum *
+		  GetLowerApproxDocWeight (qd->awd, ide->DocNum) /
+		  FetchDocStart (qd, ide->DocNum + 1, &SeekPos, &Len);
+		if (Weight <= he->Weight)
+		  continue;
+		he->DocNum = ide->DocNum + 1;
+		he->OrgWeight = &ide->Sum;
+		he->Weight = Weight;
+		he->SeekPos = SeekPos;
+		he->Len = Len;
+		ide->Sum = 0;
+		Heap_Heapify (H, 1);
+	      }
+	  }
+	  break;
+
+	  /* up to here */
+
+	case 'A':
+	  {
+	    fptr = AccumulatedWeights;
+	    for (i = 0; i < qd->sd->sdh.num_of_docs; i++, fptr++)
+	      {
+		u_long SeekPos, Len;
+		float Weight;
+		if (!*fptr)
+		  continue;
+		if (*fptr <= he->Weight)
+		  continue;
+		Weight = *fptr *
+		  GetLowerApproxDocWeight (qd->awd, i) /
+		  FetchDocStart (qd, i + 1, &SeekPos, &Len);
+		if (Weight <= he->Weight)
+		  continue;
+		he->DocNum = i + 1;
+		he->OrgWeight = fptr;
+		he->Weight = Weight;
+		he->SeekPos = SeekPos;
+		he->Len = Len;
+		*fptr = 0;
+		Heap_Heapify (H, 1);
+	      }
+	  }
+	  break;
+	case 'H':
+	  {
+	    ideh = HT->Head;
+	    for (ideh = HT->Head; ideh; ideh = ideh->next)
+	      {
+		u_long SeekPos, Len;
+		float Weight;
+		if (!ideh->IDE.Sum)
+		  continue;
+		if (ideh->IDE.Sum <= he->Weight)
+		  continue;
+		Weight = ideh->IDE.Sum *
+		  GetLowerApproxDocWeight (qd->awd, ideh->IDE.DocNum) /
+		  FetchDocStart (qd, ideh->IDE.DocNum + 1, &SeekPos, &Len);
+		if (Weight <= he->Weight)
+		  continue;
+		he->DocNum = ideh->IDE.DocNum + 1;
+		he->OrgWeight = &ideh->IDE.Sum;
+		he->Weight = Weight;
+		he->SeekPos = SeekPos;
+		he->Len = Len;
+		ideh->IDE.Sum = 0;
+		Heap_Heapify (H, 1);
+	      }
+	  }
+	  break;
+	case 'L':
+	  {
+	    ide = LT->IDE;
+	    for (i = 0; i < LT->num; i++, ide++)
+	      {
+		u_long SeekPos, Len;
+		float Weight;
+		if (!ide->Sum)
+		  continue;
+		if (ide->Sum <= he->Weight)
+		  continue;
+		Weight = ide->Sum *
+		  GetLowerApproxDocWeight (qd->awd, ide->DocNum) /
+		  FetchDocStart (qd, ide->DocNum + 1, &SeekPos, &Len);
+		if (Weight <= he->Weight)
+		  continue;
+		he->DocNum = ide->DocNum + 1;
+		he->OrgWeight = &ide->Sum;
+		he->Weight = Weight;
+		he->SeekPos = SeekPos;
+		he->Len = Len;
+		ide->Sum = 0;
+		Heap_Heapify (H, 1);
+	      }
+	  }
+	  break;
+	}
+    }
+
+
+
+  H->HC = Heap_Greater;
+  Heap_Build (H);
+
+
+  MaxDocs = H->NumItems;
+  if (rqi->MaxDocsToRetrieve != -1 && MaxDocs > rqi->MaxDocsToRetrieve)
+    MaxDocs = rqi->MaxDocsToRetrieve;
+
+  /* Alarm */
+
+  he = H->HE;
+  BackEnd = H->NumItems - 1;
+  NumExact = 0;
+  MaxExact = H->NumItems;
+  NumParas = 0;
+  Para_ST = SP_createset (DE_comp);
+  while (H->NumItems && Docs->num < MaxDocs)
+    {
+      DocEntry DocEnt;
+      DocEntry *mem;
+
+      if (rqi->Exact)
+	{
+	  if (H->HE[0].SeekPos == 0)
+	    NumExact += Make_Exact_Root (qd, H);
+	}
+      else
+	FetchDocStart (qd, he->DocNum, &he->SeekPos, &he->Len);
+
+      NumParas++;
+
+      DocEnt.DocNum = he->DocNum;
+      DocEnt.Weight = he->Weight;
+      DocEnt.Len = he->Len;
+      DocEnt.SeekPos = he->SeekPos;
+      DocEnt.CompTextBuffer = NULL;
+      DocEnt.Next = NULL;
+
+      Heap_DeleteHead (H);
+
+      if (!(mem = SP_member (&DocEnt, Para_ST)))
+	{
+	  Docs->DE[Docs->num] = DocEnt;
+	  SP_insert (&Docs->DE[Docs->num], Para_ST);
+	  Docs->num++;
+	}
+      else
+	{
+	  DocEnt.Next = mem->Next;
+	  Docs->DE[BackEnd] = DocEnt;
+	  mem->Next = &Docs->DE[BackEnd--];
+	}
+    }
+  SP_freeset (Para_ST);
+
+  if (qd->id->ifh.InvfLevel == 3)
+    {
+      Message ("%d Paragraphs were required to get %d documents",
+	       NumParas, Docs->num);
+      if (NumExact == MaxExact)
+	{
+	  Message ("The exact weights of all %d paragraphs had to be calculated", MaxExact);
+	  Message ("to obtain %d paragraphs. This may mean that the the documents", NumParas);
+	  Message ("returned do not necessarly represent an exact cosine ranking.");
+	  Message ("This problem may be corrected by increasing \'maxparas\'.");
+	}
+    }
+#if 0
+  {
+    int i;
+    FILE *f = fopen ("top.paras", "w");
+    fprintf (f, "=========================\nTop Paragraphs\n");
+    for (i = 0; i < Docs->num; i++)
+      {
+	DocEntry *d;
+	fprintf (f, "<%d(%f)>  ", Heap[i].DocNum, Heap[i].Weight);
+	for (d = Heap[i].Next; d; d = d->Next)
+	  fprintf (f, "%d(%f)  ", d->DocNum, d->Weight);
+	fprintf (f, "\n");
+      }
+    fprintf (f, "=========================\n");
+    fclose (f);
+  }
+#endif
+
+  if (AccumulatedWeights)
+    {
+      Xfree (AccumulatedWeights);
+      ChangeMemInUse (qd, -sizeof (float) * qd->sd->sdh.num_of_docs);
+    }
+  if (ST)
+    {
+      int mem = ST->mem_in_use;
+      SP_freeset (ST);
+      ChangeMemInUse (qd, -mem);
+      free_ide_pool (qd, &ide_pool);
+    }
+  if (HT)
+    HT_free (qd, HT);
+
+  if (LT)
+    LT_free (qd, LT);
+
+  if (H) Xfree (H); /* [RJM 07/98: Memory Leak] */
+
+  return (Docs);
+}
+
+
+
+
+/* if MaxDocs == -1 it means all */
+void 
+RankedQuery (query_data *qd, char *Query, RankedQueryInfo *rqi)
+{
+  DocList *dl;
+
+  if (qd->TL)
+    FreeTermList (&(qd->TL));
+
+  /* [RPAP - Feb 97: Term Frequency] */
+  if (qd->QTL)
+    FreeQueryTermList (&(qd->QTL));
+
+  qd->TL = ParseRankedQuery (qd->sd, Query, rqi->Sort, qd->sd->sdh.indexed,  /* [RPAP - Jan 97: Stem Index Change] */
+			     &(qd->QTL));  /* [RPAP - Feb 97: Term Frequency] */
+
+  /*  PrintTermList (qd->TL, stderr); */
+
+  dl = CosineGet (qd, qd->TL, rqi);
+
+  if (!dl)
+    FatalError (1, "Out of memory\n");
+
+  FreeQueryDocs (qd);
+
+  qd->DL = dl;
+}
Index: /indexers/branches/3.03a/mg/src/text/query_term_list.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/query_term_list.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/query_term_list.c	(revision 14757)
@@ -0,0 +1,228 @@
+/**************************************************************************
+ *
+ * filename -- description
+ * Copyright (C) 1994  Authors
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:21  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:35:36  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.1  1994/10/20  03:57:07  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+ */
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "local_strings.h"
+#include "query_term_list.h"
+#include "term_lists.h"  /* for MAXTERMSTRLEN */
+#include "messages.h"
+
+
+/* =========================================================================
+ * Function: MakeQueryTermList
+ * Description:
+ * Input:
+ * Output:
+ * ========================================================================= */
+QueryTermList *
+MakeQueryTermList (int n)
+{
+  QueryTermList *t;
+  int list_size = (n == 0 ? 1 : n);	/* always allocate at least one node */
+
+  t = Xmalloc (sizeof (QueryTermList) + (list_size - 1) * sizeof (QueryTermEntry));
+  if (!t)
+    FatalError (1, "Unable to allocate query term list");
+
+  t->num = n;
+  t->list_size = list_size;
+
+  return t;
+}
+
+/* =========================================================================
+ * Function: ResizeQueryTermList
+ * Description:
+ * Input:
+ * Output:
+ * ========================================================================= */
+
+#define GROWTH_FACTOR 2
+#define MIN_SIZE 2
+
+static void
+ResizeQueryTermList (QueryTermList ** query_list)
+{
+  QueryTermList *qtl = *query_list;
+
+  if (qtl->num > qtl->list_size)
+    {
+      if (qtl->list_size)
+	qtl->list_size *= GROWTH_FACTOR;
+      else
+	qtl->list_size = MIN_SIZE;
+    }
+  qtl = Xrealloc (qtl, sizeof (QueryTermList) + (qtl->list_size - 1) * sizeof (QueryTermEntry));
+
+  if (!qtl)
+    FatalError (1, "Unable to resize query term list");
+
+  *query_list = qtl;
+}
+
+/* =========================================================================
+ * Function: ConvertQueryTermsToString
+ * Description:
+ *      Convert term list into null-terminated string
+ * Input:
+ *      query_term_list = query list
+ * Output:
+ *      str = term string
+ * ========================================================================= */
+
+void
+ConvertQueryTermsToString (QueryTermList * query_term_list, char *str)
+{
+  int i = 0;
+  int total_len = 0;
+
+  /* terms_str should be preallocated */
+  if (!str)
+    return;
+
+  for (i = 0; i < query_term_list->num; i++)
+    {
+      unsigned char *word = query_term_list->QTE[i].Term;
+      int len = word[0];
+      total_len += len + 1;	/* +1 for space */
+      if (query_term_list->QTE[i].stem_method >= 0)
+	total_len += 2;         /* '#' and the stem number */
+      if (total_len > MAXTERMSTRLEN)
+	break;
+      strncpy (str, (char *) word + 1, len);
+      str += len;
+      if (query_term_list->QTE[i].stem_method >= 0)
+	{
+	  *str++ = '#';
+	  *str++ = '0' + query_term_list->QTE[i].stem_method;
+	}
+      if (i != (query_term_list->num) - 1)
+	{
+	  *str = ' ';
+	  str++;		/* add space gap */
+	}
+
+    }
+  *str = '\0';
+}
+
+/* =========================================================================
+ * Function: ResetTermList
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+void
+ResetQueryTermList (QueryTermList ** qtl)
+{
+  if (*qtl)
+    FreeQueryTermList (qtl);
+  *qtl = MakeQueryTermList (0);
+}
+
+/* =========================================================================
+ * Function: AddQueryTermEntry
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+int
+AddQueryTermEntry (QueryTermList ** query_term_list, QueryTermEntry * qte)
+{
+  QueryTermList *qtl = *query_term_list;
+
+  qtl->num++;
+  ResizeQueryTermList (query_term_list);
+  qtl = *query_term_list;
+
+  /* copy the structure contents */
+  bcopy ((char *) qte, (char *) &(qtl->QTE[qtl->num - 1]), sizeof (QueryTermEntry));
+
+  return qtl->num - 1;
+}
+
+
+
+/* =========================================================================
+ * Function: AddQueryTerm
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+int
+AddQueryTerm (QueryTermList ** query_term_list, u_char * Term, int Count, int stem_method)
+{
+  /* Create a new entry in the list for the new word */
+  QueryTermEntry qte;
+
+  qte.Count = Count;
+  qte.stem_method = stem_method;
+  qte.Term = copy_string (Term);
+  if (!qte.Term)
+    FatalError (1, "Could NOT create memory to add term");
+
+  return AddQueryTermEntry (query_term_list, &qte);
+}
+
+/* =========================================================================
+ * Function: FreeQueryTermList
+ * Description:
+ * Input:
+ * Output:
+ * ========================================================================= */
+
+void
+FreeQueryTermList (QueryTermList ** the_qtl)
+{
+  int j;
+  QueryTermList *qtl = *the_qtl;
+
+  for (j = 0; j < qtl->num; j++)
+    if (qtl->QTE[j].Term)
+      Xfree (qtl->QTE[j].Term);
+  Xfree (qtl);
+
+  *the_qtl = NULL;
+}
Index: /indexers/branches/3.03a/mg/src/text/query_term_list.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/query_term_list.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/query_term_list.h	(revision 14757)
@@ -0,0 +1,70 @@
+/**************************************************************************
+ *
+ * term_lists.h -- description
+ * Copyright (C) 1994  Authors
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:21  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:35:37  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.1  1994/10/20  03:57:08  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+ */
+
+#ifndef QUERY_TERM_LIST_H
+#define QUERY_TERM_LIST_H
+
+#include "sysfuncs.h"
+
+typedef struct QueryTermEntry
+  {
+    int Count;			/* The number of times the word occurs in the query */
+    u_char *Term;		/* The query term */
+    int stem_method;            /* The steming method to apply to the term : -1 is default */
+  }
+QueryTermEntry;
+
+typedef struct QueryTermList
+  {
+    int list_size;
+    int num;
+    QueryTermEntry QTE[1];
+  }
+QueryTermList;
+
+/* --- prototypes --- */
+void ConvertQueryTermsToString (QueryTermList * query_term_list, char *str);
+int AddQueryTerm (QueryTermList ** query_term_list, u_char * Term, int Count, int stem_method);
+void ResetQueryTermList (QueryTermList ** tl);
+void FreeQueryTermList (QueryTermList ** the_qtl);
+QueryTermList *MakeQueryTermList (int n);
+
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/read_line.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/read_line.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/read_line.c	(revision 14757)
@@ -0,0 +1,214 @@
+/**************************************************************************
+ *
+ * read_line.c -- Input line reading routines for mgquery
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "memlib.h"
+
+#ifdef GNU_READLINE
+#include "readline.h"
+#include "chardefs.h"
+#include "history.h"
+#endif
+
+
+#include "globals.h"
+#include "environment.h"
+#include "read_line.h"
+
+
+
+#ifdef GNU_READLINE
+int rl_bind_key (int, int (*)());
+
+
+void 
+Init_ReadLine (void)
+{
+  /* Make TAB just insert itself rather than do a file name completion */
+  rl_bind_key (TAB, rl_insert);
+}
+#else
+
+static FILE *rl_instream = NULL;
+static FILE *rl_outstream = NULL;
+
+void 
+Init_ReadLine (void)
+{
+  rl_instream = stdin;
+  rl_outstream = stdout;
+}
+
+static char *
+readline (char *pmt)
+{
+  static char buf[MAXLINEBUFFERLEN + 1];
+  char *s;
+
+  fprintf (rl_outstream, "%s", pmt);
+  s = fgets (buf, sizeof (buf), rl_instream);
+  if (s)
+    {
+      char *s1 = strrchr (s, '\n');
+      if (s1 && *(s1 + 1) == '\0')
+	*s1 = '\0';
+    }
+  return s ? Xstrdup (s) : NULL;
+}
+#endif
+
+/* WritePrompt() */
+/* Write out a prompt if user is a TTY */
+void 
+WritePrompt (void)
+{
+  if (isatty (fileno (InFile)))
+    {
+      if (!BooleanEnv (GetEnv ("expert"), 0))
+	fprintf (stderr, "Enter a command or query (.quit to terminate, .help for assistance).\n");
+    }
+}
+
+#ifdef GNU_READLINE
+static void memory_error_and_abort ();
+
+char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *) Xmalloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *) xmalloc (bytes);
+  else
+    temp = (char *) Xrealloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "history: Out of virtual memory!\n");
+  abort ();
+}
+#endif
+
+
+/*
+ * This routine returns a pointer to the users entered line 
+ *
+ */
+static char *
+GetLine (char *pmt)
+{
+  static char *the_line = NULL;
+  if (the_line)
+    Xfree (the_line);
+  the_line = NULL;
+  rl_instream = InFile;
+  if (isatty (fileno (InFile)))
+    {
+      fputc ('\r', stderr);
+      if (!isatty (fileno (OutFile)))
+	rl_outstream = stderr;
+      else
+	rl_outstream = OutFile;
+      the_line = readline (pmt);
+    }
+  else
+    {
+      if (isatty (fileno (OutFile)))
+	{
+	  the_line = readline (pmt);
+	  fprintf (stderr, "%s\n", the_line ? the_line : "");
+	}
+      else
+	{
+	  the_line = readline ("");
+	  if (the_line)
+	    fprintf (stderr, "%s%s\n", pmt, the_line);
+	}
+    }
+#ifdef GNU_READLINE
+  if (the_line && *the_line)
+    add_history (the_line);
+#endif
+  return (the_line);
+}
+
+
+
+
+
+
+char *
+GetMultiLine (void)
+{
+  static char *line = NULL;
+  char *s;
+  if (line)
+    Xfree (line);
+  line = NULL;
+  if (!(s = GetLine ("> ")))
+    return (NULL);
+  if (!(line = Xstrdup (s)))
+    {
+      fprintf (stderr, "Unable to allocate memory for the line\n");
+      abort ();
+    }
+
+  while ((s = strrchr (line, '\\')) && *(s + 1) == '\0')
+    {
+      char *new;
+      *strrchr (line, '\\') = '\0';
+      if (!(s = GetLine ("? ")))
+	return (NULL);
+      if (!(new = Xmalloc (strlen (line) + strlen (s) + 2)))
+	{
+	  fprintf (stderr, "Unable to allocate memory for the line\n");
+	  abort ();
+	}
+      strcpy (new, line);
+      strcat (new, "\n");
+      strcat (new, s);
+      Xfree (line);
+      line = new;
+    }
+  return (line);
+}
Index: /indexers/branches/3.03a/mg/src/text/read_line.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/read_line.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/read_line.h	(revision 14757)
@@ -0,0 +1,34 @@
+/**************************************************************************
+ *
+ * read_line.h -- Input line reading routines for mgquery
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#ifndef READ_LINE_H
+#define READ_LINE_H
+
+#define MAXLINEBUFFERLEN  65535
+
+void Init_ReadLine (void);
+void WritePrompt (void);
+char *GetMultiLine (void);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/stem_search.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/stem_search.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/stem_search.c	(revision 14757)
@@ -0,0 +1,775 @@
+/**************************************************************************
+ *
+ * stem_search.c -- Functions for searching the blocked stemmed dictionary
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "messages.h"
+#include "filestats.h"
+#include "timing.h"
+#include "local_strings.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg.h"
+#include "invf.h"
+#include "text.h"
+#include "lists.h"
+#include "backend.h"
+#include "words.h"
+#include "locallib.h"
+#include "stem_search.h"
+#include "mg_errors.h"
+#include "term_lists.h"
+#include "stemmer.h"
+
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:22  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.3  1999/07/02 00:18:55  rjmcnab
+   Changed so FindWords could be used in new ways.
+
+   Revision 1.2  1998/11/25 07:55:51  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:39  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:57:04  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:42:08  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+
+stemmed_dict *
+ReadStemDictBlk (File * stem_file)
+{
+  unsigned long i;
+  stemmed_dict *sd;
+  u_char *buffer;
+
+  if (!(sd = Xmalloc (sizeof (stemmed_dict))))
+    {
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  sd->stem_file = stem_file;
+  sd->MemForStemDict = 0;
+
+  Fread (&sd->sdh, sizeof (sd->sdh), 1, stem_file);
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(sd->sdh.lookback);
+  NTOHUL(sd->sdh.block_size);
+  NTOHUL(sd->sdh.num_blocks);
+  NTOHUL(sd->sdh.blocks_start);
+  NTOHUL(sd->sdh.index_chars);
+  NTOHUL(sd->sdh.num_of_docs);
+  NTOHUL(sd->sdh.static_num_of_docs);
+  NTOHUL(sd->sdh.num_of_words);
+  NTOHUL(sd->sdh.stem_method);
+  NTOHUL(sd->sdh.indexed);
+
+  if (!(buffer = Xmalloc (sd->sdh.index_chars)))
+    {
+      Xfree (sd);
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    };
+  sd->MemForStemDict += sd->sdh.index_chars;
+
+  if (!(sd->index = Xmalloc (sd->sdh.num_blocks * sizeof (*sd->index))))
+    {
+      Xfree (sd);
+      Xfree (buffer);
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    };
+  sd->MemForStemDict += sd->sdh.num_blocks * sizeof (*sd->index);
+
+  if (!(sd->pos = Xmalloc (sd->sdh.num_blocks * sizeof (*sd->pos))))
+    {
+      Xfree (sd);
+      Xfree (buffer);
+      Xfree (sd->index);
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    };
+  sd->MemForStemDict += sd->sdh.num_blocks * sizeof (*sd->pos);
+
+  if (!(sd->buffer = Xmalloc (sd->sdh.block_size * sizeof (*sd->buffer))))
+    {
+      Xfree (sd);
+      Xfree (buffer);
+      Xfree (sd->index);
+      Xfree (sd->buffer);
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    };
+  sd->MemForStemDict += sd->sdh.block_size * sizeof (*sd->buffer);
+
+  sd->active = -1;
+
+  for (i = 0; i < sd->sdh.num_blocks; i++)
+    {
+      register u_char len;
+      sd->index[i] = buffer;
+      len = Getc (stem_file);
+      *buffer++ = len;
+      Fread (buffer, sizeof (u_char), len, stem_file);
+      buffer += len;
+      Fread (&sd->pos[i], sizeof (*sd->pos), 1, stem_file);
+      NTOHUL(sd->pos[i]); /* [RPAP - Jan 97: Endian Ordering] */
+    }
+
+  mg_errno = MG_NOERROR;
+
+  /*  fprintf (stderr, "mem for stem dict = %i\n", sd->MemForStemDict); */
+
+  return sd;
+}
+
+
+/* [RPAP - Jan 97: Stem Index Change] */
+stemmed_idx *
+ReadStemIdxBlk (File * stem_idx_file)
+{
+  unsigned long i;
+  stemmed_idx *si;
+  u_char *buffer;
+
+  if (!(si = Xmalloc (sizeof (stemmed_idx))))
+    {
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  si->stem_idx_file = stem_idx_file;
+  si->MemForStemIdx = 0;
+
+  Fread (&si->sih, sizeof (si->sih), 1, stem_idx_file);
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(si->sih.lookback);
+  NTOHUL(si->sih.block_size);
+  NTOHUL(si->sih.num_blocks);
+  NTOHUL(si->sih.blocks_start);
+  NTOHUL(si->sih.index_chars);
+  NTOHUL(si->sih.num_of_words);
+
+  if (!(buffer = Xmalloc (si->sih.index_chars)))
+    {
+      Xfree (si);
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    };
+  si->MemForStemIdx += si->sih.index_chars;
+
+  if (!(si->index = Xmalloc (si->sih.num_blocks * sizeof (*si->index))))
+    {
+      Xfree (si);
+      Xfree (buffer);
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    };
+  si->MemForStemIdx += si->sih.num_blocks * sizeof (*si->index);
+
+  if (!(si->pos = Xmalloc (si->sih.num_blocks * sizeof (*si->pos))))
+    {
+      Xfree (si->index);
+      Xfree (si);
+      Xfree (buffer);
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    };
+  si->MemForStemIdx += si->sih.num_blocks * sizeof (*si->pos);
+
+  if (!(si->buffer = Xmalloc (si->sih.block_size * sizeof (*si->buffer))))
+    {
+      Xfree (buffer);
+      Xfree (si->index);
+      Xfree (si->buffer);
+      Xfree (si);
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    };
+  si->MemForStemIdx += si->sih.block_size * sizeof (*si->buffer);
+
+  si->active = -1;
+
+  for (i = 0; i < si->sih.num_blocks; i++)
+    {
+      register u_char len;
+      si->index[i] = buffer;
+      len = Getc (stem_idx_file);
+      *buffer++ = len;
+      Fread (buffer, sizeof (u_char), len, stem_idx_file);
+      buffer += len;
+      Fread (&si->pos[i], sizeof (*si->pos), 1, stem_idx_file);
+      NTOHUL(si->pos[i]);  /* [RPAP - Jan 97: Endian Ordering] */
+    }
+  mg_errno = MG_NOERROR;
+
+  /*  fprintf (stderr, "mem for stem idx = %i\n", si->MemForStemIdx); */
+
+  return si;
+}
+
+
+/* [RPAP - Jan 97: Stem Index Change] */
+/* word should be appropriately stemed */
+static int
+GetIdxBlock (stemmed_idx * si, u_char * word)
+{
+  register int lo = 0, hi = si->sih.num_blocks - 1;
+  register int mid = 0, c = 0;
+
+  while (lo <= hi)
+    {
+      mid = (lo + hi) / 2;
+      c = casecompare (word, si->index[mid]);
+      if (c < 0)
+	hi = mid - 1;
+      else if (c > 0)
+	lo = mid + 1;
+      else
+	return mid;
+    }
+  return hi < 0 ? 0 : (c < 0 ? mid - 1 : mid);
+}
+
+
+static int 
+GetBlock (stemmed_dict * sd, u_char * Word)
+{
+  register int lo = 0, hi = sd->sdh.num_blocks - 1;
+  register int mid = 0, c = 0;
+  while (lo <= hi)
+    {
+      mid = (lo + hi) / 2;
+      c = casecompare (Word, sd->index[mid]);  /* [RPAP - Jan 97: Stem Index Change] */
+      if (c < 0)
+	hi = mid - 1;
+      else if (c > 0)
+	lo = mid + 1;
+      else
+	return mid;
+    }
+  return hi < 0 ? 0 : (c < 0 ? mid - 1 : mid);
+}
+
+
+/*
+ * This function looks up a word in the stemmed dictionary, it returns -1
+ * if the word cound not be found, and 0 if it successfully finds the word.
+ * If count is non-null the ulong it is pointing to is set to the number of 
+ * occurances of the stemmed word in the collection. i.e wcnt.
+ * If doc_count is non-null the ulong it is pointing to is set to the number
+ * of documents that the word occurs in. i.e fcnt
+ * If invf_ptr is non-null the ulong it is pointing to is set to the position
+ * of the inverted file where the entry for this word start.
+ */
+int 
+FindWord (stemmed_dict * sd, u_char * Word, unsigned long *count,
+	  unsigned long *doc_count, unsigned long *invf_ptr,
+	  unsigned long *invf_len)
+{
+  register int lo, hi, mid, c;
+  register unsigned int res;
+  int block, num_indexes;
+  unsigned long *first_word, *last_invf_len;
+  unsigned short *num_words;
+  u_char *base;
+  unsigned short *index;
+  u_char prev[MAXSTEMLEN + 1];
+
+  block = GetBlock (sd, Word);
+  /* [RPAP - Jan 97: Endian Ordering] */
+  if (sd->active != sd->pos[block])
+    {
+      int i;
+
+      Fseek (sd->stem_file, sd->pos[block] + sd->sdh.blocks_start, 0);
+      Fread (sd->buffer, sd->sdh.block_size, sizeof (u_char), sd->stem_file);
+      sd->active = sd->pos[block];
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      first_word = (unsigned long *) (sd->buffer);
+      NTOHUL(*first_word);
+      last_invf_len = (unsigned long *) (first_word + 1);
+      NTOHUL(*last_invf_len);
+      num_words = (unsigned short *) (last_invf_len + 1);
+      NTOHUS(*num_words);
+      index = num_words + 1;
+      num_indexes = ((*num_words - 1) / sd->sdh.lookback) + 1;
+
+      for (i = 0; i < num_indexes; i++)
+	NTOHUS(index[i]);
+    }
+  else
+    {
+      first_word = (unsigned long *) (sd->buffer);
+      last_invf_len = (unsigned long *) (first_word + 1);
+      num_words = (unsigned short *) (last_invf_len + 1);
+      index = num_words + 1;
+      num_indexes = ((*num_words - 1) / sd->sdh.lookback) + 1;
+    }
+  base = (u_char *) (index + num_indexes);
+
+  lo = 0;
+  hi = num_indexes - 1;
+  while (lo <= hi)
+    {
+      mid = (lo + hi) / 2;
+      c = casecompare (Word, base + index[mid] + 1);  /* [RPAP - Jan 97: Stem Index Change] */
+      if (c < 0)
+	hi = mid - 1;
+      else if (c > 0)
+	lo = mid + 1;
+      else
+	{
+	  hi = mid;
+	  break;
+	}
+    }
+  if (hi < 0)
+    hi = 0;
+
+  res = hi * sd->sdh.lookback;
+  base += index[hi];
+
+  for (;;)
+    {
+      unsigned copy, suff;
+      unsigned long invfp;
+      if (res >= *num_words)
+	return (-1);
+      copy = *base++;
+      suff = *base++;
+      bcopy ((char *) base, (char *) (prev + copy + 1), suff);
+      base += suff;
+      *prev = copy + suff;
+
+      c = casecompare (Word, prev);   /* [RPAP - Jan 97: Stem Index Change] */
+      if (c < 0)
+	return (-1);
+
+      if (c == 0 && doc_count)
+	{
+	  bcopy ((char *) base, (char *) doc_count, sizeof (*doc_count));
+	  NTOHUL(*doc_count);  /* [RPAP - Jan 97: Endian Ordering] */
+	}
+      base += sizeof (*doc_count);
+
+      if (c == 0 && count)
+	{
+	  bcopy ((char *) base, (char *) count, sizeof (*count));
+	  NTOHUL(*count);  /* [RPAP - Jan 97: Endian Ordering] */
+	}
+      base += sizeof (*count);
+
+      if (c == 0 && invf_ptr)
+	{
+	  bcopy ((char *) base, (char *) &invfp, sizeof (invf_ptr));
+	  NTOHUL(invfp);  /* [RPAP - Jan 97: Endian Ordering] */
+	  *invf_ptr = invfp;
+	}
+      base += sizeof (*invf_ptr);
+
+      if (c == 0)
+	{
+	  /* Calculate invf_len is necessary */
+	  unsigned long next_invfp;
+	  if (!invf_len)
+	    return (*first_word + res);
+
+	  /* If the current word is the last word of the block the get the 
+	     length from last_invf_len */
+	  if (res == *num_words - 1)
+	    {
+	      *invf_len = *last_invf_len;
+	      return (*first_word + res);
+	    }
+
+	  /* Skip over most of the next word to get to the invf_ptr */
+	  base++;
+	  suff = *base++;
+	  base += suff + sizeof (unsigned long) * 2;
+	  bcopy ((char *) base, (char *) &next_invfp, sizeof (next_invfp));
+	  NTOHUL(next_invfp);  /* [RPAP - Jan 97: Endian Ordering] */
+	  *invf_len = next_invfp - invfp;
+	  return (*first_word + res);
+	}
+      res++;
+    }
+}
+
+
+/* [RPAP - Jan 97: Stem Index Change] */
+int 
+FindWords (stemmed_dict * sd, u_char * sWord, int stem_method, TermList ** tl)
+{
+  register unsigned int res;
+  unsigned int idx_res;
+  unsigned copy, suff;
+  int j, k;
+
+  int block, num_indexes;
+  unsigned long *first_word, *last_invf_len;
+  unsigned short *num_words;
+  u_char *base;
+  unsigned short *index;
+  u_char prev[MAXSTEMLEN + 1];
+
+  int idx_block, idx_num_indexes;
+  unsigned long *idx_first_word;
+  unsigned short *idx_num_words;
+  u_char *idx_base;
+  unsigned short *idx_index;
+  u_char idx_prev[MAXSTEMLEN + 1];
+
+  unsigned int num_entries, num_cases;
+  unsigned short blk_index, offset;
+  stemmed_idx * si = NULL;
+
+  /* handle stem_method 0 seperately */
+  if (stem_method == 0) {
+    TermEntry te;
+    if ((te.WE.word_num = FindWord (sd, sWord, &te.WE.count, &te.WE.doc_count,
+				   &te.WE.invf_ptr, &te.WE.invf_len)) != -1) {
+      te.WE.max_doc_count = te.WE.doc_count;
+
+      te.Count = 1;
+      te.Word = copy_string (sWord);
+      if (!te.Word)
+	FatalError (1, "Could NOT create memory to add term");
+      te.Stem = copy_string (sWord);
+      if (!te.Stem)
+	FatalError (1, "Could NOT create memory to add term");
+      /*      te.query_mask = NULL;*/
+      
+      AddTermEntry (tl, &te);
+      return (*tl)->num;
+      
+    } else {
+      /* didn't match */
+      return 0;
+    }
+  }
+  
+  if (stem_method == 1)
+    si = sd->stem1;
+  else if (stem_method == 2)
+    si = sd->stem2;
+  else
+    si = sd->stem3;
+
+  /* Locate block */
+  idx_block = GetIdxBlock (si, sWord);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  if (si->active != si->pos[idx_block])
+    {
+      Fseek (si->stem_idx_file, si->pos[idx_block] + si->sih.blocks_start, 0);
+      Fread (si->buffer, si->sih.block_size, sizeof (u_char), si->stem_idx_file);
+      si->active = si->pos[idx_block];
+
+      idx_first_word = (unsigned long *) (si->buffer);
+      NTOHUL(*idx_first_word);  /* [RPAP - Jan 97: Endian Ordering] */
+      idx_num_words = (unsigned short *) (idx_first_word + 1);
+      NTOHUS(*idx_num_words);  /* [RPAP - Jan 97: Endian Ordering] */
+      idx_index = idx_num_words + 1;
+      idx_num_indexes = ((*idx_num_words - 1) / si->sih.lookback) + 1;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (j = 0; j < idx_num_indexes; j++)
+	NTOHUS(idx_index[j]);
+    }
+  else
+    {
+      idx_first_word = (unsigned long *) (si->buffer);
+      idx_num_words = (unsigned short *) (idx_first_word + 1);
+      idx_index = idx_num_words + 1;
+      idx_num_indexes = ((*idx_num_words - 1) / si->sih.lookback) + 1;
+    }
+  idx_base = (u_char *) (idx_index + idx_num_indexes);
+  
+  {
+    /* Locate 3-in-4 block */
+    register int lo, hi, mid, c;
+    lo = 0;
+    hi = idx_num_indexes - 1;
+    while (lo <= hi)
+      {
+	mid = (lo + hi) / 2;
+	c = casecompare (sWord, idx_base + idx_index[mid] + 1);
+	if (c < 0)
+	  hi = mid - 1;
+	else if (c > 0)
+	  lo = mid + 1;
+	else
+	  {
+	    hi = mid;
+	    break;
+	  }
+      }
+    if (hi < 0)
+      hi = 0;
+
+    idx_res = hi * si->sih.lookback;
+    idx_base += idx_index[hi];
+  }
+
+  /* Locate actual word entry */
+  for (;;)
+    {
+      int c;
+      if (idx_res >= *idx_num_words)
+	return (-1);
+      copy = *idx_base++;
+      suff = *idx_base++;
+      bcopy ((char *) idx_base, (char *) (idx_prev + copy + 1), suff);
+      idx_base += suff;
+      *idx_prev = copy + suff;
+
+      c = casecompare (sWord, idx_prev);
+      if (c < 0)
+	return (-1);
+     
+      bcopy ((char *) idx_base, (char *) &num_entries, sizeof (num_entries));
+      NTOHUI(num_entries);  /* [RPAP - Jan 97: Endian Ordering] */
+      idx_base += sizeof (num_entries);
+      
+      if (c > 0)
+	idx_base += num_entries * (sizeof (num_cases) + sizeof (block) + 
+				   sizeof (blk_index) + sizeof (offset));
+
+      else
+	break;
+
+      idx_res++;
+    }
+
+  for (k = 0; k < num_entries; k++)
+    {
+      unsigned copy, suff;
+      unsigned long invfp;
+      /* Read next stem index pos */
+      bcopy ((char *) idx_base, (char *) &num_cases, sizeof (num_cases));
+      NTOHUI(num_cases);  /* [RPAP - Jan 97: Endian Ordering] */
+      idx_base += sizeof (num_cases);
+      bcopy ((char *) idx_base, (char *) &block, sizeof (block));
+      NTOHUI(block);  /* [RPAP - Jan 97: Endian Ordering] */
+      idx_base += sizeof (block);
+      bcopy ((char *) idx_base, (char *) &blk_index, sizeof (blk_index));
+      NTOHUS(blk_index);  /* [RPAP - Jan 97: Endian Ordering] */
+      idx_base += sizeof (blk_index);
+      bcopy ((char *) idx_base, (char *) &offset, sizeof (offset));
+      NTOHUS(offset);  /* [RPAP - Jan 97: Endian Ordering] */
+      idx_base += sizeof (offset);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      if (sd->active != sd->pos[block])
+	{
+	  Fseek (sd->stem_file, sd->pos[block] + sd->sdh.blocks_start, 0);
+	  Fread (sd->buffer, sd->sdh.block_size, sizeof (u_char), sd->stem_file);
+	  sd->active = sd->pos[block];
+
+	  first_word = (unsigned long *) (sd->buffer);
+	  NTOHUL(*first_word);  /* [RPAP - Jan 97: Endian Ordering] */
+	  last_invf_len = (unsigned long *) (first_word + 1);
+	  NTOHUL(*last_invf_len);  /* [RPAP - Jan 97: Endian Ordering] */
+	  num_words = (unsigned short *) (last_invf_len + 1);
+	  NTOHUS(*num_words);  /* [RPAP - Jan 97: Endian Ordering] */
+	  index = num_words + 1;
+	  num_indexes = ((*num_words - 1) / sd->sdh.lookback) + 1;
+
+	  /* [RPAP - Jan 97: Endian Ordering] */
+	  for (j = 0; j < num_indexes; j++)
+	    NTOHUS(index[j]);
+	}
+      else
+	{
+	  first_word = (unsigned long *) (sd->buffer);
+	  last_invf_len = (unsigned long *) (first_word + 1);
+	  num_words = (unsigned short *) (last_invf_len + 1);
+	  index = num_words + 1;
+	  num_indexes = ((*num_words - 1) / sd->sdh.lookback) + 1;
+	}
+      base = (u_char *) (index + num_indexes);
+      
+      res = blk_index * sd->sdh.lookback;
+      base += index[blk_index];
+      
+      for (j = 0; j < offset; j++)
+	{
+	  copy = *base++;
+	  suff = *base++;
+	  bcopy ((char *) base, (char *) (prev + copy + 1), suff);
+	  base += suff;
+	  *prev = copy + suff;
+	  base += sizeof (unsigned long);   /* skip doc_count */
+	  base += sizeof (unsigned long);   /* skip count */
+	  base += sizeof (unsigned long);   /* skip invf_ptr */
+	  res++;
+	}
+
+      for (j = 0; j < num_cases; j++)
+	{
+	  TermEntry te;
+	  
+	  if (res >= *num_words)
+	    return (-1);
+	  copy = *base++;
+	  suff = *base++;
+	  bcopy ((char *) base, (char *) (prev + copy + 1), suff);
+	  base += suff;
+	  *prev = copy + suff;
+	      
+	  te.Word = copy_string (prev);
+	  if (!te.Word)
+	    FatalError (1, "Could NOT create memory to add term");
+	  te.Stem = copy_string (prev);
+	  if (!te.Stem)
+	    FatalError (1, "Could NOT create memory to add term");
+	  stemmer (2, sd->sdh.stemmer_num, te.Stem);
+
+	  te.Count = 1;
+	  te.WE.word_num = *first_word + res;
+	  bcopy ((char *) base, (char *) &te.WE.doc_count, sizeof (te.WE.doc_count));
+	  NTOHUL(te.WE.doc_count);  /* [RPAP - Jan 97: Endian Ordering] */
+	  te.WE.max_doc_count = te.WE.doc_count;
+	  base += sizeof (te.WE.doc_count);
+	      
+	  bcopy ((char *) base, (char *) &te.WE.count, sizeof (te.WE.count));
+	  NTOHUL(te.WE.count);
+	  base += sizeof (te.WE.count);
+	      
+	  bcopy ((char *) base, (char *) &invfp, sizeof (te.WE.invf_ptr));
+	  NTOHUL(invfp);  /* [RPAP - Jan 97: Endian Ordering] */
+	  te.WE.invf_ptr = invfp;
+	  base += sizeof (te.WE.invf_ptr);
+		
+	  /* If the current word is the last word of the block the get the 
+	     length from last_invf_len */
+	  if (res == *num_words - 1)
+	    te.WE.invf_len = *last_invf_len;
+	  else
+	    {
+	      unsigned long next_invfp;
+	      u_char *oldbase = base;
+		  
+	      /* Skip over most of the next word to get to the invf_ptr */
+	      base++;
+	      suff = *base++;
+	      base += suff + sizeof (unsigned long) * 2;
+	      bcopy ((char *) base, (char *) &next_invfp, sizeof (next_invfp));
+	      NTOHUL(next_invfp);  /* [RPAP - Jan 97: Endian Ordering] */
+	      te.WE.invf_len = next_invfp - invfp;
+	      base = oldbase;
+	    }
+	      
+	  /* Add term entry to term list */
+	  /*	  te.query_mask = NULL;*/
+	  AddTermEntry (tl, &te);
+	      
+	  if (res == *num_words - 1 && j + 1 < num_cases)
+	    {
+	      int ii;
+	      /* Read in next block */
+	      block++;
+	      Fseek (sd->stem_file, sd->pos[block] + sd->sdh.blocks_start, 0);
+	      Fread (sd->buffer, sd->sdh.block_size, sizeof (u_char), sd->stem_file);
+	      sd->active = sd->pos[block];
+
+	      first_word = (unsigned long *) (sd->buffer);
+	      NTOHUL(*first_word);  /* [RPAP - Jan 97: Endian Ordering] */
+	      last_invf_len = (unsigned long *) (first_word + 1);
+	      NTOHUL(*last_invf_len);  /* [RPAP - Jan 97: Endian Ordering] */
+	      num_words = (unsigned short *) (last_invf_len + 1);
+	      NTOHUS(*num_words);  /* [RPAP - Jan 97: Endian Ordering] */
+	      index = num_words + 1;
+	      num_indexes = ((*num_words - 1) / sd->sdh.lookback) + 1;
+
+	      /* [RPAP - Jan 97: Endian Ordering] */
+	      for (ii = 0; ii < num_indexes; ii++)
+		NTOHUS(index[ii]);
+
+	      base = (u_char *) (index + num_indexes);
+	      base += index[0];
+	      res = 0;
+	      blk_index = 0;
+	    }
+	  else
+	    res++;
+	} /* end for num_cases */
+    } /* end for num_entries */
+  return (*tl)->num;
+}
+
+
+void 
+FreeStemDict (stemmed_dict * sd)
+{
+  /* [RPAP - Jan 97: Stem Index Change] */
+  if (sd->stem1)
+    FreeStemIdx (sd->stem1);
+  if (sd->stem2)
+    FreeStemIdx (sd->stem2);
+  if (sd->stem3)
+    FreeStemIdx (sd->stem3);
+
+  Xfree (sd->index[0]);
+  Xfree (sd->index);
+  Xfree (sd->buffer);
+  Xfree (sd->pos);
+  Xfree (sd);
+}
+
+/* [RPAP - Jan 97: Stem Index Change] */
+void
+FreeStemIdx (stemmed_idx * si)
+{
+  Xfree (si->index[0]);
+  Xfree (si->index);
+  Xfree (si->buffer);
+  Xfree (si->pos);
+  Xfree (si);
+}
Index: /indexers/branches/3.03a/mg/src/text/stem_search.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/stem_search.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/stem_search.h	(revision 14757)
@@ -0,0 +1,43 @@
+/**************************************************************************
+ *
+ * stem_search.h -- Functions for searching the blocked stemmed dictionary
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef H_STEM_SEARCH
+#define H_STEM_SEARCH
+
+stemmed_dict *ReadStemDictBlk (File * stem_file);
+
+stemmed_idx *ReadStemIdxBlk (File * stem_idx_file);
+
+int FindWord (stemmed_dict * sd, u_char * Word, unsigned long *count,
+	      unsigned long *doc_count, unsigned long *invf_ptr,
+	      unsigned long *invf_len);
+
+/* [RPAP - Jan 97: Stem Index Change] */
+int FindWords (stemmed_dict * sd, u_char * sWord, int stem_method, TermList ** tl);
+
+void FreeStemDict (stemmed_dict * sd);
+
+/* [RPAP - Jan 97: Stem Index Change] */
+void FreeStemIdx (stemmed_idx * si);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/stemmer.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/stemmer.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/stemmer.c	(revision 14757)
@@ -0,0 +1,148 @@
+/**************************************************************************
+ *
+ * stemmer.c -- The stemmer/case folder
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "stemmer.h"
+
+#include "lovinstem.h"
+#include "simplefrenchstem.h"
+#include "unitool.h"
+
+/*
+   $Log$
+   Revision 1.2  2004/06/22 04:17:06  kjdon
+   make stemmerdescription a const
+
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:23  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.3  1998/12/17 09:12:54  rjmcnab
+
+   Altered mg to process utf-8 encoded Unicode. The main changes
+   are in the parsing of the input, the casefolding, and the stemming.
+
+   Revision 1.2  1998/11/25 07:55:51  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:42  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:57:05  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:42:10  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+
+#define LOVINSTEMMER        0
+#define SIMPLEFRENCHSTEMMER 1
+
+
+/* decode the utf-8 encoded unicode, casefold and then recode 
+ * making sure the final length doesn't exceed the original
+ * length */
+static void unicode_casefold (u_char *word) {
+  unsigned short out[256]; /* temp space */
+  int i;
+  int len;
+
+  /* decode */
+  utf8_word_to_unicode (word, out, 255);
+  len = out[0];
+
+  /* casefold and simplify-fold */
+  for (i=0; i<len; i++) {
+    out[i+1] = unicode_tosimplified(unicode_tolower(out[i+1]));
+  }
+
+  /* re-code */
+  unicode_to_utf8_word (out, word, word[0]+1);
+}
+
+
+int stemmernumber (const u_char *stemmerdescription) {
+  u_char descript[MAX_STEM_DESCRIPTION_LEN];
+  int i;
+
+  /* copy and case-fold the description */
+  for (i=0; (stemmerdescription[i] != '\0') && 
+	 (i < MAX_STEM_DESCRIPTION_LEN-1); i++)
+    descript[i] = tolower (stemmerdescription[i]);
+  descript[i] = '\0';
+
+  /* map the description to its number */
+
+  if ((strcmp (descript, "0") == 0) ||
+      (strcmp (descript, "english") == 0) ||
+      (strcmp (descript, "lovin") == 0))
+    return LOVINSTEMMER;
+
+  if ((strcmp (descript, "1") == 1) ||
+      (strcmp (descript, "french") == 0) ||
+      (strcmp (descript, "simplefrench") == 0))
+    return SIMPLEFRENCHSTEMMER;
+
+  return -1;
+}
+
+
+
+/*
+ * Method 0 - Do not stem or case fold.
+ * Method 1 - Case fold.
+ * Method 2 - Stem.
+ * Method 3 - Case fold and stem.
+ *
+ * The stemmer number should be obtained using
+ * the stemmernumber function above.
+ */
+void 
+stemmer (int method, int stemmer, u_char *word) {
+  if (method & 1) {
+    unicode_casefold (word);
+  }
+
+  if (method & 2) {
+    switch (stemmer) {
+    case LOVINSTEMMER: lovinstem (word);
+      break;
+    case SIMPLEFRENCHSTEMMER: simplefrenchstem (word);
+      break;
+    }
+  }
+}
Index: /indexers/branches/3.03a/mg/src/text/stemmer.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/stemmer.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/stemmer.h	(revision 14757)
@@ -0,0 +1,64 @@
+/**************************************************************************
+ *
+ * stemmer.h -- The stemmer/case folder
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef STEMMER_H
+#define STEMMER_H
+
+#include "sysfuncs.h"
+
+#define STEMMER_MASK 3
+#define MAX_STEM_DESCRIPTION_LEN 16
+
+/* stemmernumber will return the stemmer for
+ * a description of the stemmer. Stemmer descriptions
+ * are not case sensitive. Valid descriptions are:
+ *
+ *   'English'
+ *   'Lovin'
+ *   'French'
+ *   'SimpleFrench'
+ *
+ * More than one description might result in the same
+ * stemmer number (for example, for stemming 'English'
+ * we currently use the 'Lovin' stemmer).
+ *
+ * stemmerdescription is a normal C, null-terminated,
+ * string.
+ *
+ * stemmernumber will return -1 if it doesn't know the
+ * stemmer description.
+ */
+int stemmernumber (const u_char *stemmerdescription);
+
+/*
+ * Method 0 - Do not stem or case fold.
+ * Method 1 - Case fold.
+ * Method 2 - Stem.
+ * Method 3 - Case fold and stem.
+ *
+ * The stemmer number should be obtained using function
+ * stemmernumber above.
+ */
+void stemmer (int method, int stemmer, u_char * word);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/term_lists.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/term_lists.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/term_lists.c	(revision 14757)
@@ -0,0 +1,334 @@
+/**************************************************************************
+ *
+ * filename -- description
+ * Copyright (C) 1994  Authors
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:24  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:52  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:43  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.1  1994/10/20  03:57:07  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "local_strings.h"
+#include "term_lists.h"
+#include "messages.h"
+#include "stemmer.h"
+
+TermList *query_term_list = NULL;
+
+/* =========================================================================
+ * Function: MakeTermList
+ * Description:
+ * Input:
+ * Output:
+ * ========================================================================= */
+TermList *
+MakeTermList (int n)
+{
+  TermList *t;
+  int list_size = (n == 0 ? 1 : n);	/* always allocate at least one node */
+
+  t = Xmalloc (sizeof (TermList) + (list_size - 1) * sizeof (TermEntry));
+  if (!t)
+    FatalError (1, "Unable to allocate term list");
+
+  t->num = n;
+  t->list_size = list_size;
+
+  return t;
+}
+
+/* =========================================================================
+ * Function: ResizeTermList
+ * Description:
+ * Input:
+ * Output:
+ * ========================================================================= */
+
+#define GROWTH_FACTOR 2
+#define MIN_SIZE 2
+
+static void
+ResizeTermList (TermList ** term_list)
+{
+  TermList *tl = *term_list;
+
+  if (tl->num > tl->list_size)
+    {
+      if (tl->list_size)
+	tl->list_size *= GROWTH_FACTOR;
+      else
+	tl->list_size = MIN_SIZE;
+    }
+  tl = Xrealloc (tl, sizeof (TermList) + (tl->list_size - 1) * sizeof (TermEntry));
+
+  if (!tl)
+    FatalError (1, "Unable to resize term list");
+
+  *term_list = tl;
+}
+
+/* =========================================================================
+ * Function: ConvertTermsToString
+ * Description:
+ *      Convert term list into null-terminated string
+ * Input:
+ *      query_term_list = term list
+ * Output:
+ *      str = term string
+ * ========================================================================= */
+
+void
+ConvertTermsToString (TermList * query_term_list, char *str)
+{
+  int i = 0;
+  int total_len = 0;
+
+  /* terms_str should be preallocated */
+  if (!str)
+    return;
+
+  for (i = 0; i < query_term_list->num; i++)
+    {
+      unsigned char *word = query_term_list->TE[i].Word;
+      int len = word[0];
+      total_len += len + 1;	/* +1 for space */
+      if (total_len > MAXTERMSTRLEN)
+	break;
+      strncpy (str, (char *) word + 1, len);
+      str += len;
+      if (i != (query_term_list->num) - 1)
+	{
+	  *str = ' ';
+	  str++;		/* add space gap */
+	}
+
+    }
+  *str = '\0';
+}
+
+/* =========================================================================
+ * Function: ResetTermList
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+void
+ResetTermList (TermList ** tl)
+{
+  if (*tl)
+    FreeTermList (tl);
+  *tl = MakeTermList (0);
+}
+
+/* =========================================================================
+ * Function: AddTermEntry
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+int
+AddTermEntry (TermList ** query_term_list, TermEntry * te)
+{
+  TermList *tl = *query_term_list;
+
+  tl->num++;
+  ResizeTermList (query_term_list);
+  tl = *query_term_list;
+
+  /* copy the structure contents */
+  bcopy ((char *) te, (char *) &(tl->TE[tl->num - 1]), sizeof (TermEntry));
+
+  return tl->num - 1;
+}
+
+
+
+/* =========================================================================
+ * Function: AddTerm
+ * Description: Used in boolean parser - see bool_tree   [RPAP - Feb 97: Term Frequency] 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+int
+AddTerm (TermList ** query_term_list, u_char * Word, int Count, int word_num,
+	 u_long count, u_long doc_count, u_long invf_ptr, u_long invf_len, int stemmer_num)  /* [RPAP - Feb 97: Term Frequency] */
+{
+  int j;
+  TermList *tl = *query_term_list;
+
+  /* Look for the word in the already identified terms */
+  for (j = 0; j < tl->num; j++)
+    {
+      TermEntry *te = &(tl->TE[j]);
+      if (compare (te->Word, Word) == 0)
+	{
+	  te->Count++;
+	  return j;
+	}
+    }
+
+
+  {
+    /* Create a new entry in the list for the new word */
+    TermEntry te;
+
+    /* [RPAP - Feb 97: Term Frequency] */
+    te.WE.word_num = word_num;
+    te.WE.count = count;
+    te.WE.doc_count = doc_count;
+    te.WE.max_doc_count = doc_count;   /* [RPAP - Jan 97: Stem Index Change] */
+    te.WE.invf_ptr = invf_ptr;
+    te.WE.invf_len = invf_len;
+    te.Count = Count;
+    te.Word = copy_string (Word);
+    if (!te.Word)
+      FatalError (1, "Could NOT create memory to add term");
+
+    /* [RPAP - Jan 97: Stem Index Change] */
+    te.Stem = copy_string (Word);
+    if (!te.Stem)
+      FatalError (1, "Could NOT create memory to add term");
+    stemmer (2, stemmer_num, te.Stem);
+
+    te.require_match = 0;  /* [RJM - 07/97: Ranked Required Terms] */
+
+    return AddTermEntry (query_term_list, &te);
+  }
+
+}
+
+/* =========================================================================
+ * Function: FreeTermList
+ * Description:
+ * Input:
+ * Output:
+ * ========================================================================= */
+
+void
+FreeTermList (TermList ** the_tl)
+{
+  int j;
+  TermList *tl = *the_tl;
+
+  for (j = 0; j < tl->num; j++)
+    {
+      if (tl->TE[j].Word)
+	Xfree (tl->TE[j].Word);
+      /* [RPAP - Jan 97: Stem Index Change] */
+      if (tl->TE[j].Stem)
+	Xfree (tl->TE[j].Stem);
+    }
+  Xfree (tl);
+
+  *the_tl = NULL;
+}
+
+/* =========================================================================
+ * Function: PrintWordEntry
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+void
+PrintWordEntry (WordEntry * we, FILE * file)
+{
+  fprintf (file, "we->word_num = %d\n", we->word_num);
+  fprintf (file, "we->count = %ld\n", we->count);
+  fprintf (file, "we->doc_count = %ld\n", we->doc_count);
+  fprintf (file, "we->max_doc_count = %ld\n", we->max_doc_count);
+  fprintf (file, "we->invf_ptr = %ld\n", we->invf_ptr);
+  fprintf (file, "we->invf_len = %ld\n", we->invf_len);
+}
+
+/* =========================================================================
+ * Function: PrintTermEntry
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+void
+PrintTermEntry (TermEntry * te, FILE * file)
+{
+
+  fprintf (file, "Term Entry\n");
+  fprintf (file, "te->Count = %d\n", te->Count);
+  fprintf (file, "te->Word = %s\n", str255_to_string (te->Word, NULL));
+  if (te->Stem != NULL)
+    fprintf (file, "te->Stem = %s\n", str255_to_string (te->Stem, NULL));  /* [RPAP - Jan 97: Stem Index Change] */
+  fprintf (file, "te->require_match = %i\n", te->require_match);  /* [RJM 07/97: Ranked Required Terms] */
+  PrintWordEntry (&(te->WE), file);
+
+}
+
+/* =========================================================================
+ * Function: PrintTermList
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+void
+PrintTermList (TermList * tl, FILE * file)
+{
+  int i;
+
+  fprintf (file, "Term List\n");
+  fprintf (file, "tl->list_size = %d\n", tl->list_size);
+  fprintf (file, "tl->num = %d\n", tl->num);
+
+  for (i = 0; i < tl->num; i++)
+    {
+      fprintf (file, "[%d]\n", i);
+      PrintTermEntry (&(tl->TE[i]), file);
+    }
+}
Index: /indexers/branches/3.03a/mg/src/text/term_lists.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/term_lists.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/term_lists.h	(revision 14757)
@@ -0,0 +1,105 @@
+/**************************************************************************
+ *
+ * term_lists.h -- description
+ * Copyright (C) 1994  Authors
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:24  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/11/25 07:55:52  rjmcnab
+
+   Modified mg to that you can specify the stemmer you want
+   to use via a command line option. You specify it to
+   mg_passes during the build process. The number of the
+   stemmer that you used is stored within the inverted
+   dictionary header and the stemmed dictionary header so
+   the correct stemmer is used in later stages of building
+   and querying.
+
+   Revision 1.1  1998/11/17 09:35:44  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.1  1994/10/20  03:57:08  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+ */
+
+#ifndef TERM_LISTS_H
+#define TERM_LISTS_H
+
+#include "sysfuncs.h"
+
+#define MAXTERMSTRLEN 1023	/* maximum number of characters in term string */
+
+typedef struct WordEntry
+  {
+    int word_num;		/* Unique number for each different word */
+    u_long count;		/* Number of times the word occurs in the text */
+    u_long doc_count;		/* Number of documents that contain the word */
+    u_long max_doc_count;       /* [RPAP - Jan 97: Stem Index Change] */
+    u_long invf_ptr;		/* This is a byte position of the  
+				   inverted file entry corresponding to the word */
+    u_long invf_len;		/* This is the length of the inverted 
+				   file entry in bytes */
+  }
+WordEntry;
+
+typedef struct TermEntry
+  {
+    WordEntry WE;
+    int Count;			/* The number of times the word occurs in the query */
+    u_char *Word;		/* The word. */
+    u_char *Stem;               /* [RPAP - Jan 97: Stem Index Change] - The stemmed non-cf version of Word */
+    int require_match;          /* [RJM 07/97: Ranked Required Terms] 0=optional match, 1=must match */
+  }
+TermEntry;
+
+typedef struct TermList
+  {
+    int list_size;
+    int num;
+    TermEntry TE[1];
+  }
+TermList;
+
+#define GetNthWE(term_list, n) (&((term_list)->TE[(n)].WE))
+
+/* --- prototypes --- */
+void ConvertTermsToString (TermList * query_term_list, char *str);
+int AddTermEntry (TermList ** query_term_list, TermEntry * te);
+int AddTerm (TermList ** query_term_list, u_char * Word, int Count, int word_num,
+	     u_long count, u_long doc_count, u_long invf_ptr, u_long invf_len, /* [RPAP - Feb 97: Term Frequency] */
+	     int stemmer_num);  
+void ResetTermList (TermList ** tl);
+void FreeTermList (TermList ** the_tl);
+void PrintWordEntry (WordEntry * we, FILE * file);
+void PrintTermEntry (TermEntry * te, FILE * file);
+void PrintTermList (TermList * tl, FILE * file);
+TermList *MakeTermList (int n);
+
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/text.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/text.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/text.h	(revision 14757)
@@ -0,0 +1,176 @@
+/**************************************************************************
+ *
+ * text.h -- Header file for compression related stuff
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+
+#ifndef H_TEXT
+#define H_TEXT
+
+#include "huffman.h"
+
+
+
+
+
+/*****************************************************************************
+ *
+ * There are several different methods of compressing the text of the
+ * database. The following defines list the different methods of text
+ * compression
+ *
+ */
+
+
+/* The dictionary contains all the fragments that occur in the collection
+   i.e. escapes are not possible */
+#define MG_COMPLETE_DICTIONARY 0
+
+
+/* Certain words have been deleted from the dictionary. The words deleted
+   have been used to create the frequency huffman codes of the characters. 
+   This dictionary has an escape code and may be used to compress novel
+   words. This dictionary may fail if there is a novel character. */
+#define MG_PARTIAL_DICTIONARY 1
+
+
+/* This dictionary has an escape so that novel words and non-words can be 
+   coded. The method for coding the novel words and non-words is determined
+   by a dictionary parameter. */
+#define MG_SEED_DICTIONARY 2
+
+
+
+
+
+
+
+
+
+/*****************************************************************************
+ *
+ * With a seed dictionary there are several methods for coding the novel
+ * words and non-words the following defined values specify the different
+ * methods of coding.
+ *
+ */
+
+
+/* Code novel words and non-words character by character using huffman codes.
+   The huffman codes for the word and non-word lengths and characters are 
+   generated from the distribution of lengths and characters in the
+   dictionary. */
+#define MG_NOVEL_HUFFMAN_CHARS 0
+
+
+/* This method codes novel words using binary codes. The novel words are stored
+   in a auxillary dictionary which is built by pass two. */
+#define MG_NOVEL_BINARY 1
+
+
+/* This method codes novel words using delta codes. The novel words are stored
+   in a auxillary dictionary which is built by pass two. */
+#define MG_NOVEL_DELTA 2
+
+
+/* This method codes novel words using hybrid version of delta. The novel
+   words are stored in a auxillary dictionary which is built by pass two. */
+#define MG_NOVEL_HYBRID 3
+
+
+/* This method codes novel words using hybrid version of delta and a MTF
+   operation. The novel words are stored in a auxillary dictionary which
+   is built by pass two. */
+#define MG_NOVEL_HYBRID_MTF 4
+
+
+
+
+
+
+/* This specified an amount of extra space allocated in the
+   compression_dict_header for adding new parameters. As new
+   parameters are added this should be decreased. */
+#define TEXT_PARAMS 15
+
+
+
+typedef struct compression_dict_header
+  {
+    u_long dict_type;
+    u_long novel_method;
+    u_long params[TEXT_PARAMS];
+    u_long num_words[2];
+    u_long num_word_chars[2];
+    u_long lookback;
+  }
+compression_dict_header;
+
+
+typedef struct comp_frags_header
+  {
+    huff_data hd;
+    u_long uncompressed_size;
+    u_long huff_words_size[MAX_HUFFCODE_LEN + 1];
+  }
+comp_frags_header;
+
+
+
+typedef struct compressed_text_header
+  {
+    u_long num_of_docs;
+    u_long num_of_words;	/* number of words in collection */
+    double num_of_bytes; /* [RJM 07/97: 4G limit] */
+    double ratio;
+    u_long length_of_longest_doc;	/* (characters) */
+    u_long dummy;    /* added to make the structure the same on different architectures */
+  }
+compressed_text_header;
+
+
+typedef struct compression_stats_header
+  {
+    u_long num_docs;
+    u_long dummy;   /* added to make the structure the same on different architectures */
+    double num_bytes; /* [RJM 07/97: 4G limit] */
+  }
+compression_stats_header;
+
+
+typedef struct frags_stats_header
+  {
+    u_long num_frags;
+    u_long mem_for_frags;
+  }
+frags_stats_header;
+
+
+typedef struct aux_frags_header
+  {
+    u_long num_frags;
+    u_long mem_for_frags;
+  }
+aux_frags_header;
+
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/text.pass1.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/text.pass1.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/text.pass1.c	(revision 14757)
@@ -0,0 +1,405 @@
+/**************************************************************************
+ *
+ * text.pass1.c -- Text compression (Pass 1)
+ * Copyright (C) 1994  Neil Sharman, Gary Eddy and Alistair Moffat
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "messages.h"
+#include "huffman.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+
+#include "mg_files.h"
+#include "mg.h"
+#include "build.h"
+#include "locallib.h"
+#include "words.h"
+#include "text.h"
+#include "hash.h"
+#include "local_strings.h"
+/* for more meaningful messages - jrm21 (gsdl) */
+#ifdef HAVE_STRERROR
+#include <string.h>
+#include <errno.h>
+#endif
+
+#define POOL_SIZE 1024*1024
+#define INITIAL_HASH_SIZE 7927
+
+
+typedef struct hash_rec
+  {
+    unsigned long wcnt;		/* word frequency */
+    unsigned long occurance_num;
+    u_char *word;
+  }
+hash_rec;
+
+typedef struct dict_data
+  {
+    hash_rec *HashTable;
+    unsigned long HashSize;
+    unsigned long HashUsed;
+    unsigned long wordnum;
+    unsigned long words_read;
+    unsigned long bytes_diff;
+    huff_data hd;
+  }
+dict_data;
+
+
+
+static unsigned long LongestDoc = 0;
+static unsigned long occurance_num = 0;
+static dict_data DictData[2];
+
+static u_char *Pool;
+static int PoolLeft;
+static double inputbytes = 0; /* [RJM 07/97: 4G limit] */
+static unsigned long MaxMemInUse = 0;
+static unsigned long MemInUse = 0;
+static compression_stats_header csh =
+{0, 0.0}; /* [RJM 07/97: 4G limit] */
+
+
+static void 
+ChangeMem (int Change)
+{
+  MemInUse += Change;
+  if (MemInUse > MaxMemInUse)
+    MaxMemInUse = MemInUse;
+}
+
+
+
+
+int 
+init_text_1 (char *FileName)
+{
+  int which;
+  if (!(Pool = Xmalloc (POOL_SIZE)))
+    {
+      Message ("Unable to allocate memory for pool");
+      return (COMPERROR);
+    }
+  PoolLeft = POOL_SIZE;
+  ChangeMem (POOL_SIZE);
+
+  for (which = 1; which >= 0; which--)
+    {
+      u_char *word;
+      hash_rec *ent;
+      dict_data *dd = &DictData[which];
+
+      dd->wordnum = 0;
+      dd->words_read = 0;
+      dd->bytes_diff = 0;
+      dd->HashSize = INITIAL_HASH_SIZE;
+      dd->HashUsed = 0;
+      if (!(dd->HashTable = Xmalloc (sizeof (hash_rec) * dd->HashSize)))
+	{
+	  Message ("Unable to allocate memory for table");
+	  return (COMPERROR);
+	}
+      ChangeMem (sizeof (hash_rec) * dd->HashSize);
+      bzero ((char *) (dd->HashTable), sizeof (hash_rec) * dd->HashSize);
+
+      word = Pool;
+      *Pool++ = '\0';
+      PoolLeft--;
+      {
+	register u_char *wptr;
+	register int hsize = dd->HashSize;
+	register unsigned long hashval, step;
+
+	HASH (hashval, step, word, hsize);
+	wptr = (dd->HashTable + hashval)->word;
+	while (wptr)
+	  {
+	    hashval += step;
+	    if (hashval >= hsize)
+	      hashval -= hsize;
+	    wptr = (dd->HashTable + hashval)->word;
+	  }
+	ent = dd->HashTable + hashval;
+      }
+      ent->wcnt = 1;
+      ent->word = word;
+      dd->HashUsed = 1;
+    }
+  return (COMPALLOK);
+}
+
+
+
+
+int 
+process_text_1 (u_char * s_in, int l_in)
+{
+  int which;
+  u_char *end = s_in + l_in - 1;
+  if (l_in > LongestDoc)
+    LongestDoc = l_in;
+
+  csh.num_docs++;
+  csh.num_bytes += l_in;
+
+  which = inaword (s_in, end);
+  /*
+   ** Alternately parse off words and non-words from the input
+   ** stream beginning with a non-word. Each token is then
+   ** inserted into the set if it does not exist or has it's
+   ** frequency count incremented if it does.
+   */
+  for (; s_in <= end; which = !which)
+    {
+      u_char Word[MAXWORDLEN + 1];
+      dict_data *dd = &DictData[which];
+
+      /* First parse a word or non-word out of the string */
+      if (which)
+	PARSE_WORD (Word, s_in, end);
+      else
+	PARSE_NON_WORD (Word, s_in, end);
+
+      dd->wordnum++;
+      inputbytes += *Word;
+      dd->words_read++;
+
+      /* Search the hash table for Word */
+      {
+	register unsigned long hashval, step;
+	register int hsize = dd->HashSize;
+	HASH (hashval, step, Word, hsize);
+	for (;;)
+	  {
+	    register u_char *s1;
+	    register u_char *s2;
+	    register int len;
+	    register hash_rec *ent;
+	    ent = dd->HashTable + hashval;
+	    if (!ent->word)
+	      {
+		int len = *Word + 1;
+		if (len > PoolLeft)
+		  {
+		    if (!(Pool = Xmalloc (POOL_SIZE)))
+		      {
+			Message ("Unable to allocate memory for pool");
+			return (COMPERROR);
+		      }
+		    PoolLeft = POOL_SIZE;
+		    ChangeMem (POOL_SIZE);
+		  }
+		ent->occurance_num = occurance_num++;
+		ent->wcnt = 1;
+		ent->word = Pool;
+		memcpy (Pool, Word, len);
+		Pool += len;
+		PoolLeft -= len;
+		dd->HashUsed++;
+		dd->bytes_diff += Word[0];
+		break;
+	      }
+	    /* Compare the words */
+	    s1 = Word;
+	    s2 = ent->word;
+	    len = *s1 + 1;
+	    for (; len; len--)
+	      if (*s1++ != *s2++)
+		break;
+
+	    if (len)
+	      {
+		hashval = (hashval + step);
+		if (hashval >= hsize)
+		  hashval -= hsize;
+	      }
+	    else
+	      {
+		ent->wcnt++;
+		break;
+	      }
+	  }
+      }
+
+  
+      if (dd->HashUsed >= dd->HashSize >> 1)
+	{
+	  hash_rec *ht;
+	  unsigned long size;
+	  unsigned long i;
+	  size = prime (dd->HashSize * 2);
+	  if (!(ht = Xmalloc (sizeof (hash_rec) * size)))
+	    {
+	      Message ("Unable to allocate memory for table");
+	      return (COMPERROR);
+	    }
+	  ChangeMem (sizeof (hash_rec) * size);
+	  bzero ((char *) ht, sizeof (hash_rec) * size);
+
+	  for (i = 0; i < dd->HashSize; i++)
+	    if (dd->HashTable[i].word)
+	      {
+		register u_char *wptr;
+		register unsigned long hashval, step;
+
+		wptr = dd->HashTable[i].word;
+		HASH (hashval, step, wptr, size);
+		wptr = (ht + hashval)->word;
+		while (wptr)
+		  {
+		    hashval += step;
+		    if (hashval >= size)
+		      hashval -= size;
+		    wptr = (ht + hashval)->word;
+		  }
+		ht[hashval] = dd->HashTable[i];
+	      }
+	  Xfree (dd->HashTable);
+	  ChangeMem (-sizeof (hash_rec) * dd->HashSize);
+	  dd->HashTable = ht;
+	  dd->HashSize = size;
+
+
+	}
+    }
+  return (COMPALLOK);
+}				/* encode */
+
+
+
+static int 
+PackHashTable (dict_data * dd)
+{
+  int s, d;
+  for (s = d = 0; s < dd->HashSize; s++)
+    if (dd->HashTable[s].word)
+      dd->HashTable[d++] = dd->HashTable[s];
+  ChangeMem (-sizeof (hash_rec) * dd->HashSize);
+  ChangeMem (sizeof (hash_rec) * dd->HashUsed);
+  if (!(dd->HashTable = Xrealloc (dd->HashTable,
+				  sizeof (hash_rec) * dd->HashUsed)))
+    {
+      Message ("Out of memory");
+      return COMPERROR;
+    }
+  dd->HashSize = dd->HashUsed;
+  return COMPALLOK;
+}
+
+
+
+
+
+static int 
+ent_comp (const void *s1, const void *s2)
+{
+  return casecompare (((hash_rec *) s1)->word, ((hash_rec *) s2)->word);
+}
+
+
+
+static void 
+WriteHashTable (FILE * fp, dict_data * dd)
+{
+  frags_stats_header fsh;
+  u_long j = 0;
+  u_char *curr;
+
+  if (PackHashTable (dd) == COMPERROR)
+    return;
+
+  qsort (dd->HashTable, dd->HashUsed, sizeof (hash_rec), ent_comp);
+
+  fsh.num_frags = dd->HashSize;
+  fsh.mem_for_frags = dd->HashSize;
+  for (j = 0; j < dd->HashSize; j++)
+    fsh.mem_for_frags += dd->HashTable[j].word[0];
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(fsh.num_frags);
+  HTONUL(fsh.mem_for_frags);
+
+  fwrite (&fsh, sizeof (fsh), 1, fp);
+
+  for (j = 0; j < dd->HashSize; j++)
+    {
+      curr = dd->HashTable[j].word;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      HTONUL(dd->HashTable[j].wcnt);
+      HTONUL(dd->HashTable[j].occurance_num);
+
+      fwrite (&dd->HashTable[j].wcnt, sizeof (dd->HashTable[j].wcnt), 1, fp);
+      fwrite (&dd->HashTable[j].occurance_num,
+	      sizeof (dd->HashTable[j].occurance_num), 1, fp);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(dd->HashTable[j].wcnt);
+      NTOHUL(dd->HashTable[j].occurance_num);
+
+      fwrite (curr, sizeof (u_char), curr[0] + 1, fp);
+    }
+}
+
+
+int 
+done_text_1 (char *file_name)
+{
+  char *temp_str;
+  FILE *fp;
+
+  if (!(fp = create_file (file_name, TEXT_STATS_DICT_SUFFIX, "wb",
+			  MAGIC_STATS_DICT, MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      fprintf(stderr,"Couldn't create file %s%s:%s\n",
+	      file_name, TEXT_STATS_DICT_SUFFIX,
+#if defined(HAVE_STRERROR) || defined(__WIN32__)
+	      strerror(errno)
+#else
+	      " "
+#endif
+	      );
+      return COMPERROR;
+    }
+
+  temp_str = msg_prefix;
+  msg_prefix = "text.pass1";
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(csh.num_docs);
+  HTOND(csh.num_bytes); /* [RJM 07/97: 4G limit] */
+
+  fwrite (&csh, sizeof (csh), 1, fp);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(csh.num_docs);
+  NTOHD(csh.num_bytes); /* [RJM 07/97: 4G limit] */
+
+  WriteHashTable (fp, &DictData[0]);
+  WriteHashTable (fp, &DictData[1]);
+  msg_prefix = temp_str;
+  fclose(fp);
+  return COMPALLOK;
+}				/* done_encode */
Index: /indexers/branches/3.03a/mg/src/text/text.pass2.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/text.pass2.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/text.pass2.c	(revision 14757)
@@ -0,0 +1,791 @@
+/**************************************************************************
+ *
+ * text.pass2.c -- Text compression (Pass 2)
+ * Copyright (C) 1994  Neil Sharman, Gary Eddy and Alistair Moffat
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "messages.h"
+#include "local_strings.h"
+#include "bitio_m_mem.h"
+#include "bitio_m.h"
+#include "huffman.h"
+#include "bitio_stdio.h"
+#include "huffman_stdio.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg.h"
+#include "mg_files.h"
+#include "build.h"
+#include "words.h"
+#include "text.h"
+#include "hash.h"
+#include "locallib.h"
+#include "comp_dict.h"
+
+
+
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.2  2002/01/22 02:41:14  jrm21
+   Try to print out an error if the aux file couldn't be written to.
+
+   Revision 1.1  1999/08/10 21:18:25  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.2  1998/12/17 09:12:54  rjmcnab
+
+   Altered mg to process utf-8 encoded Unicode. The main changes
+   are in the parsing of the input, the casefolding, and the stemming.
+
+   Revision 1.1  1998/11/17 09:35:47  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:57:10  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:42:14  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+#define POOL_SIZE 1024*256
+
+typedef struct char_pool
+  {
+    struct char_pool *next;
+    u_long left;
+    u_char *ptr;
+    u_char pool[POOL_SIZE];
+  }
+char_pool;
+
+typedef struct novel_hash_rec
+  {
+    u_long ordinal_num;
+    u_char *word;
+  }
+novel_hash_rec;
+
+
+#define INITIAL_HASH_SIZE 7927
+#define MAX_SWAPS 10000
+
+typedef struct novel_hash_table
+  {
+    novel_hash_rec *HashTable;
+    u_long HashSize, HashUsed;
+    char_pool *first_pool;
+    char_pool *pool;
+    u_long next_num, binary_start;
+    novel_hash_rec **code_to_nhr;
+  }
+novel_hash_table;
+
+
+static FILE *text, *text_idx;
+
+static u_char *comp_buffer;
+
+static u_long text_length;
+
+/* [RJM 07/97: 4G limit] */
+static double stats_in_tot_bytes = 0.0;
+static double stats_in_bytes = 0.0;
+static double stats_out_bytes = 0.0;
+
+
+static novel_hash_table nht[2];
+
+static u_long prefix_len = 0;
+
+int blk_start[2][33], blk_end[2][33];
+
+
+static char_pool *
+new_pool (char_pool * pool)
+{
+  char_pool *p = Xmalloc (sizeof (char_pool));
+  if (!p)
+    FatalError (1, "Unable to allocate memory for pool");
+  if (pool)
+    pool->next = p;
+  p->next = NULL;
+  p->left = POOL_SIZE;
+  p->ptr = p->pool;
+  return p;
+}
+
+
+
+int 
+init_text_2 (char *file_name)
+{
+  char path[512];
+  int i;
+
+  if (LoadCompressionDictionary (make_name (file_name, TEXT_DICT_SUFFIX,
+					    path)) == COMPERROR)
+    return COMPERROR;
+
+  if (!(text = create_file (file_name, TEXT_SUFFIX, "w+b",
+			    MAGIC_TEXT, MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return COMPERROR;
+
+  bzero ((char *) &cth, sizeof (cth));
+
+  if (fwrite (&cth, sizeof (cth), 1, text) != 1)
+    return COMPERROR;
+
+  text_length = sizeof (u_long) + sizeof (cth);
+
+  if (!(text_idx = create_file (file_name, TEXT_IDX_SUFFIX, "w+b",
+				MAGIC_TEXI, MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return COMPERROR;
+
+  if (fwrite (&cth, sizeof (cth), 1, text_idx) != 1)
+    return COMPERROR;
+
+  if (!(comp_buffer = Xmalloc (sizeof (u_char) * buf_size)))
+    {
+      Message ("No memory for compression buffer");
+      return (COMPERROR);
+    }
+
+#if 0
+  MaxMemInUse += sizeof (u_char) * buf_size;
+#endif
+
+  if (cdh.novel_method != MG_NOVEL_HUFFMAN_CHARS)
+    for (i = 0; i <= 1; i++)
+      {
+	nht[i].HashSize = INITIAL_HASH_SIZE;
+	nht[i].HashTable = Xmalloc (sizeof (novel_hash_rec) * nht[i].HashSize);
+	bzero ((char *) nht[i].HashTable,
+	       sizeof (novel_hash_rec) * nht[i].HashSize);
+	nht[i].HashUsed = 0;
+	nht[i].HashSize = INITIAL_HASH_SIZE;
+	nht[i].pool = nht[i].first_pool = new_pool (NULL);
+	nht[i].next_num = 1;
+	nht[i].binary_start = 1;
+	if (cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+	  nht[i].code_to_nhr = Xmalloc (sizeof (novel_hash_rec *) *
+					((nht[i].HashSize >> 1) + 2));
+	else
+	  nht[i].code_to_nhr = NULL;
+	if (cdh.novel_method == MG_NOVEL_HYBRID ||
+	    cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+	  {
+	    int num;
+	    num = 1;
+	    blk_start[i][0] = 0;
+	    blk_end[i][0] = cdh.num_words[i] - 1;
+	    while (num < 33)
+	      {
+		blk_start[i][num] = blk_end[i][num - 1] + 1;
+		blk_end[i][num] = blk_start[i][num] +
+		  (blk_end[i][num - 1] - blk_start[i][num - 1]) * 2;
+		num++;
+	      }
+	  }
+      }
+
+  return (COMPALLOK);
+}
+
+
+
+int 
+ic (void *a, void *b)
+{
+  return *((int *) a) - *((int *) b);
+}
+
+
+
+/* #define DOCDUMP 477 */
+
+int 
+process_text_2 (u_char * s_in, int l_in)
+{
+  int which, byte_length;
+  u_char *end = s_in + l_in - 1;
+  int novels_used[2];
+  int swaps[2][MAX_SWAPS];
+
+  which = inaword (s_in, end);
+
+  ENCODE_START (comp_buffer, buf_size)
+
+    ENCODE_BIT (which);
+
+  if (cdh.novel_method == MG_NOVEL_BINARY)
+    {
+      DELTA_ENCODE_L (nht[0].binary_start, prefix_len);
+      DELTA_ENCODE_L (nht[1].binary_start, prefix_len);
+    }
+
+  novels_used[0] = novels_used[1] = 0;
+
+#ifdef DOCDUMP
+  if (cth.num_of_docs == DOCDUMP)
+    {
+      printf ("---------------------------------------------------\n");
+      printf ("which = %d\n", which);
+    }
+#endif
+
+  for (; s_in <= end; which = !which)
+    {
+      u_char Word[MAXWORDLEN + 1];
+      int res;
+
+      if (which)
+	cth.num_of_words++;
+
+      /* First parse a word or non-word out of the string */
+      if (which)
+	PARSE_WORD (Word, s_in, end);
+      else
+	PARSE_NON_WORD (Word, s_in, end);
+
+#ifdef DOCDUMP
+      if (cth.num_of_docs == DOCDUMP)
+	{
+	  printf ("%sword : \"%.*s\"", which ? "    " : "non-", Word[0], Word + 1);
+	}
+#endif
+
+      /* Search the hash table for Word */
+      if (ht[which])
+	{
+	  register unsigned long hashval, step;
+	  register int tsize = ht[which]->size;
+	  register u_char **wptr;
+	  HASH (hashval, step, Word, tsize);
+	  for (;;)
+	    {
+	      register u_char *s1;
+	      register u_char *s2;
+	      register int len;
+	      wptr = ht[which]->table[hashval];
+	      if (wptr == NULL)
+		{
+		  res = COMPERROR;
+		  break;
+		}
+
+	      /* Compare the words */
+	      s1 = Word;
+	      s2 = *wptr;
+	      len = *s1 + 1;
+	      for (; len; len--)
+		if (*s1++ != *s2++)
+		  break;
+
+	      if (len)
+		{
+		  hashval += step;
+		  if (hashval >= tsize)
+		    hashval -= tsize;
+		}
+	      else
+		{
+		  res = ht[which]->table[hashval] - ht[which]->words;
+		  break;
+		}
+	    }
+	}
+      else
+	res = COMPERROR;
+      /* Check that the word was found in the dictionary */
+      if (res == COMPERROR)
+	{
+	  if (cdh.dict_type == MG_COMPLETE_DICTIONARY)
+	    {
+	      Message ("Unknown word \"%.*s\"\n", *Word, Word + 1);
+	      return (COMPERROR);
+	    }
+	  if (cdh.dict_type == MG_PARTIAL_DICTIONARY)
+	    {
+	      u_long i;
+	      if (ht[which])
+		{
+		  res = ht[which]->hd->num_codes - 1;
+		  HUFF_ENCODE (res, ht[which]->codes, ht[which]->hd->clens);
+		}
+	      HUFF_ENCODE (Word[0], lens_codes[which], lens_huff[which].clens);
+	      for (i = 0; i < Word[0]; i++)
+		HUFF_ENCODE (Word[i + 1], char_codes[which],
+			     char_huff[which].clens);
+	    }
+	  if (cdh.dict_type == MG_SEED_DICTIONARY)
+	    {
+	      if (ht[which])
+		{
+		  res = ht[which]->hd->num_codes - 1;
+		  HUFF_ENCODE (res, ht[which]->codes, ht[which]->hd->clens);
+		}
+	      switch (cdh.novel_method)
+		{
+		case MG_NOVEL_HUFFMAN_CHARS:
+		  {
+		    u_long i;
+		    HUFF_ENCODE (Word[0], lens_codes[which],
+				 lens_huff[which].clens);
+		    for (i = 0; i < Word[0]; i++)
+		      HUFF_ENCODE (Word[i + 1], char_codes[which],
+				   char_huff[which].clens);
+		  }
+		  break;
+		case MG_NOVEL_BINARY:
+		case MG_NOVEL_DELTA:
+		case MG_NOVEL_HYBRID:
+		case MG_NOVEL_HYBRID_MTF:
+		  {
+		    register unsigned long hashval, step;
+		    register novel_hash_table *h = &nht[which];
+		    register int hsize = h->HashSize;
+		    register novel_hash_rec *ent;
+		    HASH (hashval, step, Word, hsize);
+		    for (;;)
+		      {
+			register u_char *s1, *s2;
+			register int len;
+			ent = h->HashTable + hashval;
+			if (!ent->word)
+			  {
+			    int len = *Word + 1;
+			    if (len > h->pool->left)
+			      h->pool = new_pool (h->pool);
+			    ent->word = h->pool->ptr;
+			    ent->ordinal_num = h->next_num++;
+			    if (cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+			      h->code_to_nhr[ent->ordinal_num - 1] = ent;
+			    memcpy (h->pool->ptr, Word, len);
+			    h->pool->ptr += len;
+			    h->pool->left -= len;
+			    h->HashUsed++;
+			    break;
+			  }
+			/* Compare the words */
+			s1 = Word;
+			s2 = ent->word;
+			len = *s1 + 1;
+			for (; len; len--)
+			  if (*s1++ != *s2++)
+			    break;
+
+			if (!len)
+			  break;
+
+			hashval = (hashval + step);
+			if (hashval >= hsize)
+			  hashval -= hsize;
+		      }
+
+		    switch (cdh.novel_method)
+		      {
+		      case MG_NOVEL_BINARY:
+			{
+			  BINARY_ENCODE (ent->ordinal_num, h->binary_start);
+			  if (ent->ordinal_num == h->binary_start)
+			    h->binary_start++;
+			}
+			break;
+		      case MG_NOVEL_DELTA:
+			{
+			  DELTA_ENCODE (ent->ordinal_num);
+			}
+			break;
+		      case MG_NOVEL_HYBRID:
+			{
+			  int k = 0;
+			  int j = ent->ordinal_num - 1;
+			  while (j > blk_end[which][k])
+			    k++;
+			  assert (j - blk_start[which][k] + 1 >= 1 &&
+				  j - blk_start[which][k] + 1 <=
+			       blk_end[which][k] - blk_start[which][k] + 1);
+
+			  GAMMA_ENCODE (k + 1);
+			  BINARY_ENCODE (j - blk_start[which][k] + 1,
+					 blk_end[which][k] -
+					 blk_start[which][k] + 1);
+			}
+			break;
+		      case MG_NOVEL_HYBRID_MTF:
+			{
+			  int k = 0;
+			  int j = ent->ordinal_num - 1;
+			  while (j > blk_end[which][k])
+			    k++;
+			  assert (j - blk_start[which][k] + 1 >= 1 &&
+				  j - blk_start[which][k] + 1 <=
+			       blk_end[which][k] - blk_start[which][k] + 1);
+			  GAMMA_ENCODE (k + 1);
+			  BINARY_ENCODE (j - blk_start[which][k] + 1,
+					 blk_end[which][k] -
+					 blk_start[which][k] + 1);
+
+			  if (ent->ordinal_num - 1 >= novels_used[which])
+			    {
+			      int a = novels_used[which];
+			      int b = ent->ordinal_num - 1;
+			      novel_hash_rec *temp;
+
+
+/*                            fprintf(stderr, "a = %d , b = %d\n", a, b);
+ */
+			      temp = h->code_to_nhr[a];
+			      h->code_to_nhr[a] = h->code_to_nhr[b];
+			      h->code_to_nhr[b] = temp;
+			      h->code_to_nhr[a]->ordinal_num = a + 1;
+			      h->code_to_nhr[b]->ordinal_num = b + 1;
+			      if (novels_used[which] == MAX_SWAPS)
+				FatalError (1, "Not enough mem for swapping");
+			      swaps[which][novels_used[which]] = b;
+			      novels_used[which]++;
+			    }
+			}
+			break;
+		      }
+		    if (h->HashUsed >= h->HashSize >> 1)
+		      {
+			novel_hash_rec *ht;
+			unsigned long size;
+			unsigned long i;
+			size = prime (h->HashSize * 2);
+			if (cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+			  {
+			    Xfree (h->code_to_nhr);
+			    h->code_to_nhr = Xmalloc (sizeof (novel_hash_rec *) *
+						      ((size >> 1) + 2));
+			  }
+			if (!(ht = Xmalloc (sizeof (novel_hash_rec) * size)))
+			  {
+			    Message ("Unable to allocate memory for table");
+			    return (COMPERROR);
+			  }
+			bzero ((char *) ht, sizeof (novel_hash_rec) * size);
+
+			for (i = 0; i < h->HashSize; i++)
+			  if (h->HashTable[i].word)
+			    {
+			      register u_char *wptr;
+			      register unsigned long hashval, step;
+
+			      wptr = h->HashTable[i].word;
+			      HASH (hashval, step, wptr, size);
+			      wptr = (ht + hashval)->word;
+			      while (wptr)
+				{
+				  hashval += step;
+				  if (hashval >= size)
+				    hashval -= size;
+				  wptr = (ht + hashval)->word;
+				}
+			      ht[hashval] = h->HashTable[i];
+			      if (cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+				h->code_to_nhr[ht[hashval].ordinal_num - 1] =
+				  &ht[hashval];
+			    }
+			Xfree (h->HashTable);
+			h->HashTable = ht;
+			h->HashSize = size;
+		      }
+		  }
+		  break;
+		}
+	    }
+	}
+      else
+	{
+	  HUFF_ENCODE (res, ht[which]->codes, ht[which]->hd->clens);
+#ifdef DOCDUMP
+	  if (cth.num_of_docs == DOCDUMP)
+	    {
+	      printf ("   %d %d\n", ht[which]->hd->clens[res],
+		      ht[which]->codes[res]);
+	    }
+#endif
+	}
+    }
+
+
+  /* Add a 1 bit onto the end of the buffer the remaining bits in the last
+     byte will all be zero */
+
+  ENCODE_BIT (1);
+
+  ENCODE_FLUSH;
+
+  byte_length = __pos - __base;
+  if (!__remaining)
+    {
+      Message ("The end of the buffer was probably overrun");
+      return COMPERROR;
+    }
+
+  ENCODE_DONE
+
+#ifdef DOCDUMP
+    if (cth.num_of_docs == DOCDUMP)
+    {
+      printf ("unused bits = %d\n", bits_unused);
+    }
+#endif
+
+  HTONUL(text_length);  /* [RPAP - Jan 97: Endian Ordering] */
+  fwrite (&text_length, sizeof (text_length), 1, text_idx);
+  NTOHUL(text_length);  /* [RPAP - Jan 97: Endian Ordering] */
+  text_length += byte_length;
+
+#ifdef DOCDUMP
+  if (cth.num_of_docs == DOCDUMP)
+    {
+      int i;
+      for (i = 0; i < byte_length; i++)
+	printf ("%02x ", comp_buffer[i]);
+      printf ("\n");
+    }
+#endif
+
+  if (cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+    for (which = 0; which <= 1; which++)
+      for (novels_used[which]--; novels_used[which] >= 0; novels_used[which]--)
+	{
+	  int a = novels_used[which];
+	  int b = swaps[which][novels_used[which]];
+	  novel_hash_rec *temp;
+	  temp = nht[which].code_to_nhr[a];
+	  nht[which].code_to_nhr[a] = nht[which].code_to_nhr[b];
+	  nht[which].code_to_nhr[b] = temp;
+	  nht[which].code_to_nhr[a]->ordinal_num = a + 1;
+	  nht[which].code_to_nhr[b]->ordinal_num = b + 1;
+	}
+
+
+  fwrite (comp_buffer, sizeof (*comp_buffer), byte_length, text);
+
+  if ((double) l_in / (double) byte_length > cth.ratio)
+    cth.ratio = (double) l_in / (double) byte_length;
+
+  cth.num_of_docs++;
+  if (l_in > cth.length_of_longest_doc)
+    cth.length_of_longest_doc = l_in;
+
+  cth.num_of_bytes += l_in;
+
+  if (Comp_Stats)
+    {
+      stats_in_tot_bytes += l_in;
+      stats_in_bytes += l_in;
+      stats_out_bytes += byte_length;
+      if (stats_in_bytes >= comp_stat_point)
+	{
+	  fprintf (Comp_Stats, "%10.0f %10.0f %10.0f %f\n", stats_in_tot_bytes,
+		   stats_in_bytes, stats_out_bytes,
+		   (double) stats_out_bytes / (double) stats_in_bytes);
+	  stats_in_bytes = 0.0;
+	  stats_out_bytes = 0.0;
+	}
+    }
+
+  return COMPALLOK;
+}
+
+
+
+
+
+
+int 
+write_aux_dict (char *FileName)
+{
+  int i;
+  FILE *aux;
+  if (!(aux = create_file (FileName, TEXT_DICT_AUX_SUFFIX, "wb",
+			   MAGIC_AUX_DICT, MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      fprintf(stderr,"Couldn't create file %s%s:%s\n",
+              FileName, TEXT_DICT_AUX_SUFFIX,
+#if defined(HAVE_STRERROR) || defined(__WIN32__)
+              strerror(errno)
+#else
+              " "
+#endif
+              );
+      return COMPERROR;
+    }
+  for (i = 0; i <= 1; i++)
+    {
+      aux_frags_header afh;
+      char_pool *cp;
+
+      afh.num_frags = nht[i].HashUsed;
+      afh.mem_for_frags = 0;
+      for (cp = nht[i].first_pool; cp; cp = cp->next)
+	afh.mem_for_frags += POOL_SIZE - cp->left;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      HTONUL(afh.num_frags);
+      HTONUL(afh.mem_for_frags);
+
+      fwrite (&afh, sizeof (afh), 1, aux);
+
+      for (cp = nht[i].first_pool; cp; cp = cp->next)
+	fwrite (cp->pool, POOL_SIZE - cp->left, sizeof (u_char), aux);
+    }
+  fclose (aux);
+  return COMPALLOK;
+}
+
+
+void 
+estimate_compressed_aux_dict (void)
+{
+  int i;
+  u_long aux_compressed = 0, total_uncomp = 0;
+  for (i = 0; i <= 1; i++)
+    {
+      int j;
+      long chars[256], fchars[256];
+      long lens[16], flens[16];
+      char_pool *cp;
+      bzero ((char *) chars, sizeof (chars));
+      bzero ((char *) lens, sizeof (lens));
+      for (cp = nht[i].first_pool; cp; cp = cp->next)
+	{
+	  u_char *buf = cp->pool;
+	  while (buf != cp->ptr)
+	    {
+	      int len = *buf++;
+	      lens[len]++;
+	      total_uncomp += len + 4;
+	      for (; len; len--)
+		chars[*buf++]++;
+	    }
+	}
+      for (j = 0; j < 256; j++)
+	if (!chars[j] && PESINAWORD (j) == i)
+	  fchars[j] = 1;
+	else
+	  fchars[j] = chars[j];
+      for (j = 0; j < 16; j++)
+	if (!lens[j])
+	  flens[j] = 1;
+	else
+	  flens[j] = lens[j];
+
+      aux_compressed += (Calculate_Huffman_Size (16, flens, lens) +
+			 Calculate_Huffman_Size (256, fchars, chars)) / 8;
+
+    }
+
+  Message ("Aux dictionary (Uncompressed) %.2f Mb ( %u bytes   %0.3f %%)",
+	   total_uncomp / 1024.0 / 1024, total_uncomp,
+	   (total_uncomp * 100.0) / bytes_processed);
+  Message ("Aux dictionary (Compressed)   %.2f Mb ( %.0f bytes   %0.3f %%)",
+	   aux_compressed / 1024.0 / 1024, aux_compressed * 1.0,
+	   (aux_compressed * 100.0) / bytes_processed);
+}
+
+
+
+
+
+
+int 
+done_text_2 (char *FileName)
+{
+  if (Comp_Stats)
+    fprintf (Comp_Stats, "%10.0f %10.0f %10.0f %f\n", stats_in_tot_bytes,
+	     stats_in_bytes, stats_out_bytes,
+	     (double) stats_out_bytes / (double) stats_in_bytes);
+
+  HTONUL(text_length);  /* [RPAP - Jan 97: Endian Ordering] */
+  fwrite (&text_length, sizeof (text_length), 1, text_idx);
+  NTOHUL(text_length);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(cth.num_of_docs);
+  HTOND(cth.num_of_bytes); /* [RJM 07/97: 4G limit] */
+  HTONUL(cth.num_of_words);
+  HTONUL(cth.length_of_longest_doc);
+  HTOND(cth.ratio);
+
+  if (fseek (text_idx, sizeof (u_long), SEEK_SET) == -1 ||
+      fwrite (&cth, sizeof (cth), 1, text_idx) != 1)
+    return COMPERROR;
+  fclose (text_idx);
+
+  if (fseek (text, sizeof (u_long), SEEK_SET) == -1 ||
+      fwrite (&cth, sizeof (cth), 1, text) != 1)
+    return COMPERROR;
+  fclose (text);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(cth.num_of_docs);
+  NTOHD(cth.num_of_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(cth.num_of_words);
+  NTOHUL(cth.length_of_longest_doc);
+  NTOHD(cth.ratio);
+  
+
+  Message ("Compressed Text %.2f Mb ( %u bytes   %0.3f %%)",
+	   text_length / 1024.0 / 1024.0, text_length,
+	   (text_length * 100.0) / bytes_processed);
+  Message ("Words portion of the dictionary %.2f Mb ( %.0f bytes   %0.3f %%)",
+	   Words_disk / 1024.0 / 1024, Words_disk * 1.0,
+	   (Words_disk * 100.0) / bytes_processed);
+
+  if (cdh.dict_type != MG_COMPLETE_DICTIONARY &&
+      (cdh.novel_method == MG_NOVEL_BINARY ||
+       cdh.novel_method == MG_NOVEL_DELTA ||
+       cdh.novel_method == MG_NOVEL_HYBRID ||
+       cdh.novel_method == MG_NOVEL_HYBRID_MTF))
+    {
+      if (write_aux_dict (FileName) == COMPERROR)
+	return COMPERROR;
+      estimate_compressed_aux_dict ();
+    }
+  else
+    {
+      if (cdh.dict_type != MG_COMPLETE_DICTIONARY)
+	Message ("Huffman info for chars in dictionary %.2f Mb"
+		 " ( %u bytes   %0.3f %%)",
+		 Chars_disk / 1024.0 / 1024, Chars_disk,
+		 (Chars_disk * 100.0) / bytes_processed);
+      unlink (make_name (FileName, TEXT_DICT_AUX_SUFFIX, NULL));
+    }
+
+  return (COMPALLOK);
+}
Index: /indexers/branches/3.03a/mg/src/text/text_get.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/text_get.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/text_get.c	(revision 14757)
@@ -0,0 +1,1090 @@
+/**************************************************************************
+ *
+ * text_get.c -- Function for reading documents from the compressed text
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "filestats.h"
+#include "timing.h"
+#include "messages.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "huffman.h"
+#include "bitio_m_mem.h"
+#include "bitio_m.h"
+#include "bitio_stdio.h"
+#include "huffman_stdio.h"
+
+#include "mg.h"
+#include "invf.h"
+#include "text.h"
+#include "lists.h"
+#include "backend.h"
+#include "text_get.h"
+#include "locallib.h"
+#include "words.h"
+#include "mg_errors.h"
+#include "local_strings.h"
+
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:26  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:35:48  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.3  1994/10/20  03:57:11  tes
+   * I have rewritten the boolean query optimiser and abstracted out the
+   * components of the boolean query.
+   *
+   * Revision 1.2  1994/09/20  04:42:15  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+
+
+
+
+/* FetchDocStart () 
+ * Reads into DocEnt the starting position of the document in the *.text file
+ * Where the first document is document number 1
+ * It returns the true weight of the document.
+ */
+
+
+
+
+static double 
+FetchDocStartLev1 (text_data * td, u_long DN,
+		   u_long * seek_pos, u_long * len)
+{
+  unsigned long data[2];
+  /* [TS:Sep/94] Fixed up the seek call to give the correct offset */
+  Fseek (td->TextIdxFile,
+	 sizeof (unsigned long) * (DN - 1) +	/* the doc offsets */
+	 sizeof (unsigned long) +	/* the magic number */
+	 sizeof (compressed_text_header),	/* the header */
+	 0);
+  Fread ((char *) &data, sizeof (data), 1, td->TextIdxFile);
+  
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(data[0]);
+  NTOHUL(data[1]);
+
+  *seek_pos = data[0];
+  *len = data[1] - data[0];
+  return (1.0);
+}
+
+#define MG_PAGE_SIZE 2048
+
+static int 
+LoadIdx (text_data * td, unsigned long DN)
+{
+  if (!td->idx_data)
+    {
+      td->idx_data = Xmalloc (sizeof (*(td->idx_data)) * MG_PAGE_SIZE);
+      if (!td->idx_data)
+	FatalError (1, "Out of memory in FDSL2");
+    }
+  if (td->current_pos == -1 || DN >= td->current_pos + MG_PAGE_SIZE - 1 ||
+      DN < td->current_pos)
+    {
+      int i, num;  /* [RPAP - Jan 97: Endian Ordering] */
+
+      long rn = (long) DN - (MG_PAGE_SIZE >> 1);
+      if (rn < 1)
+	rn = 1;
+      Fseek (td->TextIdxWgtFile, (sizeof (unsigned long) + sizeof (float)) *
+	       (rn - 1) + sizeof (unsigned long), 0);
+      num = Fread ((char *) td->idx_data, sizeof (*(td->idx_data)), MG_PAGE_SIZE, /* [RPAP - Jan 97: Endian Ordering] */
+		   td->TextIdxWgtFile);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (i = 0; i < num; i++)
+	{
+	  NTOHUL(td->idx_data[i].Start);
+	  NTOHF(td->idx_data[i].Weight);
+	}
+
+      td->current_pos = rn;
+    }
+  return DN - td->current_pos;
+}
+
+static double 
+FDSL2 (text_data * td, unsigned long DN, unsigned long *Pos)
+{
+  unsigned long pos = LoadIdx (td, DN);
+  *Pos = td->idx_data[pos].Start;
+  return (td->idx_data[pos].Weight);
+}
+
+
+static double 
+FetchDocStartLev2 (text_data * td, u_long DN,
+		   u_long * seek_pos, u_long * len)
+{
+  double Weight;
+  unsigned long s1, s2;
+  Weight = FDSL2 (td, DN, &s1);
+  do
+    {
+      DN++;
+      FDSL2 (td, DN, &s2);
+    }
+  while (s2 == s1);
+  *seek_pos = s1;
+  *len = s2 - s1;
+  return (Weight);
+}
+
+
+
+
+double 
+FetchDocStart (query_data * qd, u_long DN, u_long * seek_pos, u_long * len)
+{
+  qd->text_idx_lookups++;
+  if (qd->td->TextIdxWgtFile)
+    return FetchDocStartLev2 (qd->td, DN, seek_pos, len);
+  else
+    return FetchDocStartLev1 (qd->td, DN, seek_pos, len);
+}
+
+unsigned long 
+FetchInitialParagraph (text_data * td, unsigned long ParaNum)
+{
+  if (td->TextIdxWgtFile)
+    {
+      unsigned long pos;
+      unsigned long start;
+      int PN = ParaNum - 1;
+      pos = LoadIdx (td, ParaNum);
+      start = td->idx_data[pos].Start;
+      while (PN > 0)
+	{
+	  pos = LoadIdx (td, PN);
+	  if (td->idx_data[pos].Start != start)
+	    return PN + 1;
+	  PN--;
+	}
+      return PN + 1;
+    }
+  else
+    return ParaNum;
+}
+
+
+
+/* FetchCompressed () 
+ * Reads into buffer DocBuff the compressed form of document DocNum. 
+ * Where the first document is document number 1
+ */
+int 
+FetchCompressed (query_data * qd, char **DocBuff, DocEntry * DocEnt)
+{
+  if (!DocEnt->SeekPos)
+    FetchDocStart (qd, DocEnt->DocNum, &DocEnt->SeekPos, &DocEnt->Len);
+  if (!(*DocBuff = Xmalloc (DocEnt->Len)))
+    return (-1);
+
+  if (Fseek (qd->td->TextFile, DocEnt->SeekPos, 0) == -1)
+    FatalError (1, "Error when seeking into text file");
+#if 0
+  printf ("Loading compressed text %d %d\n", DocEnt->SeekPos, DocEnt->Len);
+#endif
+  if (Fread (*DocBuff, 1, DocEnt->Len, qd->td->TextFile) != DocEnt->Len)
+    FatalError (1, "Error when reading data");
+
+  return (DocEnt->Len);
+
+}
+
+
+text_data *
+LoadTextData (File * text, File * text_idx_wgt, File * text_idx)
+{
+  text_data *td;
+
+  if (!(td = Xmalloc (sizeof (text_data))))
+    {
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  td->TextFile = text;
+  td->TextIdxWgtFile = text_idx_wgt;
+  td->TextIdxFile = text_idx;
+  td->current_pos = -1;
+  td->idx_data = NULL;
+  Fread (&td->cth, sizeof (td->cth), 1, text);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(td->cth.num_of_docs);
+  NTOHD(td->cth.num_of_bytes); /* [RJM 07/97: 4G limit] */
+  NTOHUL(td->cth.num_of_words);
+  NTOHUL(td->cth.length_of_longest_doc);
+  NTOHD(td->cth.ratio);
+
+  return (td);
+}
+
+
+void 
+FreeTextData (text_data * td)
+{
+  if (td)
+    {
+      if (td->idx_data)
+	Xfree (td->idx_data);
+      Xfree (td);
+    }
+}
+
+
+static int 
+pts_comp (const void *A, const void *B)
+{
+  const DocEntry *const *a = A;
+  const DocEntry *const *b = B;
+  return (*a)->DocNum - (*b)->DocNum;
+}
+
+
+
+
+int 
+GetPosLens (query_data * qd, DocEntry * Docs, int num)
+{
+  DocEntry **pts;
+  int i, j;
+  if (!(pts = Xmalloc (num * sizeof (DocEntry *))))
+    {
+      mg_errno = MG_NOMEM;
+      return (-1);
+    }
+  for (i = j = 0; i < num; i++, Docs++)
+    if (!Docs->SeekPos)
+      pts[j++] = Docs;
+
+  if (j)
+    {
+      qsort (pts, j, sizeof (DocEntry *), pts_comp);
+      for (i = 0; i < j; i++)
+	FetchDocStart (qd, pts[i]->DocNum, &pts[i]->SeekPos, &pts[i]->Len);
+    }
+
+  Xfree (pts);
+  return (0);
+}
+
+
+
+
+
+int 
+LoadBuffers (query_data * qd, DocEntry * Docs, int max_mem, int num)
+{
+  DocEntry **pts;
+  int i, j;
+  int mem;
+
+  if (!num)
+    return (0);
+  if (!(pts = Xmalloc (num * sizeof (DocEntry *))))
+    {
+      mg_errno = MG_NOMEM;
+      return (-1);
+    }
+
+  mem = i = 0;
+  do
+    {
+      pts[i] = Docs;
+      mem += Docs->Len;
+      i++;
+      Docs++;
+    }
+  while (i < num && mem < max_mem);
+  if (i > 1)
+    qsort (pts, i, sizeof (DocEntry *), pts_comp);
+  for (j = 0; j < i; j++)
+    {
+      if (FetchCompressed (qd, &pts[j]->CompTextBuffer, pts[j]) == -1)
+	return (-1);
+      ChangeMemInUse (qd, pts[j]->Len);
+    }
+
+  Xfree (pts);
+
+  return (i);
+}
+
+
+
+
+
+void 
+FreeBuffers (query_data * qd, DocEntry * Docs, int num)
+{
+  int i;
+  for (i = 0; i < num; i++, Docs++)
+    if (Docs->CompTextBuffer)
+      {
+	Xfree (Docs->CompTextBuffer);
+	Docs->CompTextBuffer = NULL;
+	ChangeMemInUse (qd, -Docs->Len);
+      }
+}
+
+
+
+/****************************************************************************/
+
+static void 
+FreeAuxDict (auxiliary_dict * ad)
+{
+  if (!ad)
+    return;
+  if (ad->word_data[0])
+    Xfree (ad->word_data[0]);
+  if (ad->word_data[1])
+    Xfree (ad->word_data[1]);
+  if (ad->words[0])
+    Xfree (ad->words[0]);
+  if (ad->words[1])
+    Xfree (ad->words[1]);
+  Xfree (ad);
+}
+
+static auxiliary_dict *
+LoadAuxDict (compression_dict * cd, File * text_aux_dict)
+{
+  auxiliary_dict *ad;
+  int i;
+
+  if (!(ad = Xmalloc (sizeof (auxiliary_dict))))
+    {
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  bzero ((char *) ad, sizeof (*ad));
+
+  for (i = 0; i <= 1; i++)
+    {
+      int j;
+      u_char *pos;
+
+      Fread (&ad->afh[i], sizeof (aux_frags_header), 1, text_aux_dict);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(ad->afh[i].num_frags);
+      NTOHUL(ad->afh[i].mem_for_frags);
+
+      if (!(ad->word_data[i] = Xmalloc (ad->afh[i].mem_for_frags)))
+	{
+	  mg_errno = MG_NOMEM;
+	  FreeAuxDict (ad);
+	  return (NULL);
+	}
+      if (!(ad->words[i] = Xmalloc (ad->afh[i].num_frags * sizeof (u_char *))))
+	{
+	  mg_errno = MG_NOMEM;
+	  FreeAuxDict (ad);
+	  return (NULL);
+	}
+
+      Fread (ad->word_data[i], ad->afh[i].mem_for_frags, sizeof (u_char),
+	     text_aux_dict);
+
+      pos = ad->word_data[i];
+      for (j = 0; j < ad->afh[i].num_frags; j++)
+	{
+	  ad->words[i][j] = pos;
+	  pos += *pos + 1;
+	}
+      if (cd->cdh.novel_method == MG_NOVEL_HYBRID ||
+	  cd->cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+	{
+	  int num;
+	  num = 1;
+	  ad->blk_start[i][0] = 0;
+	  ad->blk_end[i][0] = cd->cdh.num_words[i] - 1;
+	  while (num < 33)
+	    {
+	      ad->blk_start[i][num] = ad->blk_end[i][num - 1] + 1;
+	      ad->blk_end[i][num] = ad->blk_start[i][num] +
+		(ad->blk_end[i][num - 1] - ad->blk_start[i][num - 1]) * 2;
+	      num++;
+	    }
+	}
+    }
+  return (ad);
+}
+
+
+
+
+
+
+static u_char ***
+ReadInWords (File * dict, compression_dict * cd,
+	     comp_frags_header * cfh, u_char ** escape)
+{
+  int i, lookback;
+  int ptrs_reqd = 0;
+  int mem_reqd = 0;
+  int num_set[MAX_HUFFCODE_LEN + 1];
+  u_char *next_word[MAX_HUFFCODE_LEN + 1];
+  u_char **vals;
+  u_char ***values;
+  u_char word[MAXWORDLEN + 1];
+  u_char last_word[MAX_HUFFCODE_LEN + 1][MAXWORDLEN + 1];
+
+  lookback = cd->cdh.lookback;
+
+  for (i = cfh->hd.mincodelen; i <= cfh->hd.maxcodelen; i++)
+    {
+      ptrs_reqd += (cfh->hd.lencount[i] + ((1 << lookback) - 1)) >> lookback;
+      mem_reqd += cfh->huff_words_size[i];
+    }
+
+  if (!(vals = Xmalloc (ptrs_reqd * sizeof (*vals))))
+    return (NULL);
+
+  if (!(values = Xmalloc ((MAX_HUFFCODE_LEN + 1) * sizeof (u_char **))))
+    return (NULL);
+
+  if (!(next_word[0] = Xmalloc (mem_reqd))) return (NULL);
+
+  cd->MemForCompDict += ptrs_reqd * sizeof (*vals) +
+    (MAX_HUFFCODE_LEN + 1) * sizeof (u_char **) +
+    mem_reqd;
+
+  values[0] = vals;
+  values[0][0] = next_word[0];
+  for (i = 1; i <= cfh->hd.maxcodelen; i++)
+    {
+      int next_start = (values[i - 1] - vals) +
+      ((cfh->hd.lencount[i - 1] + ((1 << lookback) - 1)) >> lookback);
+      values[i] = &vals[next_start];
+      next_word[i] = next_word[i - 1] + cfh->huff_words_size[i - 1];
+      values[i][0] = next_word[i];
+    }
+
+  bzero ((char *) num_set, sizeof (num_set));
+
+  for (i = 0; i < cfh->hd.num_codes; i++)
+    {
+      register int val, copy;
+      register int len = cfh->hd.clens[i];
+      val = Getc (dict);
+      copy = (val >> 4) & 0xf;
+      val &= 0xf;
+
+      Fread (word + copy + 1, sizeof (u_char), val, dict);
+      *word = val + copy;
+
+      if ((num_set[len] & ((1 << lookback) - 1)) == 0)
+	{
+	  values[len][num_set[len] >> lookback] = next_word[len];
+	  memcpy (next_word[len], word, *word + 1);
+	  if (escape && i == cfh->hd.num_codes - 1)
+	    *escape = next_word[len];
+	  next_word[len] += *word + 1;
+	}
+      else
+	{
+	  copy = prefixlen (last_word[len], word);
+	  memcpy (next_word[len] + 1, word + copy + 1, *word - copy);
+	  *next_word[len] = (copy << 4) + (*word - copy);
+	  if (escape && i == cfh->hd.num_codes - 1)
+	    *escape = next_word[len];
+	  next_word[len] += (*word - copy) + 1;
+	}
+      memcpy (last_word[len], word, *word + 1);
+      num_set[len]++;
+    }
+  if (cfh->hd.clens)
+    Xfree (cfh->hd.clens);
+  cfh->hd.clens = NULL;
+  return values;
+}
+
+
+static compression_dict *
+Load_Comp_Dict (File * dict, File * aux_dict)
+{
+  int which;
+  compression_dict *cd;
+
+  if (!(cd = Xmalloc (sizeof (compression_dict))))
+    {
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  bzero ((char *) cd, sizeof (compression_dict));
+
+  cd->MemForCompDict = sizeof (compression_dict);
+
+  if (F_Read_cdh (dict, &cd->cdh, &cd->MemForCompDict, NULL) == -1)
+    return NULL;
+
+  for (which = 0; which < 2; which++)
+    switch (cd->cdh.dict_type)
+      {
+      case MG_COMPLETE_DICTIONARY:
+	{
+	  if (!(cd->cfh[which] = Xmalloc (sizeof (*cd->cfh[which]))))
+	    return NULL;
+	  cd->MemForCompDict += sizeof (*cd->cfh[which]);
+	  if (F_Read_cfh (dict, cd->cfh[which], &cd->MemForCompDict, NULL) == -1)
+	    return NULL;
+
+	  if (!(cd->values[which] = ReadInWords (dict, cd, cd->cfh[which],
+						 NULL)))
+	    return NULL;
+	  cd->escape[which] = NULL;
+
+	}
+	break;
+      case MG_PARTIAL_DICTIONARY:
+	{
+	  huff_data *hd;
+	  u_long **vals;
+	  if (cd->cdh.num_words[which])
+	    {
+	      if (!(cd->cfh[which] = Xmalloc (sizeof (*cd->cfh[which]))))
+		return NULL;
+	      cd->MemForCompDict += sizeof (*cd->cfh[which]);
+	      if (F_Read_cfh (dict, cd->cfh[which], &cd->MemForCompDict, NULL) == -1)
+		return NULL;
+
+	      if (!(cd->values[which] = ReadInWords (dict, cd, cd->cfh[which],
+						     &cd->escape[which])))
+		return NULL;
+	    }
+	  if (!(hd = Xmalloc (sizeof (huff_data))))
+	    return NULL;
+	  cd->MemForCompDict += sizeof (huff_data);
+	  if (F_Read_Huffman_Data (dict, hd, &cd->MemForCompDict, NULL) == -1)
+	    return NULL;
+	  if (!(vals = Generate_Huffman_Vals (hd, &cd->MemForCompDict)))
+	    return NULL;
+	  if (hd->clens)
+	    Xfree (hd->clens);
+	  hd->clens = NULL;
+	  cd->chars_huff[which] = hd;
+	  cd->chars_vals[which] = vals;
+	  if (!(hd = Xmalloc (sizeof (huff_data))))
+	    return NULL;
+	  cd->MemForCompDict += sizeof (huff_data);
+	  if (F_Read_Huffman_Data (dict, hd, &cd->MemForCompDict, NULL) == -1)
+	    return NULL;
+	  if (!(vals = Generate_Huffman_Vals (hd, &cd->MemForCompDict)))
+	    return NULL;
+	  cd->lens_huff[which] = hd;
+	  cd->lens_vals[which] = vals;
+	  if (hd->clens)
+	    Xfree (hd->clens);
+	  hd->clens = NULL;
+	}
+	break;
+      case MG_SEED_DICTIONARY:
+	{
+	  huff_data *hd;
+	  u_long **vals;
+	  if (cd->cdh.num_words[which])
+	    {
+	      if (!(cd->cfh[which] = Xmalloc (sizeof (*cd->cfh[which]))))
+		return NULL;
+	      cd->MemForCompDict += sizeof (*cd->cfh[which]);
+	      if (F_Read_cfh (dict, cd->cfh[which], &cd->MemForCompDict, NULL) == -1)
+		return NULL;
+
+	      if (!(cd->values[which] = ReadInWords (dict, cd, cd->cfh[which],
+						     &cd->escape[which])))
+		return NULL;
+	    }
+	  switch (cd->cdh.novel_method)
+	    {
+	    case MG_NOVEL_HUFFMAN_CHARS:
+	      if (!(hd = Xmalloc (sizeof (huff_data))))
+		return NULL;
+	      cd->chars_huff[which] = hd;
+	      cd->MemForCompDict += sizeof (huff_data);
+	      if (F_Read_Huffman_Data (dict, hd, &cd->MemForCompDict,
+				       NULL) == -1)
+		return NULL;
+	      if (!(vals = Generate_Huffman_Vals (hd, &cd->MemForCompDict)))
+		return NULL;
+	      cd->chars_vals[which] = vals;
+	      if (hd->clens)
+		Xfree (hd->clens);
+	      hd->clens = NULL;
+	      if (!(hd = Xmalloc (sizeof (huff_data))))
+		return NULL;
+	      cd->MemForCompDict += sizeof (huff_data);
+	      cd->lens_huff[which] = hd;
+	      if (F_Read_Huffman_Data (dict, hd, &cd->MemForCompDict
+				       ,NULL) == -1)
+		return NULL;
+	      if (!(vals = Generate_Huffman_Vals (hd, &cd->MemForCompDict)))
+		return NULL;
+	      cd->lens_vals[which] = vals;
+	      if (hd->clens)
+		Xfree (hd->clens);
+	      hd->clens = NULL;
+	      break;
+	    case MG_NOVEL_BINARY:
+	      break;
+	    case MG_NOVEL_DELTA:
+	      break;
+	    case MG_NOVEL_HYBRID:
+	      break;
+	    case MG_NOVEL_HYBRID_MTF:
+	      break;
+	    }
+	  break;
+	}
+      }
+
+  if (cd->cdh.novel_method == MG_NOVEL_BINARY ||
+      cd->cdh.novel_method == MG_NOVEL_DELTA ||
+      cd->cdh.novel_method == MG_NOVEL_HYBRID ||
+      cd->cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+    {
+      if (!aux_dict)
+	{
+	  mg_errno = MG_NOFILE;
+	  FreeCompDict (cd);
+	  return (NULL);
+	}
+
+      if (!(cd->ad = LoadAuxDict (cd, aux_dict)))
+	{
+	  FreeCompDict (cd);
+	  return (NULL);
+	}
+    }
+
+
+  mg_errno = MG_NOERROR;
+
+  cd->fast_loaded = 0;
+  return (cd);
+}
+
+#define WORDNO(p, base) ((((char*)(p))-((char*)(base)))/sizeof(u_char*))
+
+#define IS_FIXUP(p) ((fixup[WORDNO(p,cd)/8] & (1<<(WORDNO(p, cd) & 7))) != 0)
+
+
+static compression_dict *
+Load_Fast_Comp_Dict (File * text_fast_comp_dict)
+{
+  compression_dict *cd;
+  u_long *p, *end;
+  u_char *fixup;
+  u_long mem;
+  u_long fixup_mem;
+  int i;  /* [RPAP - Jan 97: Endian Ordering] */
+
+  Fread (&mem, sizeof (mem), 1, text_fast_comp_dict);
+  NTOHUL(mem);  /* [RPAP - Jan 97: Endian Ordering] */
+  Fread (&fixup_mem, sizeof (fixup_mem), 1, text_fast_comp_dict);
+  NTOHUL(fixup_mem);  /* [RPAP - Jan 97: Endian Ordering] */
+  if (!(cd = Xmalloc (mem)))
+    {
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  end = (u_long *) (((u_char *) cd) + mem);
+  Fread (cd, sizeof (u_char), mem, text_fast_comp_dict);
+
+  if (!(fixup = Xmalloc (fixup_mem)))
+    {
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  Fread (fixup, fixup_mem, sizeof (u_char), text_fast_comp_dict);
+
+  for (p = (u_long *) cd; (u_long) p < (u_long) end; p++)
+    if (IS_FIXUP (p))
+      {
+	NTOHUL(*p);  /* [RPAP - Jan 97: Endian Ordering] */
+	*p = *p + (u_long) cd;
+      }
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  /* cdh */
+  NTOHUL(cd->cdh.dict_type);
+  NTOHUL(cd->cdh.novel_method);
+  for (i = 0; i < TEXT_PARAMS; i++)
+    NTOHUL(cd->cdh.params[i]);
+  NTOHUL(cd->cdh.num_words[0]);
+  NTOHUL(cd->cdh.num_words[1]);
+  NTOHUL(cd->cdh.num_word_chars[0]);
+  NTOHUL(cd->cdh.num_word_chars[1]);
+  NTOHUL(cd->cdh.lookback);
+  /* cfh */
+  for (i = 0; i <= 1; i++)
+    {
+      int j;
+
+      NTOHSI(cd->cfh[i]->hd.num_codes);
+      NTOHSI(cd->cfh[i]->hd.mincodelen);
+      NTOHSI(cd->cfh[i]->hd.maxcodelen);
+      for (j = 0; j < MAX_HUFFCODE_LEN + 1; j++)
+	{
+	  NTOHSI(cd->cfh[i]->hd.lencount[j]);
+	  NTOHUL(cd->cfh[i]->hd.min_code[j]);
+	}
+      NTOHUL(cd->cfh[i]->uncompressed_size);
+      for (j = 0; j < MAX_HUFFCODE_LEN + 1; j++)
+	NTOHUL(cd->cfh[i]->huff_words_size[j]);
+    }
+  NTOHUL(cd->MemForCompDict);
+  /* ad */
+  if (cd->cdh.novel_method == MG_NOVEL_BINARY ||
+      cd->cdh.novel_method == MG_NOVEL_DELTA ||
+      cd->cdh.novel_method == MG_NOVEL_HYBRID ||
+      cd->cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+    for (i = 0; i <= 1; i++)
+      {
+	int j;
+	
+	NTOHUL(cd->ad->afh[i].num_frags);
+	NTOHUL(cd->ad->afh[i].mem_for_frags);
+	for (j = 0; j < 33; j++)
+	  {
+	    NTOHSI(cd->ad->blk_start[i][j]);
+	    NTOHSI(cd->ad->blk_end[i][j]);
+	  }
+      }
+  NTOHSI(cd->fast_loaded);
+
+  Xfree (fixup);
+  return (cd);
+}
+
+
+
+
+compression_dict *
+LoadCompDict (File * text_comp_dict,
+	      File * text_aux_dict,
+	      File * text_fast_comp_dict)
+{
+  return text_fast_comp_dict ?
+    Load_Fast_Comp_Dict (text_fast_comp_dict) :
+    Load_Comp_Dict (text_comp_dict, text_aux_dict);
+}
+
+
+
+
+void 
+FreeCompDict (compression_dict * cd)
+{
+  int which;
+  if (cd->fast_loaded)
+    {
+      Xfree (cd);
+      return;
+    }
+  for (which = 0; which < 2; which++)
+    {
+      if (cd->cfh[which])
+	Xfree (cd->cfh[which]);
+      if (cd->chars_huff[which])
+	Xfree (cd->chars_huff[which]);
+      if (cd->lens_huff[which])
+	Xfree (cd->lens_huff[which]);
+      if (cd->values[which])
+	{
+	  Xfree (cd->values[which][0][0]); /* [RJM 07/98: Memory Leak] */
+	  Xfree (cd->values[which][0]);
+	  Xfree (cd->values[which]);
+	}
+      if (cd->chars_vals[which])
+	{
+	  Xfree (cd->chars_vals[which][0]);
+	  Xfree (cd->chars_vals[which]);
+	}
+      if (cd->lens_vals[which])
+	{
+	  Xfree (cd->lens_vals[which][0]);
+	  Xfree (cd->lens_vals[which]);
+	}
+    }
+  if (cd->ad)
+    FreeAuxDict (cd->ad);
+  Xfree (cd);
+}
+
+
+
+
+
+#define MY_HUFF_DECODE(len, code, mcodes)				\
+  do {									\
+    register unsigned long *__min_code = (mcodes);			\
+    register unsigned long *__mclen = __min_code;			\
+    register unsigned long __code = 0;					\
+    do									\
+      {									\
+        DECODE_ADD(__code);						\
+      }									\
+    while (__code < *++__mclen);					\
+    (len) = __mclen - __min_code;					\
+    (code) = __code - *__mclen;						\
+  } while(0);
+
+
+/*#define DUMPDOC */
+
+#define MAX_SWAPS 10000
+
+int 
+DecodeText (compression_dict * cd,
+	    u_char * s_in, int l_in, u_char * s_out, int *l_out)
+{
+  auxiliary_dict *ad = cd->ad;
+  int which;
+  u_long num_bits, bits;
+  u_char *ptr = s_out;
+  static int num = 0;
+  u_long binary_start[2];
+  int novels_used[2];
+  int swaps[2][MAX_SWAPS];
+  novels_used[0] = novels_used[1] = 0;
+
+  {
+    unsigned char bf = s_in[l_in - 1];
+    num_bits = 1;
+    while ((bf & 1) != 1)
+      {
+	num_bits++;
+	bf >>= 1;
+      }
+    num_bits = l_in * 8 - num_bits;
+  }
+
+  DECODE_START (s_in, l_in)
+
+    which = DECODE_BIT;
+  bits = 1;
+
+  if (cd->cdh.novel_method == MG_NOVEL_BINARY)
+    {
+      DELTA_DECODE_L (binary_start[0], bits);
+      DELTA_DECODE_L (binary_start[1], bits);
+    }
+
+
+  while (bits < num_bits)
+    {
+      register unsigned code, len;
+      register int r;
+      register u_char *t, *b = NULL;
+      u_char word[MAXWORDLEN + 1];
+
+#ifdef DUMPDOC
+      printf ("\n%d %d  ", bits, num_bits);
+#endif
+      if (cd->cfh[which])
+	{
+	  MY_HUFF_DECODE (len, code, cd->cfh[which]->hd.min_code);
+	  bits += len;
+
+	  r = code & ((1 << cd->cdh.lookback) - 1);
+	  t = cd->values[which][len][code >> cd->cdh.lookback];
+
+	  /* step through from base pointer */
+	  b = word + 1;
+	  while (r--)
+	    {
+	      register int copy = *t >> 4;
+	      memcpy (word + copy + 1, t + 1, *t & 0xf);
+	      word[0] = copy + (*t & 0xf);
+	      t += ((*t) & 0xf) + 1;
+	    }
+	}
+      else
+	t = NULL;
+      if (t == cd->escape[which])
+	{
+	  switch (cd->cdh.novel_method)
+	    {
+	    case MG_NOVEL_HUFFMAN_CHARS:
+	      {
+		int len, i;
+		int c;
+		HUFF_DECODE_L (len, cd->lens_huff[which]->min_code,
+			       cd->lens_vals[which], bits);
+		for (i = 0; i < len; i++)
+		  {
+		    HUFF_DECODE_L (c, cd->chars_huff[which]->min_code,
+				   cd->chars_vals[which], bits);
+		    *ptr++ = c;
+		  }
+	      }
+	      break;
+	    case MG_NOVEL_BINARY:
+	    case MG_NOVEL_DELTA:
+	    case MG_NOVEL_HYBRID:
+	    case MG_NOVEL_HYBRID_MTF:
+	      {
+		int idx = 0, len;
+		u_char *base;
+		switch (cd->cdh.novel_method)
+		  {
+		  case MG_NOVEL_BINARY:
+		    {
+		      BINARY_DECODE_L (idx, binary_start[which], bits);
+		      if (idx == binary_start[which])
+			binary_start[which]++;
+		      idx--;
+		    }
+		    break;
+		  case MG_NOVEL_DELTA:
+		    {
+		      DELTA_DECODE_L (idx, bits);
+		      idx--;
+		    }
+		    break;
+		  case MG_NOVEL_HYBRID:
+		    {
+		      int k;
+		      GAMMA_DECODE_L (k, bits);
+		      k--;
+		      BINARY_DECODE_L (idx,
+				       ad->blk_end[which][k] -
+				       ad->blk_start[which][k] + 1, bits);
+		      idx += ad->blk_start[which][k] - 1;
+		    }
+		    break;
+		  case MG_NOVEL_HYBRID_MTF:
+		    {
+		      int k;
+		      GAMMA_DECODE_L (k, bits);
+		      k--;
+		      BINARY_DECODE_L (idx,
+				       ad->blk_end[which][k] -
+				       ad->blk_start[which][k] + 1, bits);
+		      idx += ad->blk_start[which][k] - 1;
+		      if (idx >= novels_used[which])
+			{
+			  u_char *temp;
+			  temp = ad->words[which][idx];
+			  ad->words[which][idx] =
+			    ad->words[which][novels_used[which]];
+			  ad->words[which][novels_used[which]] = temp;
+			  swaps[which][novels_used[which]] = idx;
+			  idx = novels_used[which]++;
+			}
+		    }
+		    break;
+		  }
+		base = ad->words[which][idx];
+		len = *base++;
+#ifdef DUMPDOC
+		printf ("[[");
+#endif
+		for (; len; len--)
+		  {
+		    *ptr++ = *base++;
+#ifdef DUMPDOC
+		    putchar (*(base - 1));
+#endif
+		  }
+#ifdef DUMPDOC
+		printf ("]]");
+#endif
+	      }
+	      break;
+	    }
+	}
+      else
+	{
+	  /* copy over the matching prefix */
+	  r = (*t >> 4);
+	  while (r--)
+#ifndef DUMPDOC
+	    *ptr++ = *b++;
+#else
+	    {
+	      *ptr = *b++;
+	      putchar (*ptr);
+	      ptr++;
+	    }
+#endif
+
+	  /* and the stored suffix */
+	  r = ((*t) & 0xf);
+	  while (r--)
+#ifndef DUMPDOC
+	    *ptr++ = *++t;
+#else
+	    {
+	      *ptr = *++t;
+	      putchar (*ptr);
+	      ptr++;
+	    }
+#endif
+	}
+      which = !which;
+    }
+
+  DECODE_DONE
+
+    * l_out = ptr - s_out;
+  num += *l_out + 1;
+
+  if (cd->cdh.novel_method == MG_NOVEL_HYBRID_MTF)
+    for (which = 0; which <= 1; which++)
+      for (novels_used[which]--; novels_used[which] >= 0; novels_used[which]--)
+	{
+	  int a = novels_used[which];
+	  int b = swaps[which][novels_used[which]];
+	  u_char *temp;
+	  temp = ad->words[which][a];
+	  ad->words[which][a] = ad->words[which][b];
+	  ad->words[which][b] = temp;
+	}
+  return (COMPALLOK);
+}
Index: /indexers/branches/3.03a/mg/src/text/text_get.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/text_get.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/text_get.h	(revision 14757)
@@ -0,0 +1,67 @@
+/**************************************************************************
+ *
+ * text_get.h -- Function for reading documents from the compressed text
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef H_TEXT_GET
+#define H_TEXT_GET
+
+
+
+/* FetchDocStart () 
+ * Reads into DocEnt the starting position of the document in the *.text file
+ * Where the first document is document number 1
+ * It returns the true weight of the document.
+ */
+double FetchDocStart (query_data * qd, u_long DN, u_long * seek_pos, u_long * len);
+
+unsigned long FetchInitialParagraph (text_data * td, unsigned long ParaNum);
+
+
+/* FetchCompressed () 
+ * Reads into buffer DocBuff the compressed form of document DocNum. 
+ * Where the first document is document number 1
+ */
+int FetchCompressed (query_data * qd, char **DocBuff, DocEntry * DocEnt);
+
+text_data *LoadTextData (File * text, File * text_idx_wgt, File * text_idx);
+
+void FreeTextData (text_data * td);
+
+int GetPosLens (query_data * qd, DocEntry * Docs, int num);
+
+int LoadBuffers (query_data * qd, DocEntry * Docs, int max_mem, int num);
+
+void FreeBuffers (query_data * qd, DocEntry * Docs, int num);
+
+
+
+compression_dict *LoadCompDict (File * text_comp_dict,
+				File * text_aux_dict,
+				File * text_fast_comp_dict);
+
+void FreeCompDict (compression_dict * cd);
+
+
+int DecodeText (compression_dict * cd,
+		u_char * s_in, int l_in, u_char * s_out, int *l_out);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/warranty.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/warranty.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/warranty.h	(revision 14757)
@@ -0,0 +1,24 @@
+static char *warranty_str[] = {
+"			    NO WARRANTY\n",
+"\n",
+"  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n",
+"FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n",
+"OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n",
+"PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n",
+"OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n",
+"MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n",
+"TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n",
+"PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n",
+"REPAIR OR CORRECTION.\n",
+"\n",
+"  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n",
+"WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n",
+"REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n",
+"INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n",
+"OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n",
+"TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n",
+"YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n",
+"PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n",
+"POSSIBILITY OF SUCH DAMAGES.\n",
+"\n",
+"		     END OF TERMS AND CONDITIONS\n"};
Index: /indexers/branches/3.03a/mg/src/text/warranty.src
===================================================================
--- /indexers/branches/3.03a/mg/src/text/warranty.src	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/warranty.src	(revision 14757)
@@ -0,0 +1,23 @@
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
Index: /indexers/branches/3.03a/mg/src/text/weights.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/weights.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/weights.c	(revision 14757)
@@ -0,0 +1,161 @@
+/**************************************************************************
+ *
+ * weights.c -- Functions for reading the weights file in mgquery
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "filestats.h"
+#include "memlib.h"
+#include "messages.h"
+#include "timing.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg.h"
+#include "invf.h"
+#include "text.h"
+#include "lists.h"
+#include "backend.h"
+#include "weights.h"
+#include "locallib.h"
+#include "mg_errors.h"
+
+#define MAXBITS (sizeof(unsigned long) * 8)
+
+/*
+   $Log$
+   Revision 1.1  2003/02/20 21:18:24  mdewsnip
+   Addition of MG package for search and retrieval
+
+   Revision 1.1  1999/08/10 21:18:27  sjboddie
+   renamed mg-1.3d directory mg
+
+   Revision 1.1  1998/11/17 09:35:51  rjmcnab
+   *** empty log message ***
+
+   * Revision 1.2  1994/09/20  04:42:18  tes
+   * For version 1.1
+   *
+ */
+
+static char *RCSID = "$Id$";
+
+
+
+approx_weights_data *
+LoadDocWeights (File * weight_file,
+		unsigned long num_of_docs)
+{
+  approx_weights_data *awd;
+  int num;
+
+  if (!(awd = Xmalloc (sizeof (*awd))))
+    {
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  Fseek (weight_file, sizeof (long), 0);
+  Fread (&awd->bits, sizeof (awd->bits), 1, weight_file);
+  Fread (&awd->L, sizeof (awd->L), 1, weight_file);
+  NTOHD(awd->L);  /* [RPAP - Jan 97: Endian Ordering] */
+  Fread (&awd->B, sizeof (awd->B), 1, weight_file);
+  NTOHD(awd->B);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  awd->mask = awd->bits == 32 ? 0xffffffff : (1 << awd->bits) - 1;
+
+  num = (num_of_docs * awd->bits + 31) / 32;
+  if (!(awd->DocWeights = Xmalloc (sizeof (unsigned long) * num)))
+    {
+      Xfree (awd);
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  Fread (awd->DocWeights, sizeof (unsigned long), num, weight_file);
+  {
+    /* [RPAP - Jan 97: Endian Ordering] */
+    unsigned long i;
+    for (i = 0; i < num; i++)
+      NTOHUL(awd->DocWeights[i]);
+  }
+
+  awd->MemForWeights = num * sizeof (unsigned long);
+  awd->num_of_docs = num_of_docs;
+
+  mg_errno = MG_NOERROR;
+
+  if (awd->bits <= 12)
+    {
+      int i, size = (1 << awd->bits);
+      if (!(awd->table = (float *) Xmalloc (size * sizeof (float))))
+	  return (awd);
+      awd->table[0] = awd->L;
+      for (i = 1; i < size; i++)
+	awd->table[i] = awd->table[i - 1] * awd->B;
+    }
+  else
+    awd->table = NULL;
+  return awd;
+}
+
+
+
+
+
+
+/*
+ * the first document in the collection has DocNum = 0
+ */
+float 
+GetLowerApproxDocWeight (approx_weights_data * awd, register int DocNum)
+{
+  register unsigned long c, Pos;
+  register unsigned long *dw;
+  if (awd == NULL)
+    return 1.0;
+#if 0
+  if (DocNum < 0 || DocNum >= awd->num_of_docs)
+    FatalError (1, "Something is wrong in \"GetDocWeight\" DocNum = %d\n",
+		DocNum);
+#endif
+  Pos = DocNum * awd->bits;
+  dw = &(awd->DocWeights[Pos / MAXBITS]);
+  Pos &= (MAXBITS - 1);
+  c = *dw >> Pos;
+  if (Pos + awd->bits > MAXBITS)
+    c |= *(dw + 1) << (MAXBITS - Pos);
+  c &= awd->mask;
+  if (awd->table)
+    return (awd->table[c]);
+  else
+    return (awd->L * pow (awd->B, (double) c));
+
+}
+
+void 
+FreeWeights (approx_weights_data * awd)
+{
+  Xfree (awd->DocWeights);
+  if (awd->table)
+    Xfree (awd->table);
+  Xfree (awd);
+}
Index: /indexers/branches/3.03a/mg/src/text/weights.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/weights.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/weights.h	(revision 14757)
@@ -0,0 +1,34 @@
+/**************************************************************************
+ *
+ * weights.h -- Functions for reading the weights file in mgquery
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+#ifndef H_WEIGHTS
+#define H_WEIGHTS
+
+approx_weights_data *LoadDocWeights (File * weight_file,
+				     unsigned long num_of_docs);
+
+float GetLowerApproxDocWeight (approx_weights_data * awd, register int DocNum);
+
+void FreeWeights (approx_weights_data * awd);
+
+#endif
Index: /indexers/branches/3.03a/mg/src/text/win32.mak
===================================================================
--- /indexers/branches/3.03a/mg/src/text/win32.mak	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/win32.mak	(revision 14757)
@@ -0,0 +1,244 @@
+###########################################################################
+#
+# win32 makefile -- mg\src\text
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999  The New Zealand Digital Library Project
+#
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+ 
+MGHOME = ..\..
+# for now put executables in indexers/bin
+INSTALLDIR = ..\..\..\bin
+
+AR = lib
+
+CC = cl
+CPPFLAGS = 
+# DEFS = -DQUIET -D__WIN32__ -DSHORT_SUFFIX -DHAVE_STRING_H -DHAVE_FCNTL_H \
+#        -DSTDC_HEADERS -DHAVE_CONFIG_H
+DEFS = -DNZDL -DQUIET -DSHORT_SUFFIX -DPARADOCNUM -DHAVE_CONFIG_H \
+       -D__WIN32__ -D_LITTLE_ENDIAN
+INCLUDES = -I"." -I"$(MGHOME)" -I"$(MGHOME)\lib"
+COMPILE = $(CC) $(CPPFLAGS) -c $(DEFS) $(INCLUDES)
+
+LDFLAGS =
+LINK = $(CC) $(LDFLAGS)
+
+LIBS = "$(MGHOME)\lib\libmglib.lib"
+
+.SUFFIXES: .c .cpp .obj
+.c.obj:
+	$(COMPILE) $<
+.cpp.obj:
+	$(COMPILE) $<
+
+o = .obj
+e = .exe
+
+HEADERS = \
+  backend.h          conditions.h       locallib.h         term_lists.h \
+  bool_optimiser.h   environment.h      mg.h               text.h       \
+  bool_parser.h      globals.h          mg_errors.h        text_get.h   \
+  bool_query.h       hash.h             mg_files.h         warranty.h   \
+  bool_tree.h        help.mg.h          mg_merge.h         weights.h    \
+  build.h            invf.h             read_line.h        words.h      \
+  commands.h         invf_get.h         stem_search.h                   \
+  comp_dict.h        lists.h            stemmer.h          query_term_list.h
+
+SOURCES = \
+  backend.c               locallib.c              mg_weights_build.c   \
+  bool_optimiser.c        mg.special.c            mgdictlist.c         \
+  bool_parser.c           mg_compression_dict.c   mgquery.c            \
+  bool_query.c            mg_errors.c             mgstat.c             \
+  bool_tester.c           mg_fast_comp_dict.c     mg_decompress_text.c \
+  bool_tree.c             mg_files.c              query.docnums.c      \
+  commands.c              mg_hilite_words.c       query.ranked.c       \
+  comp_dict.c             mg_invf_dict.c          read_line.c          \
+  environment.c           mg_invf_dump.c          stem_search.c        \
+  mg_invf_merge.c         stemmer.c               mg_stem_idx.c        \
+  mg_invf_rebuild.c       term_lists.c            mgstemidxlist.c      \
+  invf_get.c              mg_passes.c             text.pass1.c         \
+  ivf.pass1.c             mg_perf_hash_build.c    text.pass2.c         \
+  ivf.pass2.c             mg_text_estimate.c      text_get.c           \
+  lists.c                 mg_text_merge.c         weights.c            \
+  mgpass.c                query_term_list.c       words.c              \
+  mg_passes_4jni.c
+
+EXEC = \
+  mgquery$e mg_weights_build$e mgstat$e \
+  mg_invf_dump$e     mg_invf_dict$e \
+  mg_invf_rebuild$e     mgdictlist$e \
+  mg_passes$e     mg_perf_hash_build$e \
+  mg_compression_dict$e     mg_text_estimate$e \
+  mg_fast_comp_dict$e \
+  mg_hilite_words$e     mg_invf_merge$e \
+  mg_text_merge$e     bool_tester$e  mgpass$e \
+  mg_stem_idx$e  mgstemidxlist$e \
+  mg_decompress_text$e 
+
+all: $(EXEC) libmgtext.lib libmgpass.lib
+
+HILITE_OBJS = mg_hilite_words$o stemmer$o locallib$o words$o environment$o
+mg_hilite_words$e: $(HILITE_OBJS)
+	$(LINK) $(HILITE_OBJS) $(LIBS)
+
+BOOL_OBJS = bool_tester$o bool_tree$o bool_parser$o bool_optimiser$o  \
+	    term_lists$o stemmer$o stem_search$o mg_errors$o \
+	    query_term_list$o words$o environment$o
+
+bool_tester$e: $(BOOL_OBJS)
+	$(LINK) $(BOOL_OBJS) $(LIBS)
+
+QUERY_OBJS = \
+	mgquery$o locallib$o lists$o \
+	query.ranked$o query.docnums$o stem_search$o \
+	environment$o commands$o weights$o text_get$o stemmer$o \
+	read_line$o mg_errors$o backend$o invf_get$o \
+	term_lists$o bool_tree$o bool_parser$o bool_optimiser$o bool_query$o \
+	query_term_list$o words$o
+mgquery$e: $(QUERY_OBJS)
+	$(LINK) $(READLINE) $(QUERY_OBJS) $(READLINE_LIBS) $(LIBS)
+
+commands$o : help.mg.h warranty.h conditions.h
+
+PASSES_OBJS = \
+	mg_passes$o text.pass1$o comp_dict$o stemmer$o \
+	text.pass2$o locallib$o \
+	ivf.pass1$o ivf.pass2$o mg.special$o mg_files$o \
+	words$o environment$o
+mg_passes$e: $(PASSES_OBJS)
+	$(LINK) $(PASSES_OBJS) $(LIBS)
+
+PASS_OBJS = \
+	 mgpass$o words$o text.pass1$o comp_dict$o stemmer$o \
+	text.pass2$o locallib$o \
+	ivf.pass1$o ivf.pass2$o mg.special$o mg_files$o environment$o
+mgpass$e: $(PASS_OBJS)
+	$(LINK) $(PASS_OBJS) $(LIBS)
+
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib
+
+BUILDER_OBJS = \
+	builder$o
+builder$e: $(BUILDER_OBJS)
+	$(LINK) $(BUILDER_OBJS) $(LIBS) $(LINK32_FLAGS)
+
+WEIGHTS_BUILD_OBJS = mg_weights_build$o mg_files$o
+mg_weights_build$e: $(WEIGHTS_BUILD_OBJS)
+	$(LINK) $(WEIGHTS_BUILD_OBJS) $(LIBS)
+
+COMP_DICT_OBJS = mg_compression_dict$o mg_files$o locallib$o
+mg_compression_dict$e: $(COMP_DICT_OBJS)
+	$(LINK) $(COMP_DICT_OBJS) $(LIBS)
+
+FAST_COMP_OBJS = mg_fast_comp_dict$o mg_files$o locallib$o
+mg_fast_comp_dict$e: $(FAST_COMP_OBJS)
+	$(LINK) $(FAST_COMP_OBJS) $(LIBS)
+
+TEXT_EST_OBJS = mg_text_estimate$o locallib$o comp_dict$o mg_files$o
+mg_text_estimate$e: $(TEXT_EST_OBJS)
+	$(LINK) $(TEXT_EST_OBJS) $(LIBS)
+
+STAT_OBJS = mgstat$o mg_files$o locallib$o
+mgstat$e: $(STAT_OBJS)
+	$(LINK) $(STAT_OBJS) $(LIBS)
+
+INVF_DUMP_OBJS = mg_invf_dump$o locallib$o mg_files$o
+mg_invf_dump$e: $(INVF_DUMP_OBJS)
+	$(LINK) $(INVF_DUMP_OBJS) $(LIBS)
+
+INVF_DICT_OBJS = mg_invf_dict$o mg_files$o locallib$o
+mg_invf_dict$e: $(INVF_DICT_OBJS)
+	$(LINK) $(INVF_DICT_OBJS) $(LIBS)
+
+INVF_REB_OBJS = mg_invf_rebuild$o locallib$o
+mg_invf_rebuild$e: $(INVF_REB_OBJS)
+	$(LINK) $(INVF_REB_OBJS) $(LIBS)
+
+DICTLIST_OBJS = mgdictlist$o locallib$o
+mgdictlist$e: $(DICTLIST_OBJS)
+	$(LINK) $(DICTLIST_OBJS) $(LIBS)
+
+PERF_HASH_OBJS = mg_perf_hash_build$o mg_files$o
+mg_perf_hash_build$e: $(PERF_HASH_OBJS)
+	$(LINK) $(PERF_HASH_OBJS) $(LIBS)
+
+STEM_IDX_OBJS = mg_stem_idx$o mg_files$o stemmer$o locallib$o \
+                mg_errors$o term_lists$o
+mg_stem_idx$e: $(STEM_IDX_OBJS)
+	$(LINK) $(STEM_IDX_OBJS) $(LIBS)
+
+STEM_IDX_LIST_OBJS = mgstemidxlist$o mg_files$o
+mgstemidxlist$e: $(STEM_IDX_LIST_OBJS)
+	$(LINK) $(STEM_IDX_LIST_OBJS) $(LIBS)
+
+DECOMPRESS_TEXT_OBJS = mg_decompress_text$o query_term_list$o mg_files$o \
+		       mg_errors$o \
+                       text_get$o locallib$o backend$o stem_search$o \
+                       term_lists$o stemmer$o weights$o invf_get$o lists$o
+mg_decompress_text$e: $(DECOMPRESS_TEXT_OBJS)
+	$(LINK) $(DECOMPRESS_TEXT_OBJS) $(LIBS)
+
+TEXT_MERGE_OBJS = mg_text_merge$o mg_files$o locallib$o
+mg_text_merge$e: $(TEXT_MERGE_OBJS)
+	$(LINK) $(TEXT_MERGE_OBJS) $(LIBS)
+
+INVF_MERGE_OBJS = mg_invf_merge$o mg_files$o locallib$o
+mg_invf_merge$e: $(INVF_MERGE_OBJS)
+	$(LINK) $(INVF_MERGE_OBJS) $(LIBS)
+
+LIB_OBJS = \
+	query_term_list$o \
+	locallib$o lists$o \
+	query.ranked$o query.docnums$o stem_search$o \
+	environment$o commands$o weights$o text_get$o stemmer$o \
+	read_line$o mg_errors$o backend$o invf_get$o \
+	term_lists$o bool_tree$o bool_parser$o bool_optimiser$o \
+        bool_query$o words$o
+
+JNI_LIB_OBJS = \
+	mg_passes_4jni$o text.pass1$o comp_dict$o stemmer$o \
+	text.pass2$o locallib$o  words$o environment$o \
+	ivf.pass1$o ivf.pass2$o mg.special$o mg_files$o 
+
+
+DISTFILES = Makefile.in $(HEADERS) $(SOURCES)
+
+libmgtext.lib : $(LIB_OBJS)
+        if exist libmgtext.lib del libmgtext.lib
+	$(AR) /out:libmgtext.lib $(LIB_OBJS)
+
+libmgpass.lib : $(JNI_LIB_OBJS)
+ 	  if exist libmgpass.lib del libmgpass.lib
+	$(AR) /out:libmgpass.lib $(JNI_LIB_OBJS)
+
+install: 
+	if not exist "$(INSTALLDIR)" mkdir "$(INSTALLDIR)"
+	for %%i in ($(EXEC)) do \
+	  copy %%i "$(INSTALLDIR)"
+
+clean:
+        if exist *$o del *$o 
+	if exist *$e del *$e
+        if exist libmgtext.lib del libmgtext.lib
+        if exist libmgpass.lib del libmgpass.lib
Index: /indexers/branches/3.03a/mg/src/text/words.c
===================================================================
--- /indexers/branches/3.03a/mg/src/text/words.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/words.c	(revision 14757)
@@ -0,0 +1,34 @@
+#include "words.h"
+
+
+/* Takes the place of the old INAWORD macro. It determines
+   whether a given place in a UTF-8 encoded Unicode string
+   is part of a word. */
+int inaword (const u_char *here, const u_char *end) {
+  unsigned short c;
+  if (parse_utf8_char(here, end, &c) > 0) return is_unicode_letdig (c);
+  return 0;
+}
+
+/* Return a the UTF-8 encoded Unicode string with begining
+   unicode spaces skipped. */
+u_char *skipspace(u_char *here, u_char *end)
+{
+  unsigned short c;	
+  int length;
+  while(here != end) {
+    length = parse_utf8_char(here, end, &c);
+    if (length == 0 || !is_unicode_space(c)) break;
+    here += length;
+  }
+  return here;
+}
+
+/* It determines whether a given place in a UTF-8 encoded 
+   Unicode string is a unicode space. */
+int isaspace (const u_char *here, const u_char *end)
+{
+  unsigned short c;
+  if (parse_utf8_char(here, end, &c) > 0) return is_unicode_space(c);
+  return 0;
+}
Index: /indexers/branches/3.03a/mg/src/text/words.h
===================================================================
--- /indexers/branches/3.03a/mg/src/text/words.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/src/text/words.h	(revision 14757)
@@ -0,0 +1,395 @@
+/**************************************************************************
+ *
+ * words.h -- Macros for parsing out words from the source text
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#include "sysfuncs.h"
+#include "unitool.h"
+
+/*
+ * This has been cleaned up by Tim Shimmin. 
+ */
+
+/*
+ * ---NOTE---
+ *
+ * "WORD" refers to a word in the compressed text.
+ * "STEM" or "STEM_WORD" refers to a word for indexing on
+ *
+ */
+
+#define MAXWORDLEN	15
+	/* Maximum length in bytes of any word or non-word. Note that
+	   variations to MAXWORDLEN may have dramatic effects on the rest
+	   of the program, as the length and the prefix match are packed
+	   together into a four bit nibble, and there is not check that
+	   this is possible, i.e., leave MAXWORDLEN alone... */
+
+#define MAXSTEMLEN	255
+	/* Maximum length in bytes of any stem. Note that
+	   variations to MAXSTEMLEN may have dramatic effects on the rest
+	   of the program, , i.e., leave MAXSTEMLEN alone... */
+
+/*#define MAXNUMERIC	4*/
+
+	/* Maximum number of numeric characters permitted in a word.
+	   This avoids long sequences of numbers creating just one
+	   word occurrence for each number. At most 10,000 all numeric
+	   words will be permitted. */
+
+/* [RPAP - Jan 97: Stem Index Change] */
+#define MAXPARAMLEN     20
+        /* Maximum number of bytes to read for a parameter value for a
+	   term in a query. */
+#define WEIGHTPARAM     '/'
+#define STEMPARAM       '#'
+
+/* [RJM 07/97: Ranked Required Terms] */
+#define MUSTMATCHPARAM     '+'
+
+
+#define PESINAWORD(c)      (isalnum(c) || ((c) >= 0x80 && (c) <= 0xff))
+        /* The definition of what characters are permitted in a word.
+	   This macro is pessimistic, you cannot tell from a particular
+	   byte above 0x80 whether it is a character or not. This function
+	   is needed by various functions relating to huffman coding
+	   where frequency counts need to be primed, it should not be
+	   used in parsing the UTF-8 encoded input. */
+
+int inaword (const u_char *here, const u_char *end);
+        /* Takes the place of the old INAWORD macro. It determines
+	   whether a given place in a UTF-8 encoded Unicode string
+	   is part of a word. */
+
+int isaspace (const u_char *here, const u_char *end);
+        /* It determines whether a given place in a UTF-8 encoded 
+	   Unicode string is a unicode space. */
+ 
+u_char *skipspace(u_char *here, u_char *end);
+        /* Return a the UTF-8 encoded Unicode string with beginning 
+	   unicode spaces skipped. */
+ 
+
+/* =========================================================================
+ * Macro: PARSE_WORD
+ * Description: 
+ *      Extract a word out for compressing text
+ * Input: 
+ *      s_in = string start in buffer
+ *      end = string end in buffer
+ * Output: 
+ *      Word = extracted word with length in 1st byte
+ *      s_in = ptr to next character in buffer yet to be processed
+ * ========================================================================= */
+#define PARSE_WORD(Word, s_in, end)                                \
+  do {                                                             \
+    register int charlength = 0;                                   \
+    register u_char *wptr = (Word)+1;                              \
+    register int length = 0;                                       \
+    register int numeric = 0;                                      \
+    unsigned short c;                                              \
+    register int maxnumeric = IntEnv (GetEnv ("maxnumeric"), 4);   \
+                                                                   \
+    charlength = parse_utf8_char((s_in),(end),&c);                 \
+                                                                   \
+    while (length+charlength <= MAXWORDLEN && charlength > 0 &&    \
+	   (is_unicode_letter(c) || (is_unicode_digit(c) &&        \
+				     ++numeric <= maxnumeric))) {  \
+      while (charlength-- > 0) {                                   \
+        *wptr++ = *(s_in)++; ++length;                             \
+      }                                                            \
+      charlength = parse_utf8_char((s_in),(end),&c);               \
+    }                                                              \
+    *(Word) = length;                                              \
+  }while(0)
+
+  /*  
+#define PARSE_WORD(Word, s_in, end)                                  \
+  do {                                                               \
+	  register u_char  *wptr = (Word)+1;                         \
+	  register int    length = 0;                                \
+	  register int    c = *(s_in);                               \
+	  register int	numeric = 0;                                 \
+                                                                     \
+	  while( length < MAXWORDLEN && INAWORD(c) && (s_in)<=(end)) \
+	    {                                                        \
+	      if ((numeric += INNUMBER(c)) > MAXNUMERIC)             \
+		break;                                               \
+	      *wptr++ = c;                                           \
+	      ++length;                                              \
+	      c = *++(s_in);                                         \
+	    }                                                        \
+	  *(Word) = length;                                          \
+  }while(0)
+  */
+
+
+/* =========================================================================
+ * Macro: PARSE_NON_WORD
+ * Description: 
+ *      Extract a non-word out for storing compressed text
+ * Input: as above
+ * Output: as above
+ * ========================================================================= */
+#define PARSE_NON_WORD(Word, s_in, end)                            \
+  do {                                                             \
+    register int charlength = 0;                                   \
+    register u_char *wptr = (Word)+1;                              \
+    register int length = 0;                                       \
+    unsigned short c;                                              \
+                                                                   \
+    charlength = parse_utf8_char((s_in),(end),&c);                 \
+                                                                   \
+    while (length+charlength <= MAXWORDLEN && charlength > 0 &&    \
+	   !is_unicode_letdig(c)) {                                \
+      while (charlength-- > 0) {                                   \
+        *wptr++ = *(s_in)++; ++length;                             \
+      }                                                            \
+      charlength = parse_utf8_char((s_in),(end),&c);               \
+    }                                                              \
+    *(Word) = length;                                              \
+  }while(0)
+
+    /*
+#define PARSE_NON_WORD(Word, s_in, end)                            \
+  do {                                                             \
+	  register u_char  *wptr = (Word)+1;                       \
+	  register int    length = 0;                              \
+	  register int    c = *(s_in);                             \
+                                                                   \
+	  while( length < MAXWORDLEN && !INAWORD(c) && (s_in)<=(end) ) \
+	    {                                                      \
+	      *wptr++ = c;                                         \
+	      ++length;                                            \
+	      c = *++(s_in);                                       \
+	    }                                                      \
+	  *(Word) = length;                                        \
+  }while(0)
+    */
+
+
+/* =========================================================================
+ * Macro: PARSE_STEM_WORD 
+ * Description: 
+ *      Extracts out Word.      
+ * Input: 
+ *      s_in points to 1st letter in buffer to test
+ *      end points to last letter in buffer
+ * Output: 
+ *      s_in is modified to move to next word
+ *      Returns Word filled in with length in 1st byte.
+ * ========================================================================= */
+#define PARSE_STEM_WORD(Word, s_in, end)                           \
+  do {                                                             \
+    register int charlength = 0;                                   \
+    register u_char *wptr = (Word)+1;                              \
+    register int length = 0;                                       \
+    register int numeric = 0;                                      \
+    unsigned short c;                                              \
+    register int maxnumeric = IntEnv (GetEnv ("maxnumeric"), 4);   \
+                                                                   \
+    charlength = parse_utf8_char((s_in),(end),&c);                 \
+                                                                   \
+    while (length+charlength <= MAXSTEMLEN && charlength > 0 &&    \
+	   (is_unicode_letter(c) || (is_unicode_digit(c) &&        \
+				     ++numeric <= maxnumeric))) {  \
+      while (charlength-- > 0) {                                   \
+        *wptr++ = *(s_in)++; ++length;                             \
+      }                                                            \
+      charlength = parse_utf8_char((s_in),(end),&c);               \
+    }                                                              \
+    *(Word) = length;                                              \
+  }while(0)
+    /*
+#define PARSE_STEM_WORD(Word, s_in, end)                      \
+  do                                                          \
+    {                                                         \
+      register u_char  *wptr = (Word)+1;                      \
+      register int    length = 0;                             \
+      register int    c = *(s_in);                            \
+      register int    numeric = 0;                            \
+                                                              \
+      while ( length < MAXSTEMLEN && INAWORD(c) && (s_in)<=(end)) \
+        {                                                     \
+ 	  if ((numeric += INNUMBER(c)) > MAXNUMERIC)          \
+	    break;                                            \
+	  *wptr++ = c;                                        \
+	  ++length;                                           \
+	  c = *++(s_in);                                      \
+	}                                                     \
+      *(Word) = length;                                       \
+    }while(0)
+    */
+
+
+/* =========================================================================
+ * Macro: PARSE_NON_STEM_WORD 
+ * Description: 
+ *      Eat up non-word. Do not store non-word.
+ *      It is not needed in index only in text !
+ *      
+ * Input: as above but no Word needed
+ * Output: as above
+ * ========================================================================= */
+#define PARSE_NON_STEM_WORD(s_in, end)                             \
+  do {                                                             \
+    register int charlength = 0;                                   \
+    unsigned short c;                                              \
+                                                                   \
+    charlength = parse_utf8_char((s_in),(end),&c);                 \
+                                                                   \
+    while (charlength > 0 && !is_unicode_letdig(c)) {              \
+      (s_in) += charlength;                                        \
+      charlength = parse_utf8_char((s_in),(end),&c);               \
+    }                                                              \
+  }while(0)
+
+    /*
+#define PARSE_NON_STEM_WORD(s_in, end)           \
+  do                                             \
+    {                                            \
+      while (!INAWORD(*(s_in)) && (s_in)<=(end)) \
+	(s_in)++;                                \
+    }while(0)
+    */
+
+
+/* =========================================================================
+ * Macro: PARSE_NON_STEM_WORD_OR_SGML_TAG 
+ * Description: 
+ *      Like PARSE_NON_STEM_WORD but also eats up SGML tags
+ * Input: as above
+ * Output: as above
+ * ========================================================================= */
+#define PARSE_NON_STEM_WORD_OR_SGML_TAG(s_in, end)                 \
+  do {                                                             \
+    register int charlength = 0;                                   \
+    unsigned short c;                                              \
+                                                                   \
+    charlength = parse_utf8_char((s_in),(end),&c);                 \
+                                                                   \
+    while (charlength > 0 && !is_unicode_letdig(c)) {              \
+      if (c == '<') {                                              \
+	while (charlength > 0 && c != '>') {                       \
+	  (s_in) += charlength;                                    \
+	  charlength = parse_utf8_char((s_in),(end),&c);           \
+	}                                                          \
+      }                                                            \
+      (s_in) += charlength;                                        \
+      charlength = parse_utf8_char((s_in),(end),&c);               \
+    }                                                              \
+  }while(0)
+
+    /*
+#define PARSE_NON_STEM_WORD_OR_SGML_TAG(s_in, end) \
+  do                                               \
+    {                                              \
+      register int    c = *(s_in);                 \
+                                                   \
+      while (!INAWORD(c) && (s_in)<=(end))         \
+        {                                          \
+	  if (c == '<')                            \
+            {                                      \
+	      while (c != '>' && (s_in)<=(end))    \
+		c = *++(s_in);                     \
+            }                                      \
+	  if ((s_in)<=(end))                       \
+	    c = *++(s_in);                         \
+	}                                          \
+    }while(0)
+    */
+
+
+/* =========================================================================
+ * Macro: PARSE_OPT_TERM_PARAM     [RPAP - Jan 97: Stem Index Change]
+ * Description: 
+ *      Extracts out optional paramater for query term.
+ *      Needed only in parsing the query line !
+ *
+ *      Note: that this function has not been converted to use UTF-8
+ *            as it should still work as it is (only uses ascii
+ *            characters)
+ *      
+ * Input: as above but no Word needed
+ * Output: as above
+ * ========================================================================= */
+#define PARSE_OPT_TERM_PARAM(Param, type, s_in, end)                       \
+  do                                                                       \
+    {                                                                      \
+	  register u_char  *wptr = (Param);                                \
+	  register int    length = 0;                                      \
+	  register int    c = *(s_in);                                     \
+                                                                           \
+          if (c == WEIGHTPARAM || c == STEMPARAM)                          \
+	    {                                                              \
+	      type = c;                                                    \
+	      c = *++(s_in);                                               \
+	      while( length < MAXPARAMLEN && isdigit(c) && (s_in)<=(end))  \
+		{                                                          \
+	           *wptr++ = c;                                            \
+	           ++length;                                               \
+	           c = *++(s_in);                                          \
+	        }                                                          \
+	      *wptr = '\0';                                                \
+              for (; isdigit(c) && (s_in)<=(end); c = *++(s_in))           \
+                ;                                                          \
+            }							           \
+    }while(0)
+
+/* =========================================================================
+ * Macro: PARSE_RANKED_NON_STEM_WORD    [RJM 07/97: Ranked Required Terms]
+ * Description: 
+ *      Eat up non-word. Do not store non-word.
+ *      If come across a match requirement store it in require_match
+ *      It is not needed in index only in text !
+ *      
+ * Input: as above
+ * Output: the requirement mode for the next term. -1=must not match,
+ *      0=optional match, 1=must match
+ * ========================================================================= */
+#define PARSE_RANKED_NON_STEM_WORD(require_match, s_in, end)       \
+  do {                                                             \
+    register int charlength = 0;                                   \
+    unsigned short c;                                              \
+    (require_match) = 0;                                           \
+                                                                   \
+    charlength = parse_utf8_char((s_in),(end),&c);                 \
+                                                                   \
+    while (charlength > 0 && !is_unicode_letdig(c)) {              \
+      if (c == MUSTMATCHPARAM) (require_match) = 1;                \
+      (s_in) += charlength;                                        \
+      charlength = parse_utf8_char((s_in),(end),&c);               \
+    }                                                              \
+  }while(0)
+
+    /*
+#define PARSE_RANKED_NON_STEM_WORD(require_match, s_in, end)         \
+  do {                                            \
+    (require_match) = 0;                          \
+    while (!INAWORD(*(s_in)) && (s_in)<=(end)) {  \
+      if (*(s_in) == MUSTMATCHPARAM) {            \
+        (require_match) = 1;                      \
+      }                                           \
+      (s_in)++;                                   \
+    }                                             \
+  } while (0)
+    */
Index: /indexers/branches/3.03a/mg/stamp-h.in
===================================================================
--- /indexers/branches/3.03a/mg/stamp-h.in	(revision 14757)
+++ /indexers/branches/3.03a/mg/stamp-h.in	(revision 14757)
@@ -0,0 +1,1 @@
+timestamp
Index: /indexers/branches/3.03a/mg/stemmerinterface.c
===================================================================
--- /indexers/branches/3.03a/mg/stemmerinterface.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/stemmerinterface.c	(revision 14757)
@@ -0,0 +1,39 @@
+#include "lib/lovinstem.h"
+#include <stdio.h>
+#include <ctype.h>
+
+int main () {
+  char word[256];
+  char c;
+  int len;
+
+  c = fgetc (stdin);
+  while (!feof (stdin)) {
+    /* output non words */
+    while (!feof (stdin) && !isalnum (c)) {
+      fputc (c, stdout);
+      c = fgetc (stdin);
+    }
+
+    /* get the word */
+    len = 0;
+    while (!feof (stdin) && isalnum (c) && len < 255) {
+      len++;
+      word[len] = c;
+      c = fgetc (stdin);
+    }
+    word[0] = len;
+
+    /* if we found a word stem and output it */
+    if (len > 0) {
+      lovinstem (word);
+      len = 0;
+      while (len < word[0]) {
+        len++;
+        fputc(word[len], stdout);
+      }
+    }
+  }
+}
+
+
Index: /indexers/branches/3.03a/mg/sysfuncs.h
===================================================================
--- /indexers/branches/3.03a/mg/sysfuncs.h	(revision 14757)
+++ /indexers/branches/3.03a/mg/sysfuncs.h	(revision 14757)
@@ -0,0 +1,362 @@
+/* System dependent definitions for GNU tar.
+   Copyright (C) 1994 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 program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * [TS:Aug/95]
+ * Based on code from system.h file in GNU's tar package 
+ *
+ */
+
+#ifndef SYSFUNCS_H
+#define SYSFUNCS_H
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef HAVE_CONFIG_H
+# ifdef __WIN32__
+#  include <WIN32cfg.h>
+# else
+#  include <config.h>
+# endif
+#endif
+
+/* Declare alloca.  AIX requires this to be the first thing in the file.  */
+
+#ifdef __GNUC__
+#ifndef alloca
+#define alloca __builtin_alloca
+#endif
+#else
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#else
+#ifdef _AIX
+#pragma alloca
+#else
+#ifndef alloca
+char *alloca ();
+#endif
+#endif
+#endif
+#endif
+
+#include <sys/types.h>
+
+/* ------------------------------------------------- */
+/* [TS:Aug/95]
+ * Some extra include files that mg needs
+ */
+#include <stdlib.h>
+#include <math.h>
+
+#ifndef log2
+# ifndef M_LN2
+#  define M_LN2 0.69314718055994530942
+# endif
+# define log2(x) (log(x)/M_LN2)
+#endif
+
+
+#ifndef HAVE_SETBUFFER
+# define setbuffer(f, b, s)  setvbuf(f, b, _IOFBF, s)
+#endif
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#if defined(__MSDOS__)  && !defined(__WIN32__)
+# define SHORT_SUFFIX 1
+#endif
+
+
+
+#include <assert.h>
+
+/* ------------------------------------------------- */
+
+/* Declare a generic pointer type.  */
+#if __STDC__ || defined(__TURBOC__)
+#define voidstar void *
+#else
+#define voidstar char *
+#endif
+
+/* Declare ISASCII.  */
+
+#include <ctype.h>
+
+#if STDC_HEADERS
+#define ISASCII(Char) 1
+#else
+#ifdef isascii
+#define ISASCII(Char) isascii (Char)
+#else
+#if HAVE_ISASCII
+#define ISASCII(Char) isascii (Char)
+#else
+#define ISASCII(Char) 1
+#endif
+#endif
+#endif
+
+
+/* ------------------------------------------------- */
+/* [TS:Aug/95] 
+ * The following is copied from GNU Autoconf.Info (1.1)   
+ * It sets up the approriate string and memory functions.
+ */
+
+#if STDC_HEADERS || HAVE_STRING_H
+#include <string.h>
+   /* An ANSI string.h and pre-ANSI memory.h might conflict */
+#if !STDC_HEADERS && HAVE_MEMORY_H
+#include <memory.h>
+#endif /* not STDC_HEADERS and HAVE_MEMORY_H */
+#ifndef index
+/*#define index strchr 
+ *
+ * this is stuffing up our code so its commented out */
+#endif
+#ifndef rindex
+#define rindex strrchr
+#endif
+#ifndef bcopy
+#define bcopy(s, d, n) memcpy((d), (s), (n))
+#endif
+#ifndef bcmp
+#define bcmp(s1, s2, n) memcmp((s1), (s2), (n))
+#endif
+#ifndef bzero
+#define bzero(s, n) memset((s), 0, (n))
+#endif
+#else /* not STDC_HEADERS and not HAVE_STRING_H */
+#include <strings.h>
+   /* memory.h and strings.h conflict on some systems */
+#endif
+/* ------------------------------------------------- */
+
+
+/* Declare errno.  */
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+/* Declare open parameters.  */
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#include <sys/file.h>
+#endif
+
+#ifndef	O_BINARY
+#define O_BINARY 0
+#endif
+#ifndef O_CREAT
+#define O_CREAT 0
+#endif
+#ifndef	O_NDELAY
+#define O_NDELAY 0
+#endif
+#ifndef	O_RDONLY
+#define O_RDONLY 0
+#endif
+#ifndef O_RDWR
+#define O_RDWR 2
+#endif
+
+/* Declare file status routines and bits.  */
+
+#include <sys/stat.h>
+
+#ifdef STAT_MACROS_BROKEN
+#undef S_ISBLK
+#undef S_ISCHR
+#undef S_ISDIR
+#undef S_ISFIFO
+#undef S_ISLNK
+#undef S_ISMPB
+#undef S_ISMPC
+#undef S_ISNWK
+#undef S_ISREG
+#undef S_ISSOCK
+#endif
+
+/* On MSDOS, there are missing things from <sys/stat.h>.  */
+#if defined(__MSDOS__)
+#define S_ISUID 0
+#define S_ISGID 0
+#define S_ISVTX 0
+#endif
+
+#if defined(__GNUC__) && defined(__WIN32__)
+#include <limits.h>
+#endif
+
+#ifndef S_ISREG			/* POSIX.1 stat stuff missing */
+#define mode_t unsigned short
+#endif
+#if !defined(S_ISBLK) && defined(S_IFBLK)
+#define S_ISBLK(Mode) (((Mode) & S_IFMT) == S_IFBLK)
+#endif
+#if !defined(S_ISCHR) && defined(S_IFCHR)
+#define S_ISCHR(Mode) (((Mode) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISDIR) && defined(S_IFDIR)
+#define S_ISDIR(Mode) (((Mode) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG) && defined(S_IFREG)
+#define S_ISREG(Mode) (((Mode) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISFIFO) && defined(S_IFIFO)
+#define S_ISFIFO(Mode) (((Mode) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+#define S_ISLNK(Mode) (((Mode) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK) && defined(S_IFSOCK)
+#define S_ISSOCK(Mode) (((Mode) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISMPB) && defined(S_IFMPB)	/* V7 */
+#define S_ISMPB(Mode) (((Mode) & S_IFMT) == S_IFMPB)
+#define S_ISMPC(Mode) (((Mode) & S_IFMT) == S_IFMPC)
+#endif
+#if !defined(S_ISNWK) && defined(S_IFNWK)	/* HP/UX */
+#define S_ISNWK(Mode) (((Mode) & S_IFMT) == S_IFNWK)
+#endif
+
+#if !defined(S_ISCTG) && defined(S_IFCTG)	/* contiguous file */
+#define S_ISCTG(Mode) (((Mode) & S_IFMT) == S_IFCTG)
+#endif
+#if !defined(S_ISVTX)
+#define S_ISVTX 0001000
+#endif
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#if !defined(_POSIX_SOURCE) && !defined(__WIN32__)
+#include <sys/param.h>
+#endif
+
+/* Include <unistd.h> before any preprocessor test of _POSIX_VERSION.  */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+
+/* Declare standard functions.  */
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+voidstar malloc ();
+voidstar realloc ();
+char *getenv ();
+#endif
+
+#include <stdio.h>
+
+#ifndef _POSIX_VERSION
+#if defined(__WIN32__)
+#include <io.h>
+#define lseek _lseek
+#elif defined(__MSDOS__)
+#include <io.h>
+#else
+off_t lseek ();
+#endif
+#endif
+
+#include <pathmax.h>
+
+/* jrm21 2003 - this is in unistd.h now */
+#ifndef HAVE_UNISTD_H
+#include <getopt.h>
+#endif
+
+#ifdef WITH_DMALLOC
+#undef HAVE_VALLOC
+#define DMALLOC_FUNC_CHECK
+#include <dmalloc.h>
+#endif
+
+/* Prototypes for external functions.  */
+
+#ifndef __P
+#if PROTOTYPES
+#define __P(Args) Args
+#else
+#define __P(Args) ()
+#endif
+#endif
+
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#if ENABLE_NLS
+#include <libintl.h>
+#define _(Text) gettext (Text)
+#else
+#define textdomain(Domain)
+#define _(Text) Text
+#endif
+
+/* Library modules.  */
+
+#if (HAVE_VPRINTF || HAVE_DOPRNT) && __STDC__
+/*void error __P ((int, int, const char *,...));*/
+void error (int, int, const char *,...);
+#else
+void error (int, int, char *, char *, char *, char *, char *, char *, char *, char *, char *);
+#endif
+
+#ifndef HAVE_STRSTR
+char *strstr __P ((const char *, const char *));
+#endif
+
+/* [RB/TS:Oct/95] commented out. Used by lib/gmalloc.c - but it defines it anyway ???
+ *#ifndef HAVE_VALLOC
+ *#define valloc(Size) malloc (Size)
+ *#endif
+ */
+
+voidstar xmalloc __P ((size_t));
+voidstar xrealloc __P ((voidstar, size_t));
+char *xstrdup __P ((const char *));
+
+/* [TS:Aug/95] 
+ * These were required by files which referred 
+ * to these as function pointers. 
+ * e.g. huffman.c - fread,  mgfelics.c - fgetc
+ */
+#ifndef HAVE_FREAD_DECL
+extern size_t   fread __P ((void *, size_t, size_t, FILE *));
+#endif
+#ifndef HAVE_FGETC_DECL
+extern int      fgetc __P ((FILE *));
+#endif
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifndef u_long
+# define u_long unsigned long
+#endif
+#ifndef u_char
+# define u_char unsigned char
+#endif
+
+
+#endif /* SYSFUNCS_H */
Index: /indexers/branches/3.03a/mg/test/Makefile
===================================================================
--- /indexers/branches/3.03a/mg/test/Makefile	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/Makefile	(revision 14757)
@@ -0,0 +1,10 @@
+DISTFILES = Makefile q1 q2 q3 r1 r2 r3 mgrc1 mgrc2 mgrc3 testmg \
+            alice.sum simple_sum.c alice.len
+
+all: simple_sum
+
+dist:
+	ln $(DISTFILES) $(distdir)
+
+simple_sum: simple_sum.c
+	cc -o $@ $?
Index: /indexers/branches/3.03a/mg/test/alice.len
===================================================================
--- /indexers/branches/3.03a/mg/test/alice.len	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/alice.len	(revision 14757)
@@ -0,0 +1,2 @@
+./mgdata/alice/alice.invf.dict.hash: 13256
+./mgdata/alice/alice.text.dict: 19321
Index: /indexers/branches/3.03a/mg/test/alice.sum
===================================================================
--- /indexers/branches/3.03a/mg/test/alice.sum	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/alice.sum	(revision 14757)
@@ -0,0 +1,8 @@
+./mgdata/alice/alice.invf: 2618428 19209
+./mgdata/alice/alice.invf.chunk: 189460 2134
+./mgdata/alice/alice.invf.chunk.trans: 331998 2585
+./mgdata/alice/alice.invf.dict.blocked: 1030626 33214
+./mgdata/alice/alice.invf.idx: 309022 7572
+./mgdata/alice/alice.text: 5075885 40099
+./mgdata/alice/alice.text.idx: 185535 3380
+./mgdata/alice/alice.text.stats: 2432380 49146
Index: /indexers/branches/3.03a/mg/test/mgrc1
===================================================================
--- /indexers/branches/3.03a/mg/test/mgrc1	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/mgrc1	(revision 14757)
@@ -0,0 +1,2 @@
+.set mode text
+.set query boolean
Index: /indexers/branches/3.03a/mg/test/mgrc2
===================================================================
--- /indexers/branches/3.03a/mg/test/mgrc2	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/mgrc2	(revision 14757)
@@ -0,0 +1,2 @@
+.set mode text
+.set query ranked
Index: /indexers/branches/3.03a/mg/test/mgrc3
===================================================================
--- /indexers/branches/3.03a/mg/test/mgrc3	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/mgrc3	(revision 14757)
@@ -0,0 +1,2 @@
+.set mode docnums
+.set query boolean
Index: /indexers/branches/3.03a/mg/test/q1
===================================================================
--- /indexers/branches/3.03a/mg/test/q1	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/q1	(revision 14757)
@@ -0,0 +1,1 @@
+flamingo
Index: /indexers/branches/3.03a/mg/test/q2
===================================================================
--- /indexers/branches/3.03a/mg/test/q2	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/q2	(revision 14757)
@@ -0,0 +1,1 @@
+flamingo
Index: /indexers/branches/3.03a/mg/test/q3
===================================================================
--- /indexers/branches/3.03a/mg/test/q3	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/q3	(revision 14757)
@@ -0,0 +1,2 @@
+Rabbit & !(Alice | she)
+laser
Index: /indexers/branches/3.03a/mg/test/r1
===================================================================
--- /indexers/branches/3.03a/mg/test/r1	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/r1	(revision 14757)
@@ -0,0 +1,46 @@
+> flamingo
+flamingo
+---------------------------------- 482
+  The chief difficulty Alice found at first was in managing her 
+flamingo:  she succeeded in getting its body tucked away, 
+comfortably enough, under her arm, with its legs hanging down, 
+but generally, just as she had got its neck nicely straightened 
+out, and was going to give the hedgehog a blow with its head, it 
+WOULD twist itself round and look up in her face, with such a 
+puzzled expression that she could not help bursting out laughing:  
+and when she had got its head down, and was going to begin again, 
+it was very provoking to find that the hedgehog had unrolled 
+itself, and was in the act of crawling away:  besides all this, 
+there was generally a ridge or furrow in the way wherever she 
+wanted to send the hedgehog to, and, as the doubled-up soldiers 
+were always getting up and walking off to other parts of the 
+ground, Alice soon came to the conclusion that it was a very 
+difficult game indeed. 
+---------------------------------- 487
+  Alice waited till the eyes appeared, and then nodded.  `It's no 
+use speaking to it,' she thought, `till its ears have come, or at 
+least one of them.'  In another minute the whole head appeared, 
+and then Alice put down her flamingo, and began an account of the 
+game, feeling very glad she had someone to listen to her.  The 
+Cat seemed to think that there was enough of it now in sight, and 
+no more of it appeared. 
+---------------------------------- 502
+  The hedgehog was engaged in a fight with another hedgehog, 
+which seemed to Alice an excellent opportunity for croqueting one 
+of them with the other:  the only difficulty was, that her 
+flamingo was gone across to the other side of the garden, where 
+Alice could see it trying in a helpless sort of way to fly up 
+into a tree. 
+---------------------------------- 503
+  By the time she had caught the flamingo and brought it back, 
+the fight was over, and both the hedgehogs were out of sight:  
+`but it doesn't matter much,' thought Alice, `as all the arches 
+are gone from the side of the ground.'  So she tucked it away 
+under her arm, that it might not escape again, and went back for 
+a little more conversation with her friend. 
+---------------------------------- 526
+  `I dare say you're wondering why I don't put my arm round your 
+waist,' the Duchess said after a pause:  `the reason is, that I'm 
+doubtful about the temper of your flamingo.  Shall I try the 
+experiment?' 
+5 documents retrieved.
Index: /indexers/branches/3.03a/mg/test/r2
===================================================================
--- /indexers/branches/3.03a/mg/test/r2	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/r2	(revision 14757)
@@ -0,0 +1,46 @@
+> flamingo
+flamingo
+---------------------------------- 526 1.322623
+  `I dare say you're wondering why I don't put my arm round your 
+waist,' the Duchess said after a pause:  `the reason is, that I'm 
+doubtful about the temper of your flamingo.  Shall I try the 
+experiment?' 
+---------------------------------- 503 1.013693
+  By the time she had caught the flamingo and brought it back, 
+the fight was over, and both the hedgehogs were out of sight:  
+`but it doesn't matter much,' thought Alice, `as all the arches 
+are gone from the side of the ground.'  So she tucked it away 
+under her arm, that it might not escape again, and went back for 
+a little more conversation with her friend. 
+---------------------------------- 502 1.009519
+  The hedgehog was engaged in a fight with another hedgehog, 
+which seemed to Alice an excellent opportunity for croqueting one 
+of them with the other:  the only difficulty was, that her 
+flamingo was gone across to the other side of the garden, where 
+Alice could see it trying in a helpless sort of way to fly up 
+into a tree. 
+---------------------------------- 487 0.882496
+  Alice waited till the eyes appeared, and then nodded.  `It's no 
+use speaking to it,' she thought, `till its ears have come, or at 
+least one of them.'  In another minute the whole head appeared, 
+and then Alice put down her flamingo, and began an account of the 
+game, feeling very glad she had someone to listen to her.  The 
+Cat seemed to think that there was enough of it now in sight, and 
+no more of it appeared. 
+---------------------------------- 482 0.529432
+  The chief difficulty Alice found at first was in managing her 
+flamingo:  she succeeded in getting its body tucked away, 
+comfortably enough, under her arm, with its legs hanging down, 
+but generally, just as she had got its neck nicely straightened 
+out, and was going to give the hedgehog a blow with its head, it 
+WOULD twist itself round and look up in her face, with such a 
+puzzled expression that she could not help bursting out laughing:  
+and when she had got its head down, and was going to begin again, 
+it was very provoking to find that the hedgehog had unrolled 
+itself, and was in the act of crawling away:  besides all this, 
+there was generally a ridge or furrow in the way wherever she 
+wanted to send the hedgehog to, and, as the doubled-up soldiers 
+were always getting up and walking off to other parts of the 
+ground, Alice soon came to the conclusion that it was a very 
+difficult game indeed. 
+5 documents retrieved.
Index: /indexers/branches/3.03a/mg/test/r3
===================================================================
--- /indexers/branches/3.03a/mg/test/r3	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/r3	(revision 14757)
@@ -0,0 +1,21 @@
+> Rabbit & !(Alice | she)
+Rabbit Alice she
+     14.14     
+    126.126    
+    143.143    
+    478.478    
+    701.701    
+    704.704    
+    705.705    
+    755.755    
+    774.774    
+    786.786    
+    788.788    
+    791.791    
+    793.793    
+    801.801    
+    803.803    
+15 documents retrieved.
+> laser
+laser
+No entries correspond to that query.
Index: /indexers/branches/3.03a/mg/test/simple_sum.c
===================================================================
--- /indexers/branches/3.03a/mg/test/simple_sum.c	(revision 14757)
+++ /indexers/branches/3.03a/mg/test/simple_sum.c	(revision 14757)
@@ -0,0 +1,89 @@
+/**************************************************************************
+ *
+ * simple_sum.c -- byte summing program
+ * Copyright (C) 1995  Tim Shimmin
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************/
+
+/*
+ * If given -l option then just prints the length.
+ * Normally prints the sum and the length for the file.
+ */
+
+static int length_only = 0;
+
+#include <stdio.h>
+
+void 
+output_sum(fname, input_file, output_file)
+char *fname;
+FILE *input_file;
+FILE *output_file;
+{
+  int ch = '\0';
+  unsigned long sum = 0;
+  unsigned long num_bytes = 0;
+
+  while((ch = getc(input_file))!=EOF){
+    sum += ch;
+    num_bytes++;
+  }
+
+  if (length_only)
+    fprintf(output_file, "%s: %ld\n", fname, num_bytes);
+  else
+    fprintf(output_file, "%s: %ld %ld\n", fname, sum, num_bytes);
+}
+
+void
+main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i = 0;
+
+  /* use stdin */
+  if (argc == 1){
+    output_sum("-", stdin, stdout);
+    exit(0);
+  }
+
+  /* use args as file names for input */
+  for (i=1;i<argc; i++){
+    char *fname = argv[i];
+    FILE *input_file = NULL;
+    
+    if (!length_only && (argv[i][0] == '-') && (argv[i][1] =='l') ) 
+      { 
+        length_only = 1; 
+        continue;
+      }
+
+    input_file = fopen(fname, "r");
+    if (!input_file){
+      fprintf(stderr,"Could not open %s\n", fname);
+      continue;
+    }
+    else{
+      output_sum(fname, input_file, stdout);
+      fclose(input_file);
+    }
+  }/*for*/
+  exit(0);
+
+}
Index: /indexers/branches/3.03a/mg/win32.mak
===================================================================
--- /indexers/branches/3.03a/mg/win32.mak	(revision 14757)
+++ /indexers/branches/3.03a/mg/win32.mak	(revision 14757)
@@ -0,0 +1,76 @@
+###########################################################################
+#
+# win32 makefile -- mg
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999  The New Zealand Digital Library Project
+#
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+AR = lib
+CC = cl
+CPPFLAGS =
+
+MGHOME = $(MAKEDIR)
+DLL = 0
+DLLDEBUG = 0
+
+MDEFINES = /f win32.mak
+COMPILE = $(CC) -c $(CPPFLAGS) $(DEFS) $(INCLUDES)
+
+SOURCES = 
+
+OBJECTS = 
+
+OTHERDIRS = lib 
+
+INSTALLDIRS = src\text jni 
+
+MAKECMD = $(MAKE) $(MDEFINES)
+!IF $(DLL)
+MAKECMD = $(MAKECMD) DLL=1
+!ENDIF
+!IF $(DLLDEBUG)
+MAKECMD = $(MAKECMD) DLLDEBUG=1
+!ENDIF
+
+all: win32.mak $(OTHERDIRS) $(INSTALLDIRS)
+
+java:	FORCE
+	cd "java\org\greenstone\mg"
+	call winMake.bat
+	call winMake.bat install 
+	cd "$(MGHOME)"
+
+
+install: win32.mak $(INSTALLDIRS)
+
+$(OTHERDIRS): FORCE
+	cd "$@"
+	$(MAKECMD)
+	cd "$(MGHOME)"
+
+$(INSTALLDIRS): FORCE
+	cd "$@"
+	$(MAKECMD)
+	$(MAKECMD) install
+	cd "$(MGHOME)"
+
+FORCE:
Index: /indexers/branches/3.03a/mg/winMake.bat
===================================================================
--- /indexers/branches/3.03a/mg/winMake.bat	(revision 14757)
+++ /indexers/branches/3.03a/mg/winMake.bat	(revision 14757)
@@ -0,0 +1,61 @@
+@echo off
+
+set MAKE=nmake
+set MAKE_OPTIONS=/f
+
+if ""%1"" == """" goto all
+if ""%1"" == ""all"" goto go
+if ""%1"" == ""install"" goto go
+if ""%1"" == ""clean"" goto go
+
+:unknown
+	echo Error: Unrecognized argument %1.
+	goto done
+
+:go
+	if ""%2"" == ""javaonly"" goto java
+	if ""%2"" == ""nojava"" goto nojava
+
+:all
+	cd lib
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..
+
+	cd src\images
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..\..
+
+	cd src\text
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..\..
+
+	cd java\org\greenstone\mg
+	call winMake.bat %1
+	cd ..\..\..\..
+
+	cd jni
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..
+	goto done
+:java
+	cd java\org\greenstone\mg
+	call winMake.bat %1
+	cd ..\..\..\..
+	goto done
+
+:nojava
+	cd lib
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..
+
+	cd src\images
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..\..
+
+	cd src\text
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..\..
+	goto done
+:done
+
+
Index: /indexers/branches/3.03a/mgpp/COPYING
===================================================================
--- /indexers/branches/3.03a/mgpp/COPYING	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/COPYING	(revision 14757)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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 of the License, 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 program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: /indexers/branches/3.03a/mgpp/Makefile.in
===================================================================
--- /indexers/branches/3.03a/mgpp/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/Makefile.in	(revision 14757)
@@ -0,0 +1,133 @@
+ # Main Makefile for MGPP
+# Copyright (C) 1994, 1995 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ 
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+ 
+@SET_MAKE@
+SHELL = /bin/sh
+VPATH = @srcdir@
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+srcdir = @srcdir@
+ 
+
+CC = @CC@
+CPP = @CXX@
+CFLAGS = @CFLAGS@ -ansi
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@  
+TOUCH = echo timestamp >
+ 
+bindir = $(exec_prefix)/bin
+infodir = $(prefix)/info
+libexecdir = $(exec_prefix)/libexec
+ 
+MDEFINES = 
+#CC='$(CC)' CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' LIBS='$(LIBS)' \
+#prefix='$(prefix)' exec_prefix='$(exec_prefix)' \
+#bindir='$(bindir)' libexecdir='$(libexecdir)' \
+#infodir='$(infodir)' infodir='$(infodir)' libexecdir='$(libexecdir)'
+
+SUBDIRS = lib text 
+JAVADIRS = java/org/greenstone/mgpp 
+JNIDIRS = jni
+
+.SUFFIXES:
+
+all install uninstall execinstall execuninstall maninstall manuninstall:
+#config.h
+	for subdir in $(SUBDIRS) $(JAVADIRS) $(JNIDIRS); do \
+	  echo making $@ in $$subdir; \
+	  (cd $$subdir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+	done
+
+nojava: 
+	for subdir in $(SUBDIRS); do \
+	  echo making $@ in $$subdir; \
+	  (cd $$subdir && $(MAKE) $(MDEFINES) all) || exit 1; \
+	done
+
+install-nojava: 
+	for subdir in $(SUBDIRS); do \
+	  echo making $@ in $$subdir; \
+	  (cd $$subdir && $(MAKE) $(MDEFINES) install) || exit 1; \
+	done
+
+javaonly:
+	for subdir in $(JAVADIRS); do \
+	  echo making $@ in $$subdir; \
+	  (cd $$subdir && $(MAKE) $(MDEFINES) all) || exit 1; \
+	done
+
+install-javaonly:
+	for subdir in $(JAVADIRS); do \
+	  echo making $@ in $$subdir; \
+	  (cd $$subdir && $(MAKE) $(MDEFINES) install) || exit 1; \
+	done
+
+
+mostlyclean: mostlyclean-recursive mostlyclean-local
+
+clean: clean-recursive clean-local
+
+distclean: distclean-recursive distclean-local
+	rm config.status
+
+maintainer-clean: maintainer-clean-recursive maintainer-clean-local
+	rm config.status
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	for subdir in $(SUBDIRS) $(JAVADIRS) $(JNIDIRS); do \
+	  target=`echo $@ | sed 's/-recursive//'`; \
+	  echo making $$target in $$subdir; \
+	  (cd $$subdir && $(MAKE) $$target) || exit 1; \
+	done
+
+mostlyclean-local:
+
+clean-local: mostlyclean-local
+
+distclean-local: clean-local
+	rm -f Makefile config.cache config.h config.log stamp-h
+
+maintainer-clean-local: distclean-local
+	@echo "This command is intended only for maintainers to use;"
+	@echo "rebuilding the deleted files may require special tools."
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+distdir = $(PACKAGE)-$(VERSION)
+
+distname = $(distdir)
+
+DISTFILES = \
+INSTALL.mg INSTALL README README.port COPYING MODIFICATIONS about_mg.html \
+Makefile.in acconfig.h aclocal.m4 configure.in install-sh mkinstalldirs \
+config.guess config.sub \
+config.h.in configure stamp-h.in
+
+#-----------------------------------------------------------------
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
+
Index: /indexers/branches/3.03a/mgpp/acconfig.h
===================================================================
--- /indexers/branches/3.03a/mgpp/acconfig.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/acconfig.h	(revision 14757)
@@ -0,0 +1,41 @@
+/* Special definitions for mg, processed by autoheader.
+   Created by [TS:Aug/95] 
+   by grepping for AC_DEFINE on configure.in and using the appropriate defs 
+   of acconfig.h used by GNU tar.
+*/
+
+/* Define to the name of the distribution.  */
+#undef PACKAGE
+
+/* Define to the version of the distribution.  */
+#undef VERSION
+
+/* Define if `union wait' is the type of the first arg to wait functions.  */
+#undef HAVE_UNION_WAIT
+
+/* Define to 1 if you have the valloc function.  */
+#undef HAVE_VALLOC
+
+/* Define to 1 if ANSI function prototypes are usable.  */
+#undef PROTOTYPES
+ 
+/* Define to 1 for better use of the debugging malloc library.  See
+   site ftp.antaire.com in antaire/src, file dmalloc/dmalloc.tar.gz.  */
+#undef WITH_DMALLOC
+ 
+/* Define to 1 if GNU regex should be used instead of GNU rx.  */
+#undef WITH_REGEX
+
+/* Define to 1 if GNU readline should be used. */
+#undef WITH_GNU_READLINE
+
+/* Some braindead header files do not have the requ'd function declarations */
+#undef HAVE_FGETC_DECL
+#undef HAVE_FREAD_DECL
+
+/* See if have this field in the prstatus_t structure */
+/* It stores the size of the process heap */
+#undef HAVE_PR_BRKSIZE
+
+/* Define to 1 to override the automatic selection of "long long" */
+#undef DISABLE_LONG_LONG
Index: /indexers/branches/3.03a/mgpp/aclocal.m4
===================================================================
--- /indexers/branches/3.03a/mgpp/aclocal.m4	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/aclocal.m4	(revision 14757)
@@ -0,0 +1,224 @@
+# Local additions to Autoconf macros.
+# Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+# François Pinard <pinard@iro.umontreal.ca>, 1992.
+
+# [TS:Aug/95] - chopped out the NLS stuff which I don't support
+
+## ------------------------------- ##
+## Check for function prototypes.  ##
+## ------------------------------- ##
+
+AC_DEFUN(fp_C_PROTOTYPES,
+[AC_REQUIRE([fp_PROG_CC_STDC])
+AC_MSG_CHECKING([for function prototypes])
+if test "$ac_cv_prog_cc_stdc" != no; then
+  AC_MSG_RESULT(yes)
+  AC_DEFINE(PROTOTYPES)
+  U= ANSI2KNR=
+else
+  AC_MSG_RESULT(no)
+  U=_ ANSI2KNR=ansi2knr
+fi
+AC_SUBST(U)dnl
+AC_SUBST(ANSI2KNR)dnl
+])
+
+## ----------------------------------------- ##
+## ANSIfy the C compiler whenever possible.  ##
+## ----------------------------------------- ##
+
+# @defmac AC_PROG_CC_STDC
+# @maindex PROG_CC_STDC
+# @ovindex CC
+# If the C compiler in not in ANSI C mode by default, try to add an option
+# to output variable @code{CC} to make it so.  This macro tries various
+# options that select ANSI C on some system or another.  It considers the
+# compiler to be in ANSI C mode if it defines @code{__STDC__} to 1 and
+# handles function prototypes correctly.
+#
+# If you use this macro, you should check after calling it whether the C
+# compiler has been set to accept ANSI C; if not, the shell variable
+# @code{ac_cv_prog_cc_stdc} is set to @samp{no}.  If you wrote your source
+# code in ANSI C, you can make an un-ANSIfied copy of it by using the
+# program @code{ansi2knr}, which comes with Ghostscript.
+# @end defmac
+
+AC_DEFUN(fp_PROG_CC_STDC,
+[AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
+AC_CACHE_VAL(ac_cv_prog_cc_stdc,
+[ac_cv_prog_cc_stdc=no
+ac_save_CFLAGS="$CFLAGS"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX			-Aa -D_HPUX_SOURCE
+# SVR4			-Xc
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" -Xc
+do
+  CFLAGS="$ac_save_CFLAGS $ac_arg"
+  AC_TRY_COMPILE(
+[#if !defined(__STDC__) || __STDC__ != 1
+choke me
+#endif	
+], [int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};],
+[ac_cv_prog_cc_stdc="$ac_arg"; break])
+done
+CFLAGS="$ac_save_CFLAGS"
+])
+AC_MSG_RESULT($ac_cv_prog_cc_stdc)
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno) ;;
+  *) CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+])
+
+## --------------------------------------------------------- ##
+## Use AC_PROG_INSTALL, supplementing it with INSTALL_SCRIPT ##
+## substitution.					     ##
+## --------------------------------------------------------- ##
+
+AC_DEFUN(fp_PROG_INSTALL,
+[AC_PROG_INSTALL
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL} -m 755'
+AC_SUBST(INSTALL_SCRIPT)dnl
+])
+
+## ----------------------------------- ##
+## Check if --with-dmalloc was given.  ##
+## ----------------------------------- ##
+
+# I just checked, and GNU rx seems to work fine with a slightly
+# modified GNU m4.  So, I put out the test below in my aclocal.m4,
+# and will try to use it in my things.  The idea is to distribute
+# rx.[hc] and regex.[hc] together, for a while.  The WITH_REGEX symbol
+# (which should also be documented in acconfig.h) is used to decide
+# which of regex.h or rx.h should be included in the application.
+#
+# If `./configure --with-regex' is given, the package will use
+# the older regex.  Else, a check is made to see if rx is already
+# installed, as with newer Linux'es.  If not found, the package will
+# use the rx from the distribution.  If found, the package will use
+# the system's rx which, on Linux at least, will result in a smaller
+# executable file.
+
+AC_DEFUN(fp_WITH_DMALLOC,
+[AC_MSG_CHECKING(if malloc debugging is wanted)
+AC_ARG_WITH(dmalloc,
+[  --with-dmalloc          use dmalloc, as in
+                          ftp://ftp.letters.com/src/dmalloc/dmalloc.tar.gz],
+[if test "$withval" = yes; then
+  AC_MSG_RESULT(yes)
+  AC_DEFINE(WITH_DMALLOC)
+  LIBS="$LIBS -ldmalloc"
+  LDFLAGS="$LDFLAGS -g"
+else
+  AC_MSG_RESULT(no)
+fi], [AC_MSG_RESULT(no)])
+])
+
+## --------------------------------- ##
+## Check if --with-regex was given.  ##
+## --------------------------------- ##
+
+AC_DEFUN(fp_WITH_REGEX,
+[AC_MSG_CHECKING(which of rx or regex is wanted)
+AC_ARG_WITH(regex,
+[  --with-regex            use older regex in lieu of GNU rx for matching],
+[if test "$withval" = yes; then
+  ac_with_regex=1
+  AC_MSG_RESULT(regex)
+  AC_DEFINE(WITH_REGEX)
+  AC_LIBOBJ([regex])	
+fi])
+if test -z "$ac_with_regex"; then
+  AC_MSG_RESULT(rx)
+  AC_CHECK_FUNC(re_rx_search, , 
+   [AC_CHECK_SIZEOF(unsigned char *, unsigned char *)  
+    if test "$ac_cv_sizeof_unsigned_char_p" = 8
+    then
+      AC_MSG_WARN(I'm forcing you to use regex because I can't 
+        find a local rx library and the one included with this 
+        distribution doesn't work on 64-bit machines like yours)
+      AC_LIBOBJ([regex])
+    else
+      AC_LIBOBJ([rx])
+    fi]
+  )
+fi
+])
+
+
+## --------------------------------------- ##
+## Check if --with-gnu-readline was given. ##
+## --------------------------------------- ##
+
+AC_DEFUN(fp_WITH_GNU_READLINE,
+[AC_MSG_CHECKING(whether GNU readline requested)
+  AC_ARG_WITH(gnu_readline,
+    [  --with-gnu-readline     compile with GNU readline support],
+    [if test "$withval" = yes; then
+      AC_MSG_RESULT(yes)
+      ac_with_gnu_readline=1
+    else
+      AC_MSG_RESULT(no)
+    fi],
+    AC_MSG_RESULT(no))
+
+  if test -n "$ac_with_gnu_readline"; then
+    AC_CHECK_HEADER(readline/readline.h, ac_mg_readline_header_found=1,
+	AC_MSG_WARN(Can't find GNU readline headers; configuring without \
+GNU readline support))
+    if test -n "$ac_mg_readline_header_found"; then
+      # first check whether we can find the readline library itself
+      AC_CHECK_LIB(readline, main, 
+        [ac_mg_readline_lib_found=1
+         AC_DEFINE(WITH_GNU_READLINE)
+         LIBS="$LIBS -lreadline"],
+        AC_MSG_WARN(Can't find GNU readline library; configuring without \
+GNU readline support))
+      if test -n "$ac_mg_readline_lib_found"; then
+        # on some systems, readline needs curses.  It is difficult to 
+        #  determine whether this is necessary on the current system,
+        #  since other undefined symbols can be turned up by an
+        #  AC_CHECK_LIB(readline, readline) test that are actually defined
+	#  by mg itself (e.g. xmalloc, xrealloc).  So, if we find libcurses,
+	#  we just bung it on and hope for the best.
+	AC_CHECK_LIB(curses, main,
+	  LIBS="$LIBS -lcurses")
+      fi
+    fi
+  fi
+])	
+
+
+
+#AC_DEFUN(fp_WITH_GNU_READLINE,
+#[AC_MSG_CHECKING(whether GNU readline requested)
+#  AC_ARG_WITH(gnu-readline,
+#    [  --with-gnu-readline   compile with GNU readline support],
+#    [if test "$withval" = yes; then
+#      AC_MSG_RESULT(yes)
+#      ac_with_gnu_readline=1
+#    else
+#      AC_MSG_RESULT(no)
+#    fi],
+#    AC_MSG_RESULT(no))
+#  if test -n "$ac_with_gnu_readline"; then
+#    AC_CHECK_LIB(readline, main, 
+#      AC_CHECK_HEADER(readline/readline.h,
+#	[AC_DEFINE(WITH_GNU_READLINE)
+## curses required on some systems (DEC OSF/1), but not on others (GNU/Linux,
+##  Solaris 2.6).  Forcing its inclusion is unsophisticated; if it causes 
+##  any actual problems on any UNIX platforms, let the maintainer know.
+#	LIBS="$LIBS -lreadline -lcurses"],
+#        AC_MSG_WARN(Can't find GNU readline headers: configuring \
+#without GNU readline support)
+#      ),
+#      AC_MSG_WARN(Can't find GNU readline library: configuring \
+#without GNU readline support)
+#    )
+#  fi 
+#])
Index: /indexers/branches/3.03a/mgpp/config.guess
===================================================================
--- /indexers/branches/3.03a/mgpp/config.guess	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/config.guess	(revision 14757)
@@ -0,0 +1,1298 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+#   Free Software Foundation, Inc.
+
+timestamp='2001-07-12'
+
+# This file 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# Please send patches to <config-patches@gnu.org>.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script.
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int dummy(){}" > $dummy.c ;
+	for c in cc gcc c89 ; do
+	  ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
+	  if test $? = 0 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	rm -f $dummy.c $dummy.o $dummy.rel ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# Netbsd (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	# Determine the machine/vendor (is the vendor relevant).
+	case "${UNAME_MACHINE}" in
+	    amiga) machine=m68k-unknown ;;
+	    arm32) machine=arm-unknown ;;
+	    atari*) machine=m68k-atari ;;
+	    sun3*) machine=m68k-sun ;;
+	    mac68k) machine=m68k-apple ;;
+	    macppc) machine=powerpc-apple ;;
+	    hp3[0-9][05]) machine=m68k-hp ;;
+	    ibmrt|romp-ibm) machine=romp-ibm ;;
+	    *) machine=${UNAME_MACHINE}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE}" in
+	    i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit 0 ;;
+    alpha:OSF1:*:*)
+	if test $UNAME_RELEASE = "V4.0"; then
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+	fi
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	cat <<EOF >$dummy.s
+	.data
+\$Lformat:
+	.byte 37,100,45,37,120,10,0	# "%d-%x\n"
+
+	.text
+	.globl main
+	.align 4
+	.ent main
+main:
+	.frame \$30,16,\$26,0
+	ldgp \$29,0(\$27)
+	.prologue 1
+	.long 0x47e03d80 # implver \$0
+	lda \$2,-1
+	.long 0x47e20c21 # amask \$2,\$1
+	lda \$16,\$Lformat
+	mov \$0,\$17
+	not \$1,\$18
+	jsr \$26,printf
+	ldgp \$29,0(\$26)
+	mov 0,\$16
+	jsr \$26,exit
+	.end main
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+	if test "$?" = 0 ; then
+		case `./$dummy` in
+			0-0)
+				UNAME_MACHINE="alpha"
+				;;
+			1-0)
+				UNAME_MACHINE="alphaev5"
+				;;
+			1-1)
+				UNAME_MACHINE="alphaev56"
+				;;
+			1-101)
+				UNAME_MACHINE="alphapca56"
+				;;
+			2-303)
+				UNAME_MACHINE="alphaev6"
+				;;
+			2-307)
+				UNAME_MACHINE="alphaev67"
+				;;
+		esac
+	fi
+	rm -f $dummy.s $dummy
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit 0 ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit 0 ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit 0;;
+    amiga:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit 0 ;;
+    arc64:OpenBSD:*:*)
+	echo mips64el-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    arc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    hkmips:OpenBSD:*:*)
+	echo mips-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    pmax:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sgi:OpenBSD:*:*)
+	echo mips-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit 0;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit 0 ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit 0 ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    i86pc:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit 0 ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit 0 ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    sun3*:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mac68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+	echo m88k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit 0 ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit 0 ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.c -o $dummy \
+	  && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+	  && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit 0 ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit 0 ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit 0 ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit 0 ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit 0 ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit 0 ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit 0 ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+	exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit 0 ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		eval $set_cc_for_build
+		$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+		rm -f $dummy.c $dummy
+		echo rs6000-ibm-aix3.2.5
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit 0 ;;
+    *:AIX:*:[45])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+              case "${HPUX_REV}" in
+                11.[0-9][0-9])
+                  if [ -x /usr/bin/getconf ]; then
+                    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                        esac ;;
+                    esac
+                  fi ;;
+              esac
+              if [ "${HP_ARCH}" = "" ]; then
+              sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+	eval $set_cc_for_build
+	(CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
+	if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+	rm -f $dummy.c $dummy
+	fi ;;
+	esac
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    3050*:HI-UX:*:*)
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	echo unknown-hitachi-hiuxwe2
+	exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit 0 ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit 0 ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit 0 ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit 0 ;;
+    hppa*:OpenBSD:*:*)
+	echo hppa-unknown-openbsd
+	exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*X-MP:*:*:*)
+	echo xmp-cray-unicos
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3D:*:*:*)
+	echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY-2:*:*:*)
+	echo cray2-cray-unicos
+        exit 0 ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    hp300:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:FreeBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit 0 ;;
+    *:OpenBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	exit 0 ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit 0 ;;
+    i*:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit 0 ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit 0 ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i386-pc-interix
+	exit 0 ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit 0 ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit 0 ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    *:GNU:*:*)
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit 0 ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit 0 ;;
+    arm*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux
+	exit 0 ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    mips:Linux:*:*)
+	case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in
+	  big)    echo mips-unknown-linux-gnu && exit 0 ;;
+	  little) echo mipsel-unknown-linux-gnu && exit 0 ;;
+	esac
+	;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit 0 ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev67 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit 0 ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit 0 ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit 0 ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	ld_supported_targets=`cd /; ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit 0 ;;		
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit 0 ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+		exit 0 ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	cat >$dummy.c <<EOF
+#include <features.h>
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+#ifdef __ELF__
+# ifdef __GLIBC__
+#  if __GLIBC__ >= 2
+    printf ("%s-pc-linux-gnu\n", argv[1]);
+#  else
+    printf ("%s-pc-linux-gnulibc1\n", argv[1]);
+#  endif
+# else
+   printf ("%s-pc-linux-gnulibc1\n", argv[1]);
+# endif
+#else
+  printf ("%s-pc-linux-gnuaout\n", argv[1]);
+#endif
+  return 0;
+}
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit 0 ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit 0 ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit 0 ;;
+    i*86:*:5:[78]*)
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit 0 ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit 0 ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit 0 ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit 0 ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit 0 ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit 0 ;;
+    M68*:*:R3V[567]*:*)
+	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit 0 ;;
+    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                           # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit 0 ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit 0 ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit 0 ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit 0 ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit 0 ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit 0 ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit 0 ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Darwin:*:*)
+	echo `uname -p`-apple-darwin${UNAME_RELEASE}
+	exit 0 ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	if test "${UNAME_MACHINE}" = "x86pc"; then
+		UNAME_MACHINE=pc
+	fi
+	echo `uname -p`-${UNAME_MACHINE}-nto-qnx
+	exit 0 ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit 0 ;;
+    NSR-[KW]:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit 0 ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit 0 ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit 0 ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit 0 ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit 0 ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit 0 ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit 0 ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit 0 ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+eval $set_cc_for_build
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit 0 ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit 0 ;;
+    c34*)
+	echo c34-convex-bsd
+	exit 0 ;;
+    c38*)
+	echo c38-convex-bsd
+	exit 0 ;;
+    c4*)
+	echo c4-convex-bsd
+	exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /indexers/branches/3.03a/mgpp/config.h.in
===================================================================
--- /indexers/branches/3.03a/mgpp/config.h.in	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/config.h.in	(revision 14757)
@@ -0,0 +1,209 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+#ifndef _MGPP_CONFIG_H
+#define _MGPP_CONFIG_H
+
+/* Define if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+#undef _ALL_SOURCE
+#endif
+
+/* Define if using alloca.c.  */
+#undef C_ALLOCA
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro.  */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+#undef HAVE_ALLOCA_H
+
+/* Define if you don't have vprintf but do have _doprnt.  */
+#undef HAVE_DOPRNT
+
+/* Define if you have the vprintf function.  */
+#undef HAVE_VPRINTF
+
+/* Define if on MINIX.  */
+#undef _MINIX
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+#undef off_t
+
+/* Define if the system does not provide POSIX.1 features except
+   with this defined.  */
+#undef _POSIX_1_SOURCE
+
+/* Define if you need to in order for stat and other things to work.  */
+#undef _POSIX_SOURCE
+
+/* Define as the return type of signal handlers (int or void).  */
+#undef RETSIGTYPE
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+#undef TIME_WITH_SYS_TIME
+
+/* Define if your <sys/time.h> declares struct tm.  */
+#undef TM_IN_SYS_TIME
+
+/* Define to the name of the distribution.  */
+#undef PACKAGE
+
+/* Define to the version of the distribution.  */
+#undef VERSION
+
+/* Define to 1 if you have the valloc function.  */
+#undef HAVE_VALLOC
+
+/* Define to 1 if ANSI function prototypes are usable.  */
+#undef PROTOTYPES
+
+ 
+/* Define to 1 for better use of the debugging malloc library.  See
+   site ftp.antaire.com in antaire/src, file dmalloc/dmalloc.tar.gz.  */
+#undef WITH_DMALLOC
+
+ 
+/* Define to 1 if GNU regex should be used instead of GNU rx.  */
+#undef WITH_REGEX
+
+/* Define to 1 if GNU readline should be used. */
+#undef WITH_GNU_READLINE
+
+/* Some braindead header files do not have the requ'd function declarations */
+#undef HAVE_FGETC_DECL
+#undef HAVE_FREAD_DECL
+
+/* See if have this field in the prstatus_t structure */
+/* It stores the size of the process heap */
+#undef HAVE_PR_BRKSIZE
+
+/* Define to 1 to override the automatic selection of "long long" */
+#undef DISABLE_LONG_LONG
+
+/* The number of bytes in a unsigned char *.  */
+#undef SIZEOF_UNSIGNED_CHAR_P
+
+/* Define if you have the ftime function.  */
+#undef HAVE_FTIME
+
+/* Define if you have the ftruncate function.  */
+#undef HAVE_FTRUNCATE
+
+/* Define if you have the getpagesize function.  */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the getrusage function.  */
+#undef HAVE_GETRUSAGE
+
+/* Define if you have the mallinfo function.  */
+#undef HAVE_MALLINFO
+
+/* Define if you have the select function.  */
+#undef HAVE_SELECT
+
+/* Define if you have the setbuffer function.  */
+#undef HAVE_SETBUFFER
+
+/* Define if you have the strcasecmp function.  */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the strerror function.  */
+#undef HAVE_STRERROR
+
+/* Define if you have the strftime function.  */
+#undef HAVE_STRFTIME
+
+/* Define if you have the strstr function.  */
+#undef HAVE_STRSTR
+
+/* Define if you have the strtol function.  */
+#undef HAVE_STRTOL
+
+/* Define if you have the times function.  */
+#undef HAVE_TIMES
+
+/* Define if you have the valloc function.  */
+#undef HAVE_VALLOC
+
+/* Define if you have the <crypt.h> header file.  */
+#undef HAVE_CRYPT_H
+
+/* Define if you have the <dirent.h> header file.  */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the <fcntl.h> header file.  */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <limits.h> header file.  */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <memory.h> header file.  */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <ndir.h> header file.  */
+#undef HAVE_NDIR_H
+
+/* Define if you have the <string.h> header file.  */
+#undef HAVE_STRING_H
+
+/* Define if you have the <sys/dir.h> header file.  */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have the <sys/ndir.h> header file.  */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if you have the <sys/procfs.h> header file.  */
+#undef HAVE_SYS_PROCFS_H
+
+/* Define if you have the <sys/time.h> header file.  */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the crypt library (-lcrypt).  */
+#undef HAVE_LIBCRYPT
+
+/* Define if you have the g library (-lg).  */
+#undef HAVE_LIBG
+
+/* Define if you have the gdbm library (-lgdbm).  */
+#undef HAVE_LIBGDBM
+
+/* Define if you have the m library (-lm).  */
+#undef HAVE_LIBM
+
+/* Define if you have the stdc++ library (-lstdc++).  */
+#undef HAVE_LIBSTDC__
+
+/* Define if you have gettext (eg glibc) */
+#undef ENABLE_NLS
+
+/* Define if big endian */
+#undef WORDS_BIGENDIAN
+
+#endif /* _MGPP_CONFIG_H */
Index: /indexers/branches/3.03a/mgpp/config.sub
===================================================================
--- /indexers/branches/3.03a/mgpp/config.sub	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/config.sub	(revision 14757)
@@ -0,0 +1,1375 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+#   Free Software Foundation, Inc.
+
+timestamp='2001-06-08'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \
+	        | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \
+		| pyramid | mn10200 | mn10300 | tron | a29k \
+		| 580 | i960 | h8300 \
+		| x86 | ppcbe | mipsbe | mipsle | shbe | shle \
+		| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
+		| hppa64 \
+		| alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \
+		| alphaev6[78] \
+		| we32k | ns16k | clipper | i370 | sh | sh[34] \
+		| powerpc | powerpcle \
+		| 1750a | dsp16xx | pdp10 | pdp11 \
+		| mips16 | mips64 | mipsel | mips64el \
+		| mips64orion | mips64orionel | mipstx39 | mipstx39el \
+		| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
+		| mips64vr5000 | mips64vr5000el | mcore | s390 | s390x \
+		| sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \
+		| v850 | c4x \
+		| thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \
+		| pj | pjl | h8500 | z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	# FIXME: clean up the formatting here.
+	vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
+	      | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \
+	      | arm-*  | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \
+	      | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+	      | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
+	      | xmp-* | ymp-* \
+	      | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \
+	      | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \
+	      | hppa2.0n-* | hppa64-* \
+	      | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \
+	      | alphaev6[78]-* \
+	      | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
+	      | clipper-* | orion-* \
+	      | sparclite-* | pdp10-* | pdp11-* | sh-* | sh[34]-* | sh[34]eb-* \
+	      | powerpc-* | powerpcle-* | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \
+	      | mips16-* | mips64-* | mipsel-* \
+	      | mips64el-* | mips64orion-* | mips64orionel-* \
+	      | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
+	      | mipstx39-* | mipstx39el-* | mcore-* \
+	      | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \
+	      | [cjt]90-* \
+	      | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
+	      | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \
+	      | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*)
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	cray2)
+		basic_machine=cray2-cray
+		os=-unicos
+		;;
+	[cjt]90)
+		basic_machine=${basic_machine}-cray
+		os=-unicos
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mipsel*-linux*)
+		basic_machine=mipsel-unknown
+		os=-linux-gnu
+		;;
+	mips*-linux*)
+		basic_machine=mips-unknown
+		os=-linux-gnu
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	mmix*)
+		basic_machine=mmix-knuth
+		os=-mmixware
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+        pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pentium | p5 | k5 | k6 | nexgen)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2)
+		basic_machine=i686-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+	        ;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+	        ;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sparclite-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=t3e-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	windows32)
+		basic_machine=i386-pc
+		os=-windows32-msvcrt
+		;;
+	xmp)
+		basic_machine=xmp-cray
+		os=-unicos
+		;;
+        xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	mips)
+		if [ x$os = x-linux-gnu ]; then
+			basic_machine=mips-unknown
+		else
+			basic_machine=mips-mips
+		fi
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh3 | sh4)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv9 | sparcv9b)
+		basic_machine=sparc-sun
+		;;
+        cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	c4x*)
+		basic_machine=c4x-none
+		os=-coff
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto*)
+		os=-nto-qnx
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-ns2 )
+	        os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+	        os=-mint
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	pdp10-*)
+		os=-tops20
+		;;
+        pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+        *-gould)
+		os=-sysv
+		;;
+        *-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+        *-sgi)
+		os=-irix
+		;;
+        *-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-vxsim* | -vxworks*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /indexers/branches/3.03a/mgpp/configure
===================================================================
--- /indexers/branches/3.03a/mgpp/configure	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/configure	(revision 14757)
@@ -0,0 +1,8936 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="text/MGQuery.cpp"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS PACKAGE VERSION ENABLE_ACCENTFOLD CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT AWK YACC CC CFLAGS ac_ct_CC INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP U ANSI2KNR UNAC_DIR ALLOCA LIBOBJS JNIINC JNISUFFIX JNIFLAGS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+	      localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$0" : 'X\(//\)[^/]' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CXX_set=${CXX+set}
+ac_env_CXX_value=$CXX
+ac_cv_env_CXX_set=${CXX+set}
+ac_cv_env_CXX_value=$CXX
+ac_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_env_CXXFLAGS_value=$CXXFLAGS
+ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_cv_env_CXXFLAGS_value=$CXXFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+			  [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+			  [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-accentfold          Disable Accent Folding for MGPP
+  --enable-override-longlong
+                          overide use of long long with GCC
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-unac=dir         Use local unac library and headers
+  --with-dmalloc          use dmalloc, as in
+                          ftp://ftp.letters.com/src/dmalloc/dmalloc.tar.gz
+  --with-regex            use older regex in lieu of GNU rx for matching
+  --with-gnu-readline     compile with GNU readline support
+
+Some influential environment variables:
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+	   test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+	"s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=$`echo $ac_var`
+	echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+	       sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+	ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+          ac_config_headers="$ac_config_headers config.h"
+
+test "$program_prefix" != NONE &&
+  program_transform_name="s,^,$program_prefix,;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s,\$,$program_suffix,;$program_transform_name"
+# Double any \ or $.  echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm conftest.sed
+
+
+PACKAGE=mgpp
+VERSION=1.3
+
+LDFLAGS=
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+
+
+
+# Check whether --enable-accentfold or --disable-accentfold was given.
+if test "${enable_accentfold+set}" = set; then
+  enableval="$enable_accentfold"
+  ENABLE_ACCENTFOLD=0
+else
+  ENABLE_ACCENTFOLD=1
+fi;
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_ACCENTFOLD $ENABLE_ACCENTFOLD
+_ACEOF
+
+
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CXX" && break
+done
+test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
+
+  CXX=$ac_ct_CXX
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C++ compiler default output file name" >&5
+echo $ECHO_N "checking for C++ compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+	;;
+    conftest.$ac_ext )
+	# This is the source file.
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	# FIXME: I believe we export ac_cv_exeext for Libtool,
+	# but it would be cool to find out if it's true.  Does anybody
+	# maintain Libtool? --akim.
+	export ac_cv_exeext
+	break;;
+    * )
+	break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C++ compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5
+echo $ECHO_N "checking whether the C++ compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { echo "$as_me:$LINENO: error: cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  export ac_cv_exeext
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cxx_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cxx_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$AWK" && break
+done
+
+for ac_prog in 'bison -y' byacc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_YACC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_YACC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+  echo "$as_me:$LINENO: result: $YACC" >&5
+echo "${ECHO_T}$YACC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX 10.20 and later	-Ae
+# HP-UX older versions	-Aa -D_HPUX_SOURCE
+# SVR4			-Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	    break 3
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+all:
+	@echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  SET_MAKE=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+
+echo "$as_me:$LINENO: checking for AIX" >&5
+echo $ECHO_N "checking for AIX... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef _AIX
+  yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+cat >>confdefs.h <<\_ACEOF
+#define _ALL_SOURCE 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+
+echo "$as_me:$LINENO: checking for library containing strerror" >&5
+echo $ECHO_N "checking for library containing strerror... $ECHO_C" >&6
+if test "${ac_cv_search_strerror+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_strerror=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char strerror ();
+int
+main ()
+{
+strerror ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_strerror="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_strerror" = no; then
+  for ac_lib in cposix; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char strerror ();
+int
+main ()
+{
+strerror ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_strerror="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_strerror" >&5
+echo "${ECHO_T}$ac_cv_search_strerror" >&6
+if test "$ac_cv_search_strerror" != no; then
+  test "$ac_cv_search_strerror" = "none required" || LIBS="$ac_cv_search_strerror $LIBS"
+
+fi
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+if test "${ac_cv_header_minix_config_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for minix/config.h" >&5
+echo $ECHO_N "checking for minix/config.h... $ECHO_C" >&6
+if test "${ac_cv_header_minix_config_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_minix_config_h" >&5
+echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking minix/config.h usability" >&5
+echo $ECHO_N "checking minix/config.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <minix/config.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking minix/config.h presence" >&5
+echo $ECHO_N "checking minix/config.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <minix/config.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: minix/config.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: minix/config.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: minix/config.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: minix/config.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: minix/config.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: minix/config.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: minix/config.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: minix/config.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for minix/config.h" >&5
+echo $ECHO_N "checking for minix/config.h... $ECHO_C" >&6
+if test "${ac_cv_header_minix_config_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_minix_config_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_minix_config_h" >&5
+echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6
+
+fi
+if test $ac_cv_header_minix_config_h = yes; then
+  MINIX=yes
+else
+  MINIX=
+fi
+
+
+if test "$MINIX" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define _POSIX_SOURCE 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _POSIX_1_SOURCE 2
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _MINIX 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for ${CC-cc} option to accept ANSI C" >&5
+echo $ECHO_N "checking for ${CC-cc} option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CFLAGS="$CFLAGS"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX			-Aa -D_HPUX_SOURCE
+# SVR4			-Xc
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" -Xc
+do
+  CFLAGS="$ac_save_CFLAGS $ac_arg"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if !defined(__STDC__) || __STDC__ != 1
+choke me
+#endif
+
+int
+main ()
+{
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc="$ac_arg"; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+CFLAGS="$ac_save_CFLAGS"
+
+fi
+
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno) ;;
+  *) CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+
+echo "$as_me:$LINENO: checking for function prototypes" >&5
+echo $ECHO_N "checking for function prototypes... $ECHO_C" >&6
+if test "$ac_cv_prog_cc_stdc" != no; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  cat >>confdefs.h <<\_ACEOF
+#define PROTOTYPES 1
+_ACEOF
+
+  U= ANSI2KNR=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  U=_ ANSI2KNR=ansi2knr
+fi
+
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset x;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *ccp;
+  char **p;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  ccp = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++ccp;
+  p = (char**) ccp;
+  ccp = (char const *const *) p;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+  }
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_const=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6
+if test "${ac_cv_type_off_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((off_t *) 0)
+  return 0;
+if (sizeof (off_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_off_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_off_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6
+if test $ac_cv_type_off_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((size_t *) 0)
+  return 0;
+if (sizeof (size_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_size_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_size_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6
+if test "${ac_cv_header_time+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_time=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_time=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
+echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6
+if test "${ac_cv_struct_tm+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm *tp; tp->tm_sec;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_struct_tm=time.h
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5
+echo "${ECHO_T}$ac_cv_struct_tm" >&6
+if test $ac_cv_struct_tm = sys/time.h; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TM_IN_SYS_TIME 1
+_ACEOF
+
+fi
+
+
+
+# Check whether --with-unac or --without-unac was given.
+if test "${with_unac+set}" = set; then
+  withval="$with_unac"
+  UNAC_DIR=$withval
+else
+  UNAC_DIR="`pwd`/../packages/unac"
+fi;
+cat >>confdefs.h <<_ACEOF
+#define UNAC_DIR "$UNAC_DIR"
+_ACEOF
+
+
+
+
+if test "$ac_cv_prog_cc_stdc" = '-Xc'; then
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+
+int
+main ()
+{
+ FILE *rubbish = popen("yes", "r");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+CC="`echo $CC | sed 's/-Xc/-Xa/'`"    ac_cv_prog_cc_stdc='-Xa'
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+echo "$as_me:$LINENO: checking for main in -lg" >&5
+echo $ECHO_N "checking for main in -lg... $ECHO_C" >&6
+if test "${ac_cv_lib_g_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lg  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_g_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_g_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_g_main" >&5
+echo "${ECHO_T}$ac_cv_lib_g_main" >&6
+if test $ac_cv_lib_g_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBG 1
+_ACEOF
+
+  LIBS="-lg $LIBS"
+
+fi
+
+
+echo "$as_me:$LINENO: checking for main in -lm" >&5
+echo $ECHO_N "checking for main in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_m_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_main" >&5
+echo "${ECHO_T}$ac_cv_lib_m_main" >&6
+if test $ac_cv_lib_m_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+  LIBS="-lm $LIBS"
+
+fi
+
+
+echo "$as_me:$LINENO: checking for main in -lstdc++" >&5
+echo $ECHO_N "checking for main in -lstdc++... $ECHO_C" >&6
+if test "${ac_cv_lib_stdcpp_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lstdc++  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_stdcpp_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_stdcpp_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_stdcpp_main" >&5
+echo "${ECHO_T}$ac_cv_lib_stdcpp_main" >&6
+if test $ac_cv_lib_stdcpp_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSTDC__ 1
+_ACEOF
+
+  LIBS="-lstdc++ $LIBS"
+
+fi
+
+
+echo "$as_me:$LINENO: checking for main in -lcrypt" >&5
+echo $ECHO_N "checking for main in -lcrypt... $ECHO_C" >&6
+if test "${ac_cv_lib_crypt_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypt  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_crypt_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_crypt_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_main" >&5
+echo "${ECHO_T}$ac_cv_lib_crypt_main" >&6
+if test $ac_cv_lib_crypt_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCRYPT 1
+_ACEOF
+
+  LIBS="-lcrypt $LIBS"
+
+fi
+
+if test $ENABLE_ACCENTFOLD = 1; then
+
+echo "$as_me:$LINENO: checking for main in -liconv" >&5
+echo $ECHO_N "checking for main in -liconv... $ECHO_C" >&6
+if test "${ac_cv_lib_iconv_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-liconv  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_iconv_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_iconv_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_iconv_main" >&5
+echo "${ECHO_T}$ac_cv_lib_iconv_main" >&6
+if test $ac_cv_lib_iconv_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBICONV 1
+_ACEOF
+
+  LIBS="-liconv $LIBS"
+
+fi
+ac_cv_lib_iconv=ac_cv_lib_iconv_main
+
+fi
+
+
+
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+  as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in dir; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+else
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in x; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+fi
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+
+
+
+for ac_header in fcntl.h limits.h sys/time.h unistd.h crypt.h string.h memory.h sys/procfs.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "fread" >/dev/null 2>&1; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_FREAD_DECL 1
+_ACEOF
+
+fi
+rm -f conftest*
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "fgetc" >/dev/null 2>&1; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_FGETC_DECL 1
+_ACEOF
+
+fi
+rm -f conftest*
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/procfs.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "pr_brksize" >/dev/null 2>&1; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_PR_BRKSIZE 1
+_ACEOF
+
+fi
+rm -f conftest*
+
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+echo "$as_me:$LINENO: checking for working alloca.h" >&5
+echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6
+if test "${ac_cv_working_alloca_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_working_alloca_h=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_working_alloca_h=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5
+echo "${ECHO_T}$ac_cv_working_alloca_h" >&6
+if test $ac_cv_working_alloca_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA_H 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for alloca" >&5
+echo $ECHO_N "checking for alloca... $ECHO_C" >&6
+if test "${ac_cv_func_alloca_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  if HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_alloca_works=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_alloca_works=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5
+echo "${ECHO_T}$ac_cv_func_alloca_works" >&6
+
+if test $ac_cv_func_alloca_works = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA 1
+_ACEOF
+
+else
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble.  Some versions do not even contain alloca or
+# contain a buggy version.  If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=alloca.$ac_objext
+
+cat >>confdefs.h <<\_ACEOF
+#define C_ALLOCA 1
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5
+echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6
+if test "${ac_cv_os_cray+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "webecray" >/dev/null 2>&1; then
+  ac_cv_os_cray=yes
+else
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5
+echo "${ECHO_T}$ac_cv_os_cray" >&6
+if test $ac_cv_os_cray = yes; then
+  for ac_func in _getb67 GETB67 getb67; do
+    as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+    break
+fi
+
+  done
+fi
+
+echo "$as_me:$LINENO: checking stack direction for C alloca" >&5
+echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6
+if test "${ac_cv_c_stack_direction+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_stack_direction=0
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+int
+find_stack_direction ()
+{
+  static char *addr = 0;
+  auto char dummy;
+  if (addr == 0)
+    {
+      addr = &dummy;
+      return find_stack_direction ();
+    }
+  else
+    return (&dummy > addr) ? 1 : -1;
+}
+
+int
+main ()
+{
+  exit (find_stack_direction () < 0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_stack_direction=1
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_stack_direction=-1
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5
+echo "${ECHO_T}$ac_cv_c_stack_direction" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+if test $ac_cv_c_compiler_gnu = yes; then
+    echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5
+echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6
+if test "${ac_cv_prog_gcc_traditional+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+    ac_pattern="Autoconf.*'x'"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then
+  ac_cv_prog_gcc_traditional=yes
+else
+  ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+  if test $ac_cv_prog_gcc_traditional = no; then
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then
+  ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+  fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5
+echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6
+  if test $ac_cv_prog_gcc_traditional = yes; then
+    CC="$CC -traditional"
+  fi
+fi
+
+echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6
+if test "${ac_cv_type_signal+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+# undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int
+main ()
+{
+int i;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_signal=void
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_signal=int
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+
+for ac_func in vprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+echo "$as_me:$LINENO: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6
+if test "${ac_cv_func__doprnt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define _doprnt innocuous__doprnt
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char _doprnt (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef _doprnt
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char _doprnt ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub__doprnt) || defined (__stub____doprnt)
+choke me
+#else
+char (*f) () = _doprnt;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != _doprnt;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func__doprnt=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func__doprnt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6
+if test $ac_cv_func__doprnt = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DOPRNT 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in ftime select strftime strtol getrusage times mallinfo setbuffer getpagesize strerror
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+for ac_func in ftruncate strstr strcasecmp
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case $LIBOBJS in
+    "$ac_func.$ac_objext"   | \
+  *" $ac_func.$ac_objext"   | \
+    "$ac_func.$ac_objext "* | \
+  *" $ac_func.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;;
+esac
+
+fi
+done
+
+
+
+
+echo "$as_me:$LINENO: checking for textdomain" >&5
+echo $ECHO_N "checking for textdomain... $ECHO_C" >&6
+if test "${ac_cv_func_textdomain+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define textdomain to an innocuous variant, in case <limits.h> declares textdomain.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define textdomain innocuous_textdomain
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char textdomain (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef textdomain
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char textdomain ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_textdomain) || defined (__stub___textdomain)
+choke me
+#else
+char (*f) () = textdomain;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != textdomain;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_textdomain=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_textdomain=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_textdomain" >&5
+echo "${ECHO_T}$ac_cv_func_textdomain" >&6
+if test $ac_cv_func_textdomain = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define ENABLE_NLS  1
+_ACEOF
+
+fi
+
+
+# we need to set an extended JNI path for Mac OS/Darwin, as jni.h is on
+# a non-standard Path
+# is there a better way to do this??
+echo "$as_me:$LINENO: checking for OS to set JNI options" >&5
+echo $ECHO_N "checking for OS to set JNI options... $ECHO_C" >&6
+# set defaults
+JNIINC=""
+JNISUFFIX="so"
+JNIFLAGS="-shared"
+
+if test "`(uname -s) 2> /dev/null`" = 'Darwin'; then
+  echo "$as_me:$LINENO: result: Darwin" >&5
+echo "${ECHO_T}Darwin" >&6
+  JNIINC="-I/System/Library/Frameworks/JavaVM.framework/Headers/ "
+  JNISUFFIX="jnilib"
+  JNIFLAGS="-dynamiclib -fno-common -single_module -framework JavaVM"
+fi
+if test "`(uname -s) 2> /dev/null`" = 'SunOS'; then
+  echo "$as_me:$LINENO: result: Solaris" >&5
+echo "${ECHO_T}Solaris" >&6
+  JNIINC="-I\$(JAVA_HOME)/include/solaris "
+fi
+if test "`(uname -s) 2> /dev/null`" = 'Linux'; then
+  echo "$as_me:$LINENO: result: Linux" >&5
+echo "${ECHO_T}Linux" >&6
+  JNIINC="-I\$(JAVA_HOME)/include/linux "
+fi
+
+
+
+
+
+# *** Custom checking (based on GNU tar configure.in) ***
+# ---------------------------------------------------------------------------
+echo "$as_me:$LINENO: checking for HP-UX needing gmalloc" >&5
+echo $ECHO_N "checking for HP-UX needing gmalloc... $ECHO_C" >&6
+if test "`(uname -s) 2> /dev/null`" = 'HP-UX'; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  case $LIBOBJS in
+    "gmalloc.$ac_objext"   | \
+  *" gmalloc.$ac_objext"   | \
+    "gmalloc.$ac_objext "* | \
+  *" gmalloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS gmalloc.$ac_objext" ;;
+esac
+
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_VALLOC 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+for ac_func in valloc
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+fi
+
+echo "$as_me:$LINENO: checking if malloc debugging is wanted" >&5
+echo $ECHO_N "checking if malloc debugging is wanted... $ECHO_C" >&6
+
+# Check whether --with-dmalloc or --without-dmalloc was given.
+if test "${with_dmalloc+set}" = set; then
+  withval="$with_dmalloc"
+  if test "$withval" = yes; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  cat >>confdefs.h <<\_ACEOF
+#define WITH_DMALLOC 1
+_ACEOF
+
+  LIBS="$LIBS -ldmalloc"
+  LDFLAGS="$LDFLAGS -g"
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi;
+
+echo "$as_me:$LINENO: checking which of rx or regex is wanted" >&5
+echo $ECHO_N "checking which of rx or regex is wanted... $ECHO_C" >&6
+
+# Check whether --with-regex or --without-regex was given.
+if test "${with_regex+set}" = set; then
+  withval="$with_regex"
+  if test "$withval" = yes; then
+  ac_with_regex=1
+  echo "$as_me:$LINENO: result: regex" >&5
+echo "${ECHO_T}regex" >&6
+  cat >>confdefs.h <<\_ACEOF
+#define WITH_REGEX 1
+_ACEOF
+
+  case $LIBOBJS in
+    "regex.$ac_objext"   | \
+  *" regex.$ac_objext"   | \
+    "regex.$ac_objext "* | \
+  *" regex.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS regex.$ac_objext" ;;
+esac
+
+fi
+fi;
+if test -z "$ac_with_regex"; then
+  echo "$as_me:$LINENO: result: rx" >&5
+echo "${ECHO_T}rx" >&6
+  echo "$as_me:$LINENO: checking for re_rx_search" >&5
+echo $ECHO_N "checking for re_rx_search... $ECHO_C" >&6
+if test "${ac_cv_func_re_rx_search+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define re_rx_search to an innocuous variant, in case <limits.h> declares re_rx_search.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define re_rx_search innocuous_re_rx_search
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char re_rx_search (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef re_rx_search
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char re_rx_search ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_re_rx_search) || defined (__stub___re_rx_search)
+choke me
+#else
+char (*f) () = re_rx_search;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != re_rx_search;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_re_rx_search=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_re_rx_search=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_re_rx_search" >&5
+echo "${ECHO_T}$ac_cv_func_re_rx_search" >&6
+if test $ac_cv_func_re_rx_search = yes; then
+  :
+else
+  echo "$as_me:$LINENO: checking for unsigned char *" >&5
+echo $ECHO_N "checking for unsigned char *... $ECHO_C" >&6
+if test "${ac_cv_type_unsigned_char_p+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((unsigned char * *) 0)
+  return 0;
+if (sizeof (unsigned char *))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_unsigned_char_p=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_unsigned_char_p=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_unsigned_char_p" >&5
+echo "${ECHO_T}$ac_cv_type_unsigned_char_p" >&6
+
+echo "$as_me:$LINENO: checking size of unsigned char *" >&5
+echo $ECHO_N "checking size of unsigned char *... $ECHO_C" >&6
+if test "${ac_cv_sizeof_unsigned_char_p+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_unsigned_char_p" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (unsigned char *))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (unsigned char *))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+		    if test $ac_lo -le $ac_mid; then
+		      ac_lo= ac_hi=
+		      break
+		    fi
+		    ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (unsigned char *))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (unsigned char *))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+		       if test $ac_mid -le $ac_hi; then
+			 ac_lo= ac_hi=
+			 break
+		       fi
+		       ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (unsigned char *))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_unsigned_char_p=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (unsigned char *), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (unsigned char *), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+long longval () { return (long) (sizeof (unsigned char *)); }
+unsigned long ulongval () { return (long) (sizeof (unsigned char *)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (unsigned char *))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (unsigned char *))))
+	exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (unsigned char *))))
+	exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_unsigned_char_p=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (unsigned char *), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (unsigned char *), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+  ac_cv_sizeof_unsigned_char_p=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_unsigned_char_p" >&5
+echo "${ECHO_T}$ac_cv_sizeof_unsigned_char_p" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UNSIGNED_CHAR_P $ac_cv_sizeof_unsigned_char_p
+_ACEOF
+
+
+    if test "$ac_cv_sizeof_unsigned_char_p" = 8
+    then
+      { echo "$as_me:$LINENO: WARNING: I'm forcing you to use regex because I can't
+        find a local rx library and the one included with this
+        distribution doesn't work on 64-bit machines like yours" >&5
+echo "$as_me: WARNING: I'm forcing you to use regex because I can't
+        find a local rx library and the one included with this
+        distribution doesn't work on 64-bit machines like yours" >&2;}
+      case $LIBOBJS in
+    "regex.$ac_objext"   | \
+  *" regex.$ac_objext"   | \
+    "regex.$ac_objext "* | \
+  *" regex.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS regex.$ac_objext" ;;
+esac
+
+    else
+      case $LIBOBJS in
+    "rx.$ac_objext"   | \
+  *" rx.$ac_objext"   | \
+    "rx.$ac_objext "* | \
+  *" rx.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS rx.$ac_objext" ;;
+esac
+
+    fi
+
+fi
+
+fi
+
+echo "$as_me:$LINENO: checking whether GNU readline requested" >&5
+echo $ECHO_N "checking whether GNU readline requested... $ECHO_C" >&6
+
+# Check whether --with-gnu_readline or --without-gnu_readline was given.
+if test "${with_gnu_readline+set}" = set; then
+  withval="$with_gnu_readline"
+  if test "$withval" = yes; then
+      echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+      ac_with_gnu_readline=1
+    else
+      echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+    fi
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi;
+
+  if test -n "$ac_with_gnu_readline"; then
+    if test "${ac_cv_header_readline_readline_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for readline/readline.h" >&5
+echo $ECHO_N "checking for readline/readline.h... $ECHO_C" >&6
+if test "${ac_cv_header_readline_readline_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_readline_readline_h" >&5
+echo "${ECHO_T}$ac_cv_header_readline_readline_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking readline/readline.h usability" >&5
+echo $ECHO_N "checking readline/readline.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <readline/readline.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking readline/readline.h presence" >&5
+echo $ECHO_N "checking readline/readline.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <readline/readline.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: readline/readline.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: readline/readline.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: readline/readline.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: readline/readline.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: readline/readline.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: readline/readline.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: readline/readline.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: readline/readline.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: readline/readline.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: readline/readline.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: readline/readline.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: readline/readline.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: readline/readline.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: readline/readline.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: readline/readline.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: readline/readline.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for readline/readline.h" >&5
+echo $ECHO_N "checking for readline/readline.h... $ECHO_C" >&6
+if test "${ac_cv_header_readline_readline_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_readline_readline_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_readline_readline_h" >&5
+echo "${ECHO_T}$ac_cv_header_readline_readline_h" >&6
+
+fi
+if test $ac_cv_header_readline_readline_h = yes; then
+  ac_mg_readline_header_found=1
+else
+  { echo "$as_me:$LINENO: WARNING: Can't find GNU readline headers; configuring without \
+GNU readline support" >&5
+echo "$as_me: WARNING: Can't find GNU readline headers; configuring without \
+GNU readline support" >&2;}
+fi
+
+
+    if test -n "$ac_mg_readline_header_found"; then
+      # first check whether we can find the readline library itself
+      echo "$as_me:$LINENO: checking for main in -lreadline" >&5
+echo $ECHO_N "checking for main in -lreadline... $ECHO_C" >&6
+if test "${ac_cv_lib_readline_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lreadline  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_readline_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_readline_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_readline_main" >&5
+echo "${ECHO_T}$ac_cv_lib_readline_main" >&6
+if test $ac_cv_lib_readline_main = yes; then
+  ac_mg_readline_lib_found=1
+         cat >>confdefs.h <<\_ACEOF
+#define WITH_GNU_READLINE 1
+_ACEOF
+
+         LIBS="$LIBS -lreadline"
+else
+  { echo "$as_me:$LINENO: WARNING: Can't find GNU readline library; configuring without \
+GNU readline support" >&5
+echo "$as_me: WARNING: Can't find GNU readline library; configuring without \
+GNU readline support" >&2;}
+fi
+
+      if test -n "$ac_mg_readline_lib_found"; then
+        # on some systems, readline needs curses.  It is difficult to
+        #  determine whether this is necessary on the current system,
+        #  since other undefined symbols can be turned up by an
+        #  AC_CHECK_LIB(readline, readline) test that are actually defined
+	#  by mg itself (e.g. xmalloc, xrealloc).  So, if we find libcurses,
+	#  we just bung it on and hope for the best.
+	echo "$as_me:$LINENO: checking for main in -lcurses" >&5
+echo $ECHO_N "checking for main in -lcurses... $ECHO_C" >&6
+if test "${ac_cv_lib_curses_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcurses  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_curses_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_curses_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_curses_main" >&5
+echo "${ECHO_T}$ac_cv_lib_curses_main" >&6
+if test $ac_cv_lib_curses_main = yes; then
+  LIBS="$LIBS -lcurses"
+fi
+
+      fi
+    fi
+  fi
+
+
+# text for endianness
+echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
+if test "${ac_cv_c_bigendian+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_bigendian=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+# It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+  # try to guess the endianness by grepping values into an object file
+  ac_cv_c_bigendian=unknown
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+  ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+  if test "$ac_cv_c_bigendian" = unknown; then
+    ac_cv_c_bigendian=no
+  else
+    # finding both strings is unlikely to happen, but who knows?
+    ac_cv_c_bigendian=unknown
+  fi
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+int
+main ()
+{
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long l;
+    char c[sizeof (long)];
+  } u;
+  u.l = 1;
+  exit (u.c[sizeof (long) - 1] == 1);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6
+case $ac_cv_c_bigendian in
+  yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+  no)
+     ;;
+  *)
+    { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+
+# ---------------------------------------------------------------------------
+if test "$ac_cv_func_alloca" = 'no'; then
+  case $LIBOBJS in
+    "xmalloc.$ac_objext"   | \
+  *" xmalloc.$ac_objext"   | \
+    "xmalloc.$ac_objext "* | \
+  *" xmalloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS xmalloc.$ac_objext" ;;
+esac
+
+  case $LIBOBJS in
+    "error.$ac_objext"   | \
+  *" error.$ac_objext"   | \
+    "error.$ac_objext "* | \
+  *" error.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS error.$ac_objext" ;;
+esac
+
+fi
+
+
+# ---------------------------------------------------------------------------
+# see if the user wants to override use of long long
+# Check whether --enable-override-longlong or --disable-override-longlong was given.
+if test "${enable_override_longlong+set}" = set; then
+  enableval="$enable_override_longlong"
+  cat >>confdefs.h <<\_ACEOF
+#define DISABLE_LONG_LONG 1
+_ACEOF
+
+fi;
+
+
+# ---------------------------------------------------------------------------
+
+                                                  ac_config_files="$ac_config_files Makefile text/Makefile lib/Makefile jni/Makefile java/org/greenstone/mgpp/Makefile"
+          ac_config_commands="$ac_config_commands default"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[	 ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[	 ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+	 sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+		   instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+		   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "text/Makefile" ) CONFIG_FILES="$CONFIG_FILES text/Makefile" ;;
+  "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
+  "jni/Makefile" ) CONFIG_FILES="$CONFIG_FILES jni/Makefile" ;;
+  "java/org/greenstone/mgpp/Makefile" ) CONFIG_FILES="$CONFIG_FILES java/org/greenstone/mgpp/Makefile" ;;
+  "default" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
+  "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@PACKAGE@,$PACKAGE,;t t
+s,@VERSION@,$VERSION,;t t
+s,@ENABLE_ACCENTFOLD@,$ENABLE_ACCENTFOLD,;t t
+s,@CXX@,$CXX,;t t
+s,@CXXFLAGS@,$CXXFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CXX@,$ac_ct_CXX,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@AWK@,$AWK,;t t
+s,@YACC@,$YACC,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@LN_S@,$LN_S,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@U@,$U,;t t
+s,@ANSI2KNR@,$ANSI2KNR,;t t
+s,@UNAC_DIR@,$UNAC_DIR,;t t
+s,@ALLOCA@,$ALLOCA,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@JNIINC@,$JNIINC,;t t
+s,@JNISUFFIX@,$JNISUFFIX,;t t
+s,@JNIFLAGS@,$JNIFLAGS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+	cat >$tmp/stdin
+	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+				     sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+	 # Absolute (can't be DOS-style, as IFS=:)
+	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 echo "$f";;
+      *) # Relative
+	 if test -f "$f"; then
+	   # Build tree
+	   echo "$f"
+	 elif test -f "$srcdir/$f"; then
+	   # Source tree
+	   echo "$srcdir/$f"
+	 else
+	   # /dev/null tree
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([	 ]*\)#\([	 ]*define[	 ][	 ]*\)'
+ac_dB='[	 ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([	 ]*\)#\([	 ]*\)undef\([	 ][	 ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+	cat >$tmp/stdin
+	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+	 # Absolute (can't be DOS-style, as IFS=:)
+	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 # Do quote $f, to prevent DOS paths from being IFS'd.
+	 echo "$f";;
+      *) # Relative
+	 if test -f "$f"; then
+	   # Build tree
+	   echo "$f"
+	 elif test -f "$srcdir/$f"; then
+	   # Source tree
+	   echo "$srcdir/$f"
+	 else
+	   # /dev/null tree
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[	 ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*\)\(([^)]*)\)[	 ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[	 ]*#[	 ]*undef[	 ][	 ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if grep "^[	 ]*#[	 ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[	 ]*#[	 ]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo '  fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[	 ]*#[	 ]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+      { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+  ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+  ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+  ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_dest" : 'X\(//\)[^/]' \| \
+	 X"$ac_dest" : 'X\(//\)$' \| \
+	 X"$ac_dest" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+  case $ac_dest in
+    default ) test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h ;;
+  esac
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
Index: /indexers/branches/3.03a/mgpp/configure.in
===================================================================
--- /indexers/branches/3.03a/mgpp/configure.in	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/configure.in	(revision 14757)
@@ -0,0 +1,170 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(text/MGQuery.cpp)
+AC_CONFIG_HEADER(config.h)
+AC_ARG_PROGRAM
+
+dnl
+PACKAGE=mgpp
+VERSION=1.3
+
+LDFLAGS=
+
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
+AC_SUBST(PACKAGE)
+AC_SUBST(VERSION)
+
+dnl 
+dnl disable compilation of accent folding stuff for mgpp (and one day mg)
+dnl
+AC_ARG_ENABLE(accentfold, [  --disable-accentfold          Disable Accent Folding for MGPP], ENABLE_ACCENTFOLD=0, ENABLE_ACCENTFOLD=1)
+AC_DEFINE(ENABLE_ACCENTFOLD, $ENABLE_ACCENTFOLD)
+AC_SUBST(ENABLE_ACCENTFOLD)
+
+dnl Checks for programs.
+AC_PROG_CXX
+AC_PROG_AWK
+AC_PROG_YACC
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_AIX
+AC_ISC_POSIX
+AC_MINIX
+fp_C_PROTOTYPES
+AC_C_CONST
+AC_TYPE_OFF_T
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+AC_STRUCT_TM
+
+dnl
+dnl look for unac package if not in standard location
+dnl
+dnl is it ok to use `pwd` like this??
+AC_ARG_WITH(unac, [  --with-unac=dir         Use local unac library and headers], UNAC_DIR=$withval, UNAC_DIR="`pwd`/../packages/unac")
+AC_DEFINE_UNQUOTED(UNAC_DIR, "$UNAC_DIR")
+AC_SUBST(UNAC_DIR)
+
+
+dnl --- This should be in the stdc checking -----------------
+if test "$ac_cv_prog_cc_stdc" = '-Xc'; then
+dnl The Pyramids running SMP_DC.OSx on MIPS r3000 chips with
+dnl /usr/opt/cc3.11/bin/cc treat -Xc as full ANSI mode - no POSIX or
+dnl XOPEN extensions (like popen).
+dnl Unfortunately -D_{XOPEN,POSIX}_SOURCE can't provide all that mg
+dnl needs. So drop back to -Xa
+AC_TRY_COMPILE(
+[#include <stdio.h>
+], [ FILE *rubbish = popen("yes", "r"); ],,
+[CC="`echo $CC | sed 's/-Xc/-Xa/'`"    ac_cv_prog_cc_stdc='-Xa'])
+fi
+dnl ----------------------
+
+
+dnl Checks for libraries.
+dnl Replace `main' with a function in -lg:
+AC_CHECK_LIB(g, main)
+dnl Replace `main' with a function in -lm:
+AC_CHECK_LIB(m, main)
+dnl Replace `main' with a function in -lstdc++:
+AC_CHECK_LIB(stdc++, main)
+dnl Replace `main' with a function in -lcrypt:
+AC_CHECK_LIB(crypt, main)
+if test $ENABLE_ACCENTFOLD = 1; then
+AC_HAVE_LIBRARY(iconv)
+fi
+
+
+dnl Checks for header files.
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h limits.h sys/time.h unistd.h crypt.h string.h memory.h sys/procfs.h)
+AC_EGREP_HEADER(fread, stdio.h, AC_DEFINE(HAVE_FREAD_DECL))
+AC_EGREP_HEADER(fgetc, stdio.h, AC_DEFINE(HAVE_FGETC_DECL))
+AC_EGREP_HEADER(pr_brksize, sys/procfs.h, AC_DEFINE(HAVE_PR_BRKSIZE))
+
+dnl Checks for library functions.
+AC_FUNC_ALLOCA
+AC_PROG_GCC_TRADITIONAL
+AC_TYPE_SIGNAL
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS(ftime select strftime strtol getrusage times mallinfo setbuffer getpagesize strerror)
+AC_REPLACE_FUNCS(ftruncate strstr strcasecmp)
+
+
+dnl see if gettext is in libc. (try the textdomain() function).
+AC_CHECK_FUNC(textdomain, AC_DEFINE(ENABLE_NLS ,1) )
+
+# we need to set an extended JNI path for Mac OS/Darwin, as jni.h is on
+# a non-standard Path
+# is there a better way to do this??
+AC_MSG_CHECKING(for OS to set JNI options)
+# set defaults
+JNIINC=""
+JNISUFFIX="so"
+JNIFLAGS="-shared"
+
+if test "`(uname -s) 2> /dev/null`" = 'Darwin'; then
+  AC_MSG_RESULT(Darwin)
+  JNIINC="-I/System/Library/Frameworks/JavaVM.framework/Headers/ "
+  JNISUFFIX="jnilib"
+  JNIFLAGS="-dynamiclib -fno-common -single_module -framework JavaVM"
+fi
+if test "`(uname -s) 2> /dev/null`" = 'SunOS'; then
+  AC_MSG_RESULT(Solaris)
+  JNIINC="-I\$(JAVA_HOME)/include/solaris "
+fi
+if test "`(uname -s) 2> /dev/null`" = 'Linux'; then
+  AC_MSG_RESULT(Linux)
+  JNIINC="-I\$(JAVA_HOME)/include/linux "
+fi
+
+AC_SUBST(JNIINC)
+AC_SUBST(JNISUFFIX)
+AC_SUBST(JNIFLAGS)
+
+# *** Custom checking (based on GNU tar configure.in) ***
+# ---------------------------------------------------------------------------
+AC_MSG_CHECKING(for HP-UX needing gmalloc)
+if test "`(uname -s) 2> /dev/null`" = 'HP-UX'; then
+  AC_MSG_RESULT(yes)
+  AC_LIBOBJ(gmalloc)
+  AC_DEFINE(HAVE_VALLOC)
+else
+  AC_MSG_RESULT(no)
+  AC_CHECK_FUNCS(valloc)
+fi
+
+fp_WITH_DMALLOC
+fp_WITH_REGEX
+fp_WITH_GNU_READLINE
+
+# text for endianness
+AC_C_BIGENDIAN
+
+# ---------------------------------------------------------------------------
+if test "$ac_cv_func_alloca" = 'no'; then
+dnl    support functions for alloca.c
+  AC_LIBOBJ(xmalloc)
+  AC_LIBOBJ(error)
+fi
+
+
+# ---------------------------------------------------------------------------
+# see if the user wants to override use of long long
+AC_ARG_ENABLE(override-longlong,
+[  --enable-override-longlong
+                          overide use of long long with GCC],
+  AC_DEFINE(DISABLE_LONG_LONG))
+
+
+# ---------------------------------------------------------------------------
+
+AC_OUTPUT([Makefile text/Makefile lib/Makefile 
+   jni/Makefile java/org/greenstone/mgpp/Makefile], 
+[test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h])
Index: /indexers/branches/3.03a/mgpp/install-sh
===================================================================
--- /indexers/branches/3.03a/mgpp/install-sh	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/install-sh	(revision 14757)
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
Index: /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPDocInfo.java
===================================================================
--- /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPDocInfo.java	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPDocInfo.java	(revision 14757)
@@ -0,0 +1,20 @@
+package org.greenstone.mgpp;
+
+/** DocInfo 'struct' class for a search result from mgpp
+ * used by MGPPQueryResult
+ *
+ * @See MGPPQueryResult
+ */
+public class MGPPDocInfo {
+
+    public long num_=0;
+    public float rank_=0;
+
+    public MGPPDocInfo(long doc, float rank) {
+	num_=doc;
+	rank_=rank;
+    }
+    public String toString(){
+	return ""+num_+"("+rank_+")";
+    }
+}
Index: /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPPassesWrapper.java
===================================================================
--- /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPPassesWrapper.java	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPPassesWrapper.java	(revision 14757)
@@ -0,0 +1,146 @@
+/*
+ *    MGPassesWrapper.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.mgpp;
+
+
+/** java wrapper class for access to gs3_mgpp_passes in C
+ *
+ * the native side implemented in MGPPPassesWrapperImpl.c
+ */
+
+public class MGPPPassesWrapper
+{
+    static {
+	System.loadLibrary("mgpppassjni");
+	initIDs();
+    }
+    
+    //static final public char INVF_LEVEL_1 = '1';
+    //static final public char INVF_LEVEL_2 = '2';
+    //static final public char INVF_LEVEL_3 = '3';
+    
+    static final public int TEXT_PASS_1 = 0;
+    static final public int TEXT_PASS_2 = 1;
+    static final public int INDEX_PASS_1 = 2;
+    static final public int INDEX_PASS_2 = 3;
+    static final public int SPECIAL_PASS = 4;
+
+    //static final public int NO_STEM_OR_CASE = 0;
+    //static final public int CASE_ONLY = 1;
+    //static final public int STEM_ONLY = 2;
+    //static final public int STEM_AND_CASE = 3;
+
+    //static final public String STEMMER_ENGLISH = "english";
+    //static final public String STEMMER_FRENCH = "french";
+    //static final public String STEMMER_LOVIN = "lovin";
+    //static final public String STEMMER_SIMPLE_FRENCH = "simple-french";
+
+    //static final private char END_OF_DOCUMENT = (char) 2;
+
+    public MGPPPassesWrapper() {
+	initCSide();
+    }
+
+    /** initialise the pass through the documents */
+    public native boolean init();
+    
+    /** add a pass declaration */
+    public void addPass(int pass) {
+	switch (pass) {
+	case TEXT_PASS_1:
+	    addPass('T','1');
+	    break;
+	case TEXT_PASS_2:
+	    addPass('T','2');	    
+	    break;
+	case INDEX_PASS_1:
+	    addPass('I','1');
+	    break;
+	case INDEX_PASS_2:
+	    addPass('I','2');
+	    break;
+	case SPECIAL_PASS:
+	    addPass('S','1');
+	    break;
+	}
+    }
+    /** set the base path */
+    public native void setBasePath(String basepath);
+    /** set the file name */
+    public native void setFileName(String filename);
+
+    /** set the Document tag */
+    public native void setDocumentTag(String tag);
+
+    /** add a level tag */
+    public native void addLevelTag(String tag);
+
+    /** set the index level (default word level) */
+    public native void setIndexLevel(String tag);
+    
+    /** Maximum amount of memory to use for  the index  pass-2  file
+	inversion  in  megabytes.
+    */
+    public native void setInversionMemLimit(int limit);
+
+    /** process one or more MGPP documents */
+    public boolean processDocument(String doc_text) {
+	try {
+	    processMGPPDocument(doc_text.getBytes("UTF-8"));
+	} catch (Exception e) {
+	    e.printStackTrace();
+	    return false;
+	}
+	return true;
+    }
+   
+    /** finalise the pass through the documents */
+    public native boolean finish();
+
+    /** get the exit value once finished */
+    public native int exitValue();
+
+    /** initialises field and method IDs for java side to enable access on C side */
+    private static native void initIDs();
+
+    /** initialises any C side stuff */
+    private native boolean initCSide();
+
+    private native void addPass(char pass_type, char pass_num);
+
+    /** process a MGPP document */
+    private native boolean processMGPPDocument(byte[] text);
+
+    public static void main(String []args) {
+
+	String doc = "<Document>hello there kath<Title>this is a title</Title></Document><Document>my name is helen</Document>";
+
+	MGPPPassesWrapper wrapper = new MGPPPassesWrapper();
+	wrapper.addPass(TEXT_PASS_1);
+	wrapper.addPass(TEXT_PASS_2);
+	wrapper.setDocumentTag("Document");
+	wrapper.setBasePath("/tmp/kjdon/index");
+	wrapper.setFileName("idx");
+
+	wrapper.init();
+	wrapper.processDocument(doc);
+	wrapper.finish();
+
+    }
+}
Index: /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPQueryResult.java
===================================================================
--- /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPQueryResult.java	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPQueryResult.java	(revision 14757)
@@ -0,0 +1,108 @@
+package org.greenstone.mgpp;
+
+import java.util.Vector;
+
+/** a java version of QueryResult for mgpp
+ *
+ * contains get methods for the java side, and simple
+ * set methods to be called from c++ side
+ *
+ */
+public class MGPPQueryResult {
+
+    /** the list of MGPPDocInfo */
+    protected Vector docs_=null;
+    /** the list of MGPPTermInfo */
+    protected Vector terms_=null;
+    /** the total number of docs found - not likely to be the size of docs_*/
+    protected long total_num_docs_=0;
+    /** whether a syntax error has occurred */
+    protected boolean syntax_error_ = false;
+    
+    MGPPQueryResult() {
+	docs_ = new Vector();
+	terms_ = new Vector();
+    }
+    /** clear the info from the last query - should be called before setting any new docs/terms */
+    public void clear() {
+	total_num_docs_=0;
+	docs_.clear();
+	terms_.clear();
+	syntax_error_ = false;
+    }
+    /** returns the result as a String - useful for printing out results */
+    public String toString() {
+	
+	String result = "";
+	result += "docs (ranks): ";
+	for (int i=0; i<docs_.size(); i++) {
+	    result += ((MGPPDocInfo)docs_.elementAt(i)).toString()+", ";
+	}
+	result += "\nterms: ";
+	for (int i=0; i<terms_.size(); i++) {
+	    result += ((MGPPTermInfo)terms_.elementAt(i)).toString()+", ";
+	}
+	result += "\nactual number of docs found = "+total_num_docs_;
+
+	return result;
+    }
+    /** a shorter representation - just terms and total docs - not the 
+	individual docnums and ranks */
+    public String toShortString() {
+	String result = "";
+	result += "\nterms: ";
+	for (int i=0; i<terms_.size(); i++) {
+	    result += ((MGPPTermInfo)terms_.elementAt(i)).toString()+", ";
+	}
+	result += "\nactual number of docs found = "+total_num_docs_;
+	return result;
+    }
+
+    // set methods used by c++ code
+    
+    public void setTotalDocs(long num) {
+	total_num_docs_=num;
+    }
+
+    public void addDoc(long doc, float rank) {
+	MGPPDocInfo doc_info = new MGPPDocInfo(doc, rank);
+	docs_.add(doc_info);
+    }
+
+    public void addTerm(String term, String tag, int stem, long match, long freq, String[] equivs) {
+	MGPPTermInfo ti = new MGPPTermInfo();
+	ti.term_=term;
+	ti.tag_=tag;
+	ti.stem_method_=stem;
+	ti.match_docs_=match;
+	ti.term_freq_=freq;
+	if (equivs!=null) {
+	  for (int i=0; i<equivs.length; i++) {
+	    ti.equiv_terms_.add(equivs[i]);
+	  }
+	}
+	terms_.add(ti);
+    }
+
+    // get methods for the java side
+    public Vector getDocs() {
+	return docs_;
+    }
+
+    public Vector getTerms() {
+	return terms_;
+    }
+
+    public long getTotalDocs() {
+	return total_num_docs_;
+    }
+     
+    public void setSyntaxError(boolean error) {
+	syntax_error_ = error;
+    }
+
+    public boolean hasSyntaxError() {
+	return syntax_error_;
+    }
+}
+
Index: /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPRetrieveWrapper.java
===================================================================
--- /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPRetrieveWrapper.java	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPRetrieveWrapper.java	(revision 14757)
@@ -0,0 +1,126 @@
+/*
+ *    MGPPRetrieveWrapper.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.mgpp;
+
+import java.util.Vector;
+
+/** java wrapper class for access to mgpp in C++
+ *
+ * the native side implemented in MGPPWrapperImpl.cpp
+ * uses MGPPQueryResult to hold the result of a query. the 
+ * result of a getDocument is a String
+ * uses the jni
+ *
+ *@see MGPPQueryResult
+ */
+public class MGPPRetrieveWrapper {
+  
+    /** the query result
+     * will be filled in by runQuery
+     */
+    protected MGPPQueryResult mgpp_query_result_=null; 
+    /** pointer to c++ MGPPWrapperData class - cached indexData and queryInfo
+     */
+    protected long mgpp_data_ptr_=0;
+
+    static {
+	System.loadLibrary("mgppretrievejni");
+	initIDs();
+    }
+    
+    public MGPPRetrieveWrapper() {
+	mgpp_query_result_ = new MGPPQueryResult();
+	initCppSide();
+    }
+
+    /** initialises field and method IDs for java side to enable access on
+	C++ side */
+    //these two init methods and the load and unload methods are shared by search and retrieve
+    private static native void initIDs();
+
+    /** initialises the mgpp_data_ptr_ */
+    private native boolean initCppSide();
+
+    /** returns a document: number docnum at level level 
+     * text_path path should provide
+     * the absolute location of the mgpp text files eg ..../index/text/demo
+     * returns the doc in utf-8
+     */
+    public native String getDocument(String text_path,
+				     String level,
+				     long docnum );
+
+    /** the public method - converts between utf-8 and unicode
+     */
+    // public String getDocument(String text_path,
+    //		      String level,
+    //		      long docnum ) {
+
+    //String utf8_doc = getUtF8Document(base_dir, text_path, level, docnum);
+	
+    /** load up the data structure for index 
+     * - maintains state between requests as can be slow  
+     * index_path should provide
+     * the absolute location of the mgpp index files eg ..../index/tt/demo 
+     */
+    public native boolean loadIndexData(String index_path);
+    /** unloads the data */
+    public native boolean unloadIndexData();
+
+    // query param methods
+//
+//    /** if on=true, sets default stemming on  - its off by default*/
+//    public native void setStem(boolean on);
+//    
+//    /** if on=true, sets default accentfolding on  - its off by default*/
+//    public native void setAccentFold(boolean on);
+//
+//   /** if on=true, sets default casefolding on - its off by default */
+//   public native void setCase(boolean on);
+//    /** default is 50 */
+//    public native void setMaxDocs(int num);
+//    /** if on=true, sorts by rank, otherwise returns in build order - 
+//	default is on */
+//    public native void setSortByRank(boolean on);
+//    /** if on=true, a query returns term freq info - default is on */
+//    public native void setReturnTerms(boolean on);
+//    /** sets the granularity of the  query  - default 'Document' */
+//    public native void setQueryLevel(String level);
+//    /** sets the granularity of the result - default 'Document' */
+//    public native void setReturnLevel(String level);
+//    /** sets the default boolean operator - AND(=1)/OR(=0) */
+//    public native void setMatchMode(int mode);
+//
+//    /** sets maxnumeric */
+//    public native void setMaxNumeric(int maxnumeric);
+//    /** returns a string with all the current query param settings */
+//    public native String getQueryParams();
+//
+//    /** actually carry out the query. Use the set methods to set any query
+//	params 
+//    * writes the result to query_result
+//    */
+//    public native void runQuery(String query_string); 
+//
+//    /** get the result out of the wrapper */
+//    public MGPPQueryResult getQueryResult() {
+//	return mgpp_query_result_;
+//    }
+//    
+}
Index: /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPSearchWrapper.java
===================================================================
--- /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPSearchWrapper.java	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPSearchWrapper.java	(revision 14757)
@@ -0,0 +1,126 @@
+/*
+ *    MGPPSearchWrapper.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.mgpp;
+
+import java.util.Vector;
+
+/** java wrapper class for access to mgpp in C++
+ *
+ * the native side implemented in MGPPWrapperImpl.cpp
+ * uses MGPPQueryResult to hold the result of a query. the 
+ * result of a getDocument is a String
+ * uses the jni
+ *
+ *@see MGPPQueryResult
+ */
+public class MGPPSearchWrapper {
+  
+    /** the query result
+     * will be filled in by runQuery
+     */
+    protected MGPPQueryResult mgpp_query_result_=null; 
+    /** pointer to c++ MGPPWrapperData class - cached indexData and queryInfo
+     */
+    protected long mgpp_data_ptr_=0;
+
+    static {
+	System.loadLibrary("mgppsearchjni");
+	initIDs();
+    }
+    
+    public MGPPSearchWrapper() {
+	mgpp_query_result_ = new MGPPQueryResult();
+	initCppSide();
+    }
+
+    /** initialises field and method IDs for java side to enable access on
+	C++ side */
+    private static native void initIDs();
+
+    /** initialises the mgpp_data_ptr_ */
+    private native boolean initCppSide();
+
+    /** returns a document: number docnum at level level 
+     * text_path path should provide
+     * the absolute location of the mgpp text files eg ..../index/text/demo
+     * returns the doc in utf-8
+     */
+    //only this method is for search purpose
+//    public native String getDocument(String text_path,
+//				     String level,
+//				     long docnum );
+
+    /** the public method - converts between utf-8 and unicode
+     */
+    // public String getDocument(String text_path,
+    //		      String level,
+    //		      long docnum ) {
+
+    //String utf8_doc = getUtF8Document(base_dir, text_path, level, docnum);
+	
+    /** load up the data structure for index 
+     * - maintains state between requests as can be slow  
+     * index_path should provide
+     * the absolute location of the mgpp index files eg ..../index/tt/demo 
+     */
+    public native boolean loadIndexData(String index_path);
+    /** unloads the data */
+    public native boolean unloadIndexData();
+
+    // query param methods
+
+    /** if on=true, sets default stemming on  - its off by default*/
+    public native void setStem(boolean on);
+    
+    /** if on=true, sets default accentfolding on  - its off by default*/
+    public native void setAccentFold(boolean on);
+
+   /** if on=true, sets default casefolding on - its off by default */
+   public native void setCase(boolean on);
+    /** default is 50 */
+    public native void setMaxDocs(int num);
+    /** if on=true, sorts by rank, otherwise returns in build order - 
+	default is on */
+    public native void setSortByRank(boolean on);
+    /** if on=true, a query returns term freq info - default is on */
+    public native void setReturnTerms(boolean on);
+    /** sets the granularity of the  query  - default 'Document' */
+    public native void setQueryLevel(String level);
+    /** sets the granularity of the result - default 'Document' */
+    public native void setReturnLevel(String level);
+    /** sets the default boolean operator - AND(=1)/OR(=0) */
+    public native void setMatchMode(int mode);
+
+    /** sets maxnumeric */
+    public native void setMaxNumeric(int maxnumeric);
+    /** returns a string with all the current query param settings */
+    public native String getQueryParams();
+
+    /** actually carry out the query. Use the set methods to set any query
+	params 
+    * writes the result to query_result
+    */
+    public native void runQuery(String query_string); 
+
+    /** get the result out of the wrapper */
+    public MGPPQueryResult getQueryResult() {
+	return mgpp_query_result_;
+    }
+    
+}
Index: /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPTermInfo.java
===================================================================
--- /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPTermInfo.java	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPTermInfo.java	(revision 14757)
@@ -0,0 +1,46 @@
+package org.greenstone.mgpp;
+
+import java.util.Vector;
+
+/** TermInfo 'struct' class for a search result from mgpp
+ * used by MGPPQueryResult
+ * 
+ *
+ *@see MGPPQueryResult
+ */
+public class MGPPTermInfo {
+
+    /** the term itself */
+    public String term_=null;
+    /** the tag - level or metadata - for which the query was done */
+    public String tag_=null;
+    /** what stem and casefold method was used
+	0 = none
+	1 = casefold only
+	2 = stem only
+	3 = casefold and stem */
+    public int stem_method_=0;
+    /** the number of documents containing this term (where document is defined by the tag data */
+    public long match_docs_=0;
+    /** overall term freq  - word level*/
+    public long term_freq_=0;
+    /** list of stemmed and casefolded equivalent terms - if stem_method_ is non-zero 
+      - Vector of Strings */
+    public Vector equiv_terms_=null;
+
+    public MGPPTermInfo() {
+	equiv_terms_ = new Vector();
+    }
+	
+    /** output the class as a string */
+    public String toString() {
+	String result="";
+	result +="<"+tag_+">\""+term_+"\"stem("+stem_method_+")docs("+match_docs_;
+	result +=")freq("+term_freq_+")equiv terms(";
+	for (int i=0; i<equiv_terms_.size(); i++) {
+	    result += (String)equiv_terms_.elementAt(i)+", ";
+	}
+	result += ")";
+	return result;
+    }
+}
Index: /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPWrapper.java
===================================================================
--- /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPWrapper.java	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/MGPPWrapper.java	(revision 14757)
@@ -0,0 +1,108 @@
+
+package org.greenstone.mgpp;
+
+import java.util.Vector;
+
+/** java wrapper class for access to mgpp in C++
+ *
+ * the native side implemented in MGPPWrapperImpl.cpp
+ * uses MGPPQueryResult to hold the result of a query. the 
+ * result of a getDocument is a String
+ * uses the jni
+ *
+ *@see MGPPQueryResult
+ */
+public class MGPPWrapper {
+  
+    /** the query result
+     * will be filled in by runQuery
+     */
+    protected MGPPQueryResult mgpp_query_result_=null; 
+    /** pointer to c++ MGPPWrapperData class - cached indexData and queryInfo
+     */
+    protected long mgpp_data_ptr_=0;
+
+    static {
+	System.loadLibrary("mgppjni");
+	initIDs();
+    }
+    
+    public MGPPWrapper() {
+	mgpp_query_result_ = new MGPPQueryResult();
+	initCppSide();
+    }
+
+    /** initialises field and method IDs for java side to enable access on
+	C++ side */
+    private static native void initIDs();
+
+    /** initialises the mgpp_data_ptr_ */
+    private native boolean initCppSide();
+
+    /** returns a document: number docnum at level level 
+     * text_path path should provide
+     * the absolute location of the mgpp text files eg ..../index/text/demo
+     * returns the doc in utf-8
+     */
+    public native String getDocument(String text_path,
+				     String level,
+				     long docnum );
+
+    /** the public method - converts between utf-8 and unicode
+     */
+    // public String getDocument(String text_path,
+    //		      String level,
+    //		      long docnum ) {
+
+    //String utf8_doc = getUtF8Document(base_dir, text_path, level, docnum);
+	
+    /** load up the data structure for index 
+     * - maintains state between requests as can be slow  
+     * index_path should provide
+     * the absolute location of the mgpp index files eg ..../index/tt/demo 
+     */
+    public native boolean loadIndexData(String index_path);
+    /** unloads the data */
+    public native boolean unloadIndexData();
+
+    // query param methods
+
+    /** if on=true, sets default stemming on  - its off by default*/
+    public native void setStem(boolean on);
+    
+    /** if on=true, sets default accentfolding on  - its off by default*/
+    public native void setAccentFold(boolean on);
+
+   /** if on=true, sets default casefolding on - its off by default */
+   public native void setCase(boolean on);
+    /** default is 50 */
+    public native void setMaxDocs(int num);
+    /** if on=true, sorts by rank, otherwise returns in build order - 
+	default is on */
+    public native void setSortByRank(boolean on);
+    /** if on=true, a query returns term freq info - default is on */
+    public native void setReturnTerms(boolean on);
+    /** sets the granularity of the  query  - default 'Document' */
+    public native void setQueryLevel(String level);
+    /** sets the granularity of the result - default 'Document' */
+    public native void setReturnLevel(String level);
+    /** sets the default boolean operator - AND(=1)/OR(=0) */
+    public native void setMatchMode(int mode);
+
+    /** sets maxnumeric */
+    public native void setMaxNumeric(int maxnumeric);
+    /** returns a string with all the current query param settings */
+    public native String getQueryParams();
+
+    /** actually carry out the query. Use the set methods to set any query
+	params 
+    * writes the result to query_result
+    */
+    public native void runQuery(String query_string); 
+
+    /** get the result out of the wrapper */
+    public MGPPQueryResult getQueryResult() {
+	return mgpp_query_result_;
+    }
+    
+}
Index: /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/Makefile.in
===================================================================
--- /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/Makefile.in	(revision 14757)
@@ -0,0 +1,63 @@
+
+SHELL = /bin/sh
+VPATH = @srcdir@
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+bindir = @bindir@
+srcdir = @srcdir@
+libdir = @libdir@
+subdir = java/org/greenstone/mgpp
+top_srcdir = @top_srcdir@
+transform = @program_transform_name@
+
+AR = ar
+CC = @CC@
+CXX = @CXX@
+JAVAC = $(JAVA_HOME)/bin/javac
+JAVAH = $(JAVA_HOME)/bin/javah
+JAR = $(JAVA_HOME)/bin/jar
+CFLAGS = @CFLAGS@ -ansi -DSILENT -DSHORT_SUFFIX
+CXXFLAGS = @CXXFLAGS@ -DSILENT -DSHORT_SUFFIX
+DEFS = @DEFS@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBS =  -lstdc++ @LIBS@
+TOUCH = echo timestamp >
+AWK = @AWK@
+
+MGPPHOME=../../../..
+JAVACLASSDIR=./classes
+JAVASRCDIR=../../..
+JAVACOPTIONS= -deprecation -g -O
+JAVACLASSPATH=$(JAVACLASSDIR):
+
+datadir = $(prefix)/share
+libexecdir = $(exec_prefix)/libexec
+localedir = $(datadir)/locale
+mandir = $(prefix)/man/man1
+
+
+all: setup compile
+
+setup:
+	mkdir -p $(JAVACLASSDIR)
+
+compile: setup
+	$(JAVAC) -d $(JAVACLASSDIR) -sourcepath $(JAVASRCDIR) $(JAVACOPTIONS) *.java
+	$(JAVAH) -classpath $(JAVACLASSPATH) -d $(MGPPHOME)/jni org.greenstone.mgpp.MGPPWrapper
+	$(JAVAH) -classpath $(JAVACLASSPATH) -d $(MGPPHOME)/jni org.greenstone.mgpp.MGPPPassesWrapper
+
+	$(JAR) cf $(MGPPHOME)/mgpp.jar -C $(JAVACLASSDIR) org
+
+clean:
+	rm -rf $(JAVACLASSDIR) $(MGPPHOME)/mgpp.jar $(MGPPHOME)/jni/org_greenstone_mgpp_MGPPWrapper.h $(MGPPHOME)/jni/org_greenstone_mgpp_MGPPPassesWrapper.h
+
+install:
+
+distclean: clean
+	rm -f Makefile
+
+
Index: /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/Queryer.java
===================================================================
--- /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/Queryer.java	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/Queryer.java	(revision 14757)
@@ -0,0 +1,184 @@
+package org.greenstone.mgpp;
+
+import java.util.Vector;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.File;
+/** Queryer - java port of c++ Queryer 
+ * - uses MGPPWrapper to access mgpp
+ * only has get document and search - full text browse not implemented
+ *
+ * run as:
+ * java org.greenstone.mgpp.Queryer <basedir> <indexdir> <textdir>
+ *@see MGPPWrapper
+ */
+public class Queryer {
+  
+  /** outputs to std out a help message describing the commands used by 
+   * Queryer 
+   */
+  public void printHelp() {
+	
+	System.out.println( "commands available are:\n"+
+			    "\t.q\t\tquit\n"+
+			    "\t.h\t\tprint this help message\n"+
+			    "\t.d\t\tprint the current query parameter settings\n" +
+			    "\t.i<level>\tchange the search level to level\n"+
+			    "\t.l<level>\tchange the result level to level\n"+
+			    "\t.r0/.r1\t\tranking off/on\n"+
+			    "\t.t0/.t1\t\tquery type some/all\n"+
+			    "\t.c0/.c1\t\tcasefolding off/on\n"+
+			    "\t.s0/.s1\t\tstemming off/on\n"+
+			    "\t.o0/.o1\t\tshort output off/on\n"+
+			    "\t.m<num>\t\tset max docs to return to num\n\n"+
+			    "\t.p<docnum>\tprint document docnum\n"+
+			    "\t<query string>\t do a query\n");
+    }
+
+   
+    public static void main(String[] args) {
+	if (args.length != 3) {
+	    System.out.println("Usage: java org.greenstone.mgpp.Queryer <basedir> <indexdir> <textdir>");
+	    return;
+	}
+	
+	Queryer self = new Queryer();
+	
+	String base_dir = args[0];
+	String text_path = args[2];
+	String index_path = args[1];
+
+	text_path = base_dir + File.separatorChar+text_path;
+	index_path = base_dir  + File.separatorChar+ index_path;
+	
+	// the jni class to access mgpp stuff
+	MGPPWrapper wrapper = new MGPPWrapper();
+	wrapper.loadIndexData(index_path);
+	
+	// the return level
+	String level = "Section";
+
+	System.out.println("Welcome to Java Queryer :-)");
+	self.printHelp();
+
+	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+	boolean shortOutput=false;
+
+	String command; // user input
+	char x; // the command letter
+	String data=null; // any auxiliary input to a command
+	while (true) {
+	  System.out.print(">"); // the prompt
+            try {
+                command = br.readLine();
+                command=command.trim();
+		if (command.startsWith(".")) {
+		    // a system command
+		    x = command.charAt(1);
+		    if (command.length() > 2) {
+			data = command.substring(2);
+			data = data.trim();
+			
+		    }
+		    switch (x) {
+		    case 'q': // clean up and exit
+			wrapper.unloadIndexData();
+			return;  
+		    case 'h': // print help message
+			self.printHelp();
+			break;
+		    case 'd': // print query param settings
+			String info = wrapper.getQueryParams();
+			System.out.println(info);
+			break;
+		    case 'p': // print doc
+			int docnum = Integer.parseInt(data);
+			String doc = wrapper.getDocument(text_path, 
+							 level, docnum);
+			System.out.println(doc);
+			break;
+		    case 'm': //match docs
+			int match = Integer.parseInt(data);
+			wrapper.setMaxDocs(match);
+			break;
+		    case 's': // set stem on/off
+			int stem = Integer.parseInt(data);
+			if (stem==0 ){
+			    wrapper.setStem(false);
+			} else if(stem==1) {
+			    wrapper.setStem(true);
+			} else {
+			    System.err.println("Error: stem should be 0 or 1");
+			}
+			break;
+		    case 'c': // set case on/off
+			int casef = Integer.parseInt(data);
+			if (casef==0) {
+			    wrapper.setCase(false);
+			} else if (casef==1) {
+			    wrapper.setCase(true);
+			} else {
+			    System.err.println("Error: case should be 0 or 1");
+			}
+			break;
+		    case 'i': // set search level
+			wrapper.setQueryLevel(data);
+			break;
+		    case 'l': // set result level
+			wrapper.setReturnLevel(data);
+			level = data;
+			break; 
+		    case 'r': // set rank on/off
+			int rank = Integer.parseInt(data);
+			if (rank==0) {
+			    wrapper.setSortByRank(false);
+			} else if (rank==1) {
+			    wrapper.setSortByRank(true);
+			} else {
+			    System.err.println("Error: rank should be 0 or 1");
+			}
+			break;
+		    case 't': // set query type some/all
+			int type = Integer.parseInt(data);
+			if (type==0 || type==1) {
+			    wrapper.setMatchMode(type);
+			} else {
+			    System.err.println("Error: type should be 0 (some) or 1 (all)");
+			}
+			break;
+		    case 'o': // set output short/long
+			int output = Integer.parseInt(data);
+			if (output==0) {
+			    shortOutput = false;
+			} else if (output==1) {
+			    shortOutput = true;
+			}else {
+			    System.err.println("Error: output should be 0 or 1");
+			}
+			break;
+		    }
+		}
+		else {
+		    // a query
+		    wrapper.runQuery(command);
+		    MGPPQueryResult res = wrapper.getQueryResult();
+		    if (res.hasSyntaxError()) {
+		      System.out.println("invalid syntax error\n");
+		    } else {
+		      if (shortOutput) {
+			System.out.println(res.toShortString());
+		      } else {
+			System.out.println(res.toString());
+		      }
+		    }
+		}
+		    
+	    } catch (Exception e) {
+		System.out.println("Queryer error: "+e.getClass() + " "+e.getMessage());
+	    }
+
+	}
+    }
+
+
+}
Index: /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/winMake.bat
===================================================================
--- /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/winMake.bat	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/java/org/greenstone/mgpp/winMake.bat	(revision 14757)
@@ -0,0 +1,45 @@
+@echo off
+
+set MGPPHOME=..\..\..\..
+
+rem ---- Where to put class files ----
+set JAVACLASSDIR=classes
+
+rem ---- Name and location of java programs ----
+set JAVAC="%JAVA_HOME%\bin\javac"
+set JAVAH="%JAVA_HOME%\bin\javah"
+set JAVA="%JAVA_HOME%\bin\java"
+set JAVADOC="%JAVA_HOME%\bin\javadoc"
+set JAR="%JAVA_HOME%\bin\jar"
+
+set JAVACOPTIONS= -deprecation -g -O
+
+
+if ""%1"" == """" goto all
+if ""%1"" == ""all"" goto all
+if ""%1"" == ""install"" goto install
+if ""%1"" == ""clean"" goto clean
+
+:unknown
+	echo Error: Unrecognized argument %1.
+	goto done
+
+:all
+	if not exist %JAVACLASSDIR% mkdir %JAVACLASSDIR%
+	echo Compiling MGPP Java classes ...
+        %JAVAC% -d %JAVACLASSDIR% %JAVACOPTIONS% *.java
+        %JAVAH% -classpath %JAVACLASSDIR% -d %MGPPHOME%\jni org.greenstone.mgpp.MGPPWrapper
+        %JAR% cf %MGPPHOME%\mgpp.jar -C %JAVACLASSDIR% org
+	goto done
+
+:install
+	goto done
+
+:clean
+	echo Cleaning up...
+	if exist %JAVACLASSDIR% rmdir /S /Q %JAVACLASSDIR%
+        if exist %MGPPHOME%\mgpp.jar del %MGPPHOME%\mgpp.jar
+        if exist %MGPPHOME%\jni\org_greenstone_mgpp_MGPPWrapper.h del %MGPPHOME%\jni\org_greenstone_mgpp_MGPPWrapper.h
+	goto done
+
+:done
Index: /indexers/branches/3.03a/mgpp/jni/MGPPPassesWrapperImpl.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/jni/MGPPPassesWrapperImpl.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/jni/MGPPPassesWrapperImpl.cpp	(revision 14757)
@@ -0,0 +1,190 @@
+/*
+ *    MGPassesWrapperImpl.c
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <jni.h>
+#include <assert.h>
+#include "sysfuncs.h"
+#include "org_greenstone_mgpp_MGPPPassesWrapper.h"
+
+#include "mgpp_passes_4jni.h"
+#include "mg_files.h"
+
+/* if we need to use java objects, we should initialise their field ids here*/
+JNIEXPORT void JNICALL
+Java_org_greenstone_mgpp_MGPPPassesWrapper_initIDs(JNIEnv *j_env, jclass j_cls)
+{
+  return;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_greenstone_mgpp_MGPPPassesWrapper_initCSide(JNIEnv *j_env, jobject j_obj)
+{
+  clear_variables();
+  return true;  
+}  
+
+/* add a pass type T1, T2, I1, I2, S */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mgpp_MGPPPassesWrapper_addPass(JNIEnv *j_env, 
+					       jobject j_obj, 
+					       jchar j_pass_type,
+					       jchar j_pass_num)
+{
+  /* get the level as a c char */
+  const char pass_type = j_pass_type;
+  const char pass_num = j_pass_num;
+  add_pass(pass_type, pass_num);
+  
+}
+
+/* Set the filename */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mgpp_MGPPPassesWrapper_setFileName(JNIEnv *j_env, 
+						   jobject j_obj,
+						   jstring j_filename)
+{
+  /* Get the filename as a C string */
+  const char* filename = j_env->GetStringUTFChars(j_filename, NULL);
+ 
+  assert(filename != NULL);
+  set_filename(filename);
+  
+  /* Release the string */
+ j_env->ReleaseStringUTFChars(j_filename, filename);
+
+}
+
+/* Set the base path */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mgpp_MGPPPassesWrapper_setBasePath(JNIEnv *j_env, 
+						   jobject j_obj,
+						   jstring j_basepath)
+{
+  /* Get the base_path as a C string */
+  const char* basepath = j_env->GetStringUTFChars(j_basepath, NULL);
+  assert(basepath != NULL);
+ 
+  set_basepath(basepath);
+  
+  /* Release the string */
+  j_env->ReleaseStringUTFChars(j_basepath, basepath);
+
+}
+
+/* set the Document tag */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mgpp_MGPPPassesWrapper_setDocumentTag(JNIEnv *j_env, 
+						      jobject j_obj,
+						      jstring j_tag)
+{
+  const char* tag = j_env->GetStringUTFChars(j_tag, NULL);
+
+  set_document_tag(tag);
+  /* Release the string */
+  j_env->ReleaseStringUTFChars(j_tag, tag);
+
+
+}
+
+/* add a level tag */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mgpp_MGPPPassesWrapper_addLevelTag(JNIEnv *j_env, 
+						   jobject j_obj,
+						   jstring j_tag)
+{
+  const char* tag = j_env->GetStringUTFChars(j_tag, NULL);
+  add_level_tag(tag);
+
+  /* Release the string */
+  j_env->ReleaseStringUTFChars(j_tag, tag);
+
+}
+
+/* set the index level (default word level) */
+JNIEXPORT void JNICALL
+Java_org_greenstone_mgpp_MGPPPassesWrapper_setIndexLevel(JNIEnv *j_env, 
+						     jobject j_obj,
+						     jstring j_tag)
+{
+  const char* tag = j_env->GetStringUTFChars(j_tag, NULL);
+  set_index_level(tag);
+
+  /* Release the string */
+  j_env->ReleaseStringUTFChars(j_tag, tag);
+
+  
+}
+
+
+/** Maximum amount of memory to use for  the index  pass-2  file
+    inversion  in  megabytes.
+*/
+JNIEXPORT void JNICALL
+Java_org_greenstone_mgpp_MGPPPassesWrapper_setInversionMemLimit(JNIEnv *j_env, 
+							    jobject j_obj, 
+							    jint j_limit) {
+  int limit = j_limit;
+  set_inversion_limit(limit);
+}
+
+
+/* initialise the pass through the documents. must be called after all
+   the set methods 
+*/
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mgpp_MGPPPassesWrapper_init(JNIEnv *j_env, 
+					    jobject j_obj) {
+
+  init_driver();
+  return true;
+}
+
+
+/* process one or more documents */
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mgpp_MGPPPassesWrapper_processMGPPDocument(JNIEnv *j_env, 
+						       jobject j_obj,
+						       jbyteArray j_doc_text) {
+  /* Get the text as a C string */
+  int length = j_env->GetArrayLength(j_doc_text);
+  u_char * text_buffer = (u_char *)j_env->GetByteArrayElements(j_doc_text, NULL);
+  process_document(text_buffer, length);
+  /* Release the string */
+  // why doesn't this work in c++ when it works in C?????
+  //j_env->ReleaseByteArrayElements(j_doc_text, text_buffer, 0);
+  return true;
+}
+
+/* finalise the pass through the documents */
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mgpp_MGPPPassesWrapper_finish(JNIEnv *j_env, 
+					    jobject j_obj) {
+  
+  finalise_driver();
+  return true;
+}
+
+/** get the exit value once finished */
+JNIEXPORT jint JNICALL 
+Java_org_greenstone_mgpp_MGPPPassesWrapper_exitValue(JNIEnv *j_env, 
+					    jobject j_obj) {
+
+  return get_exit_value();
+}
Index: /indexers/branches/3.03a/mgpp/jni/MGPPRetrieveWrapperImpl.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/jni/MGPPRetrieveWrapperImpl.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/jni/MGPPRetrieveWrapperImpl.cpp	(revision 14757)
@@ -0,0 +1,278 @@
+/*
+ *    MGPPRetrieveWrapperImpl.c
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */ 
+#ifdef __WIN32__
+#include <WIN32cfg.h>
+#include <strstream>
+#include <sstream>
+#else
+#ifdef __APPLE__
+#include <strstream>
+#include <sstream>
+#else
+#include <sstream>
+#endif
+#endif
+
+#include <jni.h>
+#include "org_greenstone_mgpp_MGPPRetrieveWrapper.h"
+#include "MGPPWrapperImpl.h"
+#include "TextGet.h"
+#include "GSDLQueryParser.h"
+#include "MGQuery.h"
+  
+MGPPWrapperData::MGPPWrapperData() {
+  indexData = new IndexData();
+  queryInfo = new QueryInfo();
+
+  if (queryInfo==NULL) {
+    cerr<<"couldn't allocate new query info\n";
+    if (indexData!=NULL) {
+      delete indexData;
+    }
+  }
+
+  // set all the default params
+  //SetCStr(queryInfo->docLevel, "Document"); // the level to search at
+  queryInfo->maxDocs = 50;
+  queryInfo->sortByRank = true;
+  queryInfo->exactWeights = false;
+  queryInfo->needRankInfo = true;
+  queryInfo->needTermFreqs = true;
+
+  UCArrayClear(level);
+  SetCStr(level, "Document"); // the level to return docs at
+  defaultStemMethod=0;
+  defaultBoolCombine=0;
+  maxNumeric = 4;
+}
+
+MGPPWrapperData::~MGPPWrapperData() { 
+  if (indexData !=NULL) {
+    delete indexData;
+  }
+  if (queryInfo !=NULL) {
+    delete queryInfo;
+  }
+}
+
+// ********************************************
+// initialisation stuff
+// ********************************************
+
+// cached ids for java stuff 
+jfieldID FID_mgpp_data = NULL; // MGPPWrapperData
+jfieldID FID_query_result = NULL; // MGPPQueryResult
+jmethodID MID_addDoc=NULL; // MGPPQueryResult.addDoc()
+jmethodID MID_addTerm=NULL; // MGPPQueryResult.addTerm()
+jmethodID MID_setTotalDocs=NULL; // MGPPQueryResult.setTotalDocs()
+jmethodID MID_clearResult=NULL; //MGPPQueryResult.clear()
+jmethodID MID_setSyntaxError=NULL; // MGPPQueryResult.setSyntaxError()
+jclass CID_String=NULL; // class ID of String
+
+/* to access objects and methods on java side, need their field/method ids - 
+ this initialises them at the start to avoid recalculating them each time they
+ are needed 
+Note: the descriptors need to be exactly right, otherwise you get an error 
+saying "no such field" but no reference to the fact that it has the right 
+name but the wrong type.
+Note: apparently the jclass is a local ref and should only work 
+in the method that created it. It seems to work ok, but I'll make it
+ global cos the book said I should, and it may avoid future hassles.
+*/
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPRetrieveWrapper_initIDs (JNIEnv *j_env, jclass j_cls) {
+  
+  FID_mgpp_data = j_env->GetFieldID(j_cls, "mgpp_data_ptr_", "J"); //a long-"J"
+  if (FID_mgpp_data==NULL) {
+      cerr <<"MGPP JNI: field mgpp_data_ptr_ not found"<<endl;
+  } 
+
+  FID_query_result = j_env->GetFieldID(j_cls, "mgpp_query_result_", "Lorg/greenstone/mgpp/MGPPQueryResult;"); // an object -"L<class name>;"
+  if (FID_query_result==NULL) {
+      cerr <<"MGPP JNI: field mgpp_query_result_ not found"<<endl;
+  }
+  // the methods we want to use
+
+  // addDoc(long doc, float rank)
+  jclass JC_MGPPQueryResult = j_env->FindClass("org/greenstone/mgpp/MGPPQueryResult");
+  MID_addDoc = j_env->GetMethodID(JC_MGPPQueryResult, "addDoc", "(JF)V");
+  if (MID_addDoc==NULL) {
+      cerr <<"MGPP JNI: addDoc method not found"<<endl;
+  }
+  // addTerm(String term, String tag, int stem_method, long match_docs, 
+  // long term_freq, String[] equiv_terms)
+  MID_addTerm = j_env->GetMethodID(JC_MGPPQueryResult, "addTerm", "(Ljava/lang/String;Ljava/lang/String;IJJ[Ljava/lang/String;)V");
+  if (MID_addTerm==NULL) {
+      cerr <<"MGPP JNI: method addTerm not found"<<endl;
+  }
+  
+  // setTotalDocs(long)
+  MID_setTotalDocs = j_env->GetMethodID(JC_MGPPQueryResult, "setTotalDocs", "(J)V");
+  if (MID_setTotalDocs==NULL) {
+      cerr <<"MGPP JNI: method setTotalDocs not found"<<endl;
+  }
+  
+  MID_clearResult = j_env->GetMethodID(JC_MGPPQueryResult, "clear", "()V");
+  if (MID_clearResult==NULL) {
+      cerr <<"MGPP JNI: method clear not found"<<endl;
+  }
+  MID_setSyntaxError = j_env->GetMethodID(JC_MGPPQueryResult, "setSyntaxError", "(Z)V");
+  if (MID_clearResult==NULL) {
+      cerr <<"MGPP JNI: method setSyntaxError not found"<<endl;
+  }
+
+  // get the class for String to use in NewObjectArray in runQuery()
+  // FindClass returns a local reference - have to convert it to a global one
+  jclass local_CID_String = j_env->FindClass("java/lang/String");
+  if (local_CID_String==NULL) {
+    cerr <<"MGPP JNI: java String class not found"<<endl;
+  } else { 
+    /* create a global ref */
+    CID_String = (jclass)j_env->NewGlobalRef(local_CID_String);
+    /* The local reference is no longer useful */
+    j_env->DeleteLocalRef(local_CID_String);
+ 
+    /* Is the global reference created successfully? */
+    if (CID_String == NULL) {
+      return; /* out of memory exception thrown */
+    }
+  }
+  
+}
+
+/* the java side MGPPWrapper has a pointer to a C++ object - MGPPWrapperData
+   initialise this and set the pointer 
+*/
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mgpp_MGPPRetrieveWrapper_initCppSide (JNIEnv *j_env, jobject j_obj){
+
+  MGPPWrapperData * data = new MGPPWrapperData();
+  j_env->SetIntField(j_obj, FID_mgpp_data, (long)data);
+
+  return true;
+
+}
+
+//****************************************************
+// retrieve a document
+//****************************************************
+
+/* returns a document from mgpp as a string
+Note: TextData isn't cached - just reloaded each time
+*/
+JNIEXPORT jstring JNICALL 
+Java_org_greenstone_mgpp_MGPPRetrieveWrapper_getDocument (JNIEnv *j_env, 
+ jobject j_obj, jstring j_text_name, jstring j_level, jlong j_docnum) {
+  
+#ifdef __WIN32__
+  const char* base_dir = "";
+#else
+  const char* base_dir = "/";
+#endif
+
+  const char * text_name = j_env->GetStringUTFChars(j_text_name, NULL);
+  if (text_name==NULL) {
+   return NULL;
+  }
+
+  const char * level = j_env->GetStringUTFChars( j_level, NULL);
+  if (level==NULL) {
+   j_env->ReleaseStringUTFChars(j_text_name, text_name);
+   return NULL;
+  }
+    
+  // does this work alright? j_docnum is a long (64 bit)
+  unsigned long docnum = j_docnum;
+  TextData td;
+
+  // cast to char* otherwise complains about const
+  td.LoadData((char *)base_dir, (char *)text_name);
+
+  UCArray mg_level;
+  SetCStr(mg_level, level);
+  UCArray docText;
+  docText.clear();
+  // get the actual text
+  if (!GetDocText(td, mg_level, docnum, docText)) {
+    cerr <<"MGPP JNI: couldn't retrieve doc text"<<endl;
+  }
+
+  td.UnloadData();
+  
+  char * doc = GetCStr(docText); // do I need to free this char *??
+  jstring result = j_env->NewStringUTF(doc);
+  // release any gets
+  j_env->ReleaseStringUTFChars(j_text_name, text_name);
+  j_env->ReleaseStringUTFChars(j_level, level);
+
+  // free any C++ stuff
+  delete doc;
+
+  return result;
+ 
+}
+
+//******************************************
+// do a query
+// ****************************************
+
+/* load the IndexData - cached for querying
+ */
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mgpp_MGPPRetrieveWrapper_loadIndexData (JNIEnv *j_env, jobject j_obj,  jstring j_index_name) {
+
+  jint data_ptr = j_env->GetIntField(j_obj, FID_mgpp_data);
+  MGPPWrapperData * data = (MGPPWrapperData *)data_ptr;
+
+#ifdef __WIN32__
+  const char* base_dir = "";
+#else
+  const char* base_dir = "/";
+#endif
+
+  const char * index_name = j_env->GetStringUTFChars( j_index_name, NULL);
+  if (index_name==NULL) {
+    return false;
+  }
+  
+  jboolean j_result=false;
+  
+  // why doesn't this complain about const??
+  if (data->indexData->LoadData(base_dir, index_name)) {
+    j_result=true;
+  }
+  
+  // release any gets
+  j_env->ReleaseStringUTFChars(j_index_name, index_name);
+  
+  return j_result;
+}
+
+/* unload the data 
+ */
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mgpp_MGPPRetrieveWrapper_unloadIndexData (JNIEnv *j_env, jobject j_obj) {
+
+  jint data_ptr = j_env->GetIntField(j_obj, FID_mgpp_data);
+  MGPPWrapperData * data = (MGPPWrapperData *)data_ptr;
+
+  data->indexData->UnloadData();
+  return true;
+
+}
Index: /indexers/branches/3.03a/mgpp/jni/MGPPSearchWrapperImpl.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/jni/MGPPSearchWrapperImpl.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/jni/MGPPSearchWrapperImpl.cpp	(revision 14757)
@@ -0,0 +1,483 @@
+/*
+ *    MGPPSearchWrapperImpl.c
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    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 of the License, 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 program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */ 
+#ifdef __WIN32__
+#include <WIN32cfg.h>
+#include <strstream>
+#include <sstream>
+#else
+#ifdef __APPLE__
+#include <strstream>
+#include <sstream>
+#else
+#include <sstream>
+#endif
+#endif
+
+#include <jni.h>
+#include "org_greenstone_mgpp_MGPPSearchWrapper.h"
+#include "MGPPWrapperImpl.h"
+#include "TextGet.h"
+#include "GSDLQueryParser.h"
+#include "MGQuery.h"
+  
+MGPPWrapperData::MGPPWrapperData() {
+  indexData = new IndexData();
+  queryInfo = new QueryInfo();
+
+  if (queryInfo==NULL) {
+    cerr<<"couldn't allocate new query info\n";
+    if (indexData!=NULL) {
+      delete indexData;
+    }
+  }
+
+  // set all the default params
+  SetCStr(queryInfo->docLevel, "Document"); // the level to search at
+  queryInfo->maxDocs = 50;
+  queryInfo->sortByRank = true;
+  queryInfo->exactWeights = false;
+  queryInfo->needRankInfo = true;
+  queryInfo->needTermFreqs = true;
+
+  UCArrayClear(level);
+  SetCStr(level, "Document"); // the level to return docs at
+  defaultStemMethod=0;
+  defaultBoolCombine=0;
+  maxNumeric = 4;
+}
+
+MGPPWrapperData::~MGPPWrapperData() { 
+  if (indexData !=NULL) {
+    delete indexData;
+  }
+  if (queryInfo !=NULL) {
+    delete queryInfo;
+  }
+}
+
+// ********************************************
+// initialisation stuff
+// ********************************************
+
+// cached ids for java stuff 
+jfieldID FID_mgpp_data = NULL; // MGPPWrapperData
+jfieldID FID_query_result = NULL; // MGPPQueryResult
+jmethodID MID_addDoc=NULL; // MGPPQueryResult.addDoc()
+jmethodID MID_addTerm=NULL; // MGPPQueryResult.addTerm()
+jmethodID MID_setTotalDocs=NULL; // MGPPQueryResult.setTotalDocs()
+jmethodID MID_clearResult=NULL; //MGPPQueryResult.clear()
+jmethodID MID_setSyntaxError=NULL; // MGPPQueryResult.setSyntaxError()
+jclass CID_String=NULL; // class ID of String
+
+/* to access objects and methods on java side, need their field/method ids - 
+ this initialises them at the start to avoid recalculating them each time they
+ are needed 
+Note: the descriptors need to be exactly right, otherwise you get an error 
+saying "no such field" but no reference to the fact that it has the right 
+name but the wrong type.
+Note: apparently the jclass is a local ref and should only work 
+in the method that created it. It seems to work ok, but I'll make it
+ global cos the book said I should, and it may avoid future hassles.
+*/
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_initIDs (JNIEnv *j_env, jclass j_cls) {
+  
+  FID_mgpp_data = j_env->GetFieldID(j_cls, "mgpp_data_ptr_", "J"); //a long-"J"
+  if (FID_mgpp_data==NULL) {
+      cerr <<"MGPP JNI: field mgpp_data_ptr_ not found"<<endl;
+  } 
+
+  FID_query_result = j_env->GetFieldID(j_cls, "mgpp_query_result_", "Lorg/greenstone/mgpp/MGPPQueryResult;"); // an object -"L<class name>;"
+  if (FID_query_result==NULL) {
+      cerr <<"MGPP JNI: field mgpp_query_result_ not found"<<endl;
+  }
+  // the methods we want to use
+
+  // addDoc(long doc, float rank)
+  jclass JC_MGPPQueryResult = j_env->FindClass("org/greenstone/mgpp/MGPPQueryResult");
+  MID_addDoc = j_env->GetMethodID(JC_MGPPQueryResult, "addDoc", "(JF)V");
+  if (MID_addDoc==NULL) {
+      cerr <<"MGPP JNI: addDoc method not found"<<endl;
+  }
+  // addTerm(String term, String tag, int stem_method, long match_docs, 
+  // long term_freq, String[] equiv_terms)
+  MID_addTerm = j_env->GetMethodID(JC_MGPPQueryResult, "addTerm", "(Ljava/lang/String;Ljava/lang/String;IJJ[Ljava/lang/String;)V");
+  if (MID_addTerm==NULL) {
+      cerr <<"MGPP JNI: method addTerm not found"<<endl;
+  }
+  
+  // setTotalDocs(long)
+  MID_setTotalDocs = j_env->GetMethodID(JC_MGPPQueryResult, "setTotalDocs", "(J)V");
+  if (MID_setTotalDocs==NULL) {
+      cerr <<"MGPP JNI: method setTotalDocs not found"<<endl;
+  }
+  
+  MID_clearResult = j_env->GetMethodID(JC_MGPPQueryResult, "clear", "()V");
+  if (MID_clearResult==NULL) {
+      cerr <<"MGPP JNI: method clear not found"<<endl;
+  }
+  MID_setSyntaxError = j_env->GetMethodID(JC_MGPPQueryResult, "setSyntaxError", "(Z)V");
+  if (MID_clearResult==NULL) {
+      cerr <<"MGPP JNI: method setSyntaxError not found"<<endl;
+  }
+
+  // get the class for String to use in NewObjectArray in runQuery()
+  // FindClass returns a local reference - have to convert it to a global one
+  jclass local_CID_String = j_env->FindClass("java/lang/String");
+  if (local_CID_String==NULL) {
+    cerr <<"MGPP JNI: java String class not found"<<endl;
+  } else { 
+    /* create a global ref */
+    CID_String = (jclass)j_env->NewGlobalRef(local_CID_String);
+    /* The local reference is no longer useful */
+    j_env->DeleteLocalRef(local_CID_String);
+ 
+    /* Is the global reference created successfully? */
+    if (CID_String == NULL) {
+      return; /* out of memory exception thrown */
+    }
+  }
+  
+}
+
+/* the java side MGPPWrapper has a pointer to a C++ object - MGPPWrapperData
+   initialise this and set the pointer 
+*/
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_initCppSide (JNIEnv *j_env, jobject j_obj){
+
+  MGPPWrapperData * data = new MGPPWrapperData();
+  j_env->SetIntField(j_obj, FID_mgpp_data, (long)data);
+
+  return true;
+
+}
+
+//******************************************
+// do a query
+// ****************************************
+
+/* load the IndexData - cached for querying
+ */
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_loadIndexData (JNIEnv *j_env, jobject j_obj,  jstring j_index_name) {
+
+  jint data_ptr = j_env->GetIntField(j_obj, FID_mgpp_data);
+  MGPPWrapperData * data = (MGPPWrapperData *)data_ptr;
+
+#ifdef __WIN32__
+  const char* base_dir = "";
+#else
+  const char* base_dir = "/";
+#endif
+
+  const char * index_name = j_env->GetStringUTFChars( j_index_name, NULL);
+  if (index_name==NULL) {
+    return false;
+  }
+  
+  jboolean j_result=false;
+  
+  // why doesn't this complain about const??
+  if (data->indexData->LoadData(base_dir, index_name)) {
+    j_result=true;
+  }
+  
+  // release any gets
+  j_env->ReleaseStringUTFChars(j_index_name, index_name);
+  
+  return j_result;
+}
+
+/* unload the data 
+ */
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_unloadIndexData (JNIEnv *j_env, jobject j_obj) {
+
+  jint data_ptr = j_env->GetIntField(j_obj, FID_mgpp_data);
+  MGPPWrapperData * data = (MGPPWrapperData *)data_ptr;
+
+  data->indexData->UnloadData();
+  return true;
+
+}
+
+/* do the actual query - the results are written to query_result held on the 
+   java side */
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_runQuery (JNIEnv *j_env, jobject j_obj, jstring j_query){
+  
+  jthrowable exc; // an exception - check if something funny has happened
+  const char *query = j_env->GetStringUTFChars(j_query, NULL);
+  if (query==NULL) {
+    return; // exception already thrown
+  }
+  // turn to UCArray for mgpp and then release the string
+  UCArray queryArray;
+  SetCStr(queryArray, query);
+  j_env->ReleaseStringUTFChars(j_query, query);
+  
+  // the query data
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  
+  // the result to write to
+  jobject result_ptr = j_env->GetObjectField(j_obj, FID_query_result);
+  if (result_ptr==NULL) {
+    cerr <<"couldn't access the result to write to"<<endl;
+    return;
+  }
+  
+  // clear the result
+  j_env->CallVoidMethod(result_ptr, MID_clearResult);
+  exc = j_env->ExceptionOccurred(); // this catches teh exception I think - it
+  //wont be thrown any further
+  if (exc) {
+    j_env->ExceptionDescribe();
+    return;
+  }
+  // the mgpp QueryResult that we will use
+  ExtQueryResult queryResult;
+
+  QueryNode * queryTree = NULL;
+  // parse the query string into a tree structure
+  queryTree = ParseQuery(queryArray, data->defaultBoolCombine, 
+			 data->defaultStemMethod, data->maxNumeric);
+  if (queryTree == NULL) {
+    // invalid syntax
+    j_env->CallVoidMethod(result_ptr, MID_setSyntaxError, true);
+    cerr << "MGPPWrapperImpl: invalid query syntax!!\n";
+    return; 
+  }
+  // print the query
+  PrintNode (cout, queryTree);
+  // finally, do the query
+  MGQuery(*(data->indexData), *(data->queryInfo), queryTree, queryResult, data->level);
+
+  delete queryTree;
+
+  // convert queryResult to the java side version
+  // use levels rather than docs of ExtQueryResult
+  // CallVoidMethod(obj, method id, args to method)
+  for (int i=0; i<queryResult.levels.size(); i++) {
+    jlong doc = queryResult.levels[i];
+    jfloat rank = queryResult.ranks[i];
+    j_env->CallVoidMethod(result_ptr, MID_addDoc, doc, rank);
+    exc = j_env->ExceptionOccurred();
+    if (exc) {
+      j_env->ExceptionDescribe();
+      return;
+    }
+    
+  }
+
+  // actual num of docs
+  jlong total = queryResult.actualNumDocs;
+  j_env->CallVoidMethod(result_ptr, MID_setTotalDocs, total);
+  exc = j_env->ExceptionOccurred();
+  if (exc) {
+    j_env->ExceptionDescribe();
+    return;
+  }
+
+  // the terms
+  for (int j=0; j<queryResult.termFreqs.size(); j++) {
+    
+    TermFreqData tf = queryResult.termFreqs[j];
+    jstring term = j_env->NewStringUTF(GetCStr(tf.term));
+    jstring tag = j_env->NewStringUTF(GetCStr(tf.tag));
+    jint stem = tf.stemMethod;
+    jlong match = tf.matchDocs;
+    jlong freq = tf.termFreq;
+    
+    jobjectArray equivs=NULL;
+    jstring empty = j_env->NewStringUTF(""); // the initial object to fill the array
+    jint num_equivs = tf.equivTerms.size();
+    equivs = j_env->NewObjectArray(num_equivs, CID_String, empty);
+    if (equivs==NULL) {
+      cerr<<"couldn't create object array"<<endl;
+      
+    } else {
+      for (int k=0; k<num_equivs;k++) {
+	jstring equiv = j_env->NewStringUTF(GetCStr(tf.equivTerms[k]));
+	j_env->SetObjectArrayElement(equivs, k, equiv);
+      }
+      
+      
+      j_env->CallVoidMethod(result_ptr, MID_addTerm, term, tag, stem, match, freq, equivs);
+      exc = j_env->ExceptionOccurred();
+      if (exc) {
+	j_env->ExceptionDescribe();
+	return;
+      }
+    }
+  }
+
+
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_setStem (JNIEnv *j_env, 
+					      jobject j_obj, 
+					      jboolean j_on) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  if (j_on) {
+    data->defaultStemMethod |= 2;
+  } else {
+    data->defaultStemMethod &= 0xd;
+  }
+
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_setAccentFold (JNIEnv *j_env, 
+					      jobject j_obj, 
+					      jboolean j_on) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  if (j_on) {
+    data->defaultStemMethod |= 4;
+  } else {
+    data->defaultStemMethod &= 0xb;
+  }
+}
+
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_setCase (JNIEnv *j_env, 
+					      jobject j_obj, 
+					      jboolean j_on) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+
+  if (j_on) {
+    data->defaultStemMethod |= 1;
+  } else {
+    data->defaultStemMethod &= 0xe;
+  }
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_setMaxDocs (JNIEnv *j_env, 
+						 jobject j_obj, 
+						 jint j_max) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  data->queryInfo->maxDocs=j_max;
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_setMaxNumeric (JNIEnv *j_env, 
+						 jobject j_obj, 
+						 jint j_max) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  data->maxNumeric=j_max;
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_setSortByRank (JNIEnv *j_env, 
+						    jobject j_obj, 
+						    jboolean j_on) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  
+  data->queryInfo->sortByRank=j_on;
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_setReturnTerms(JNIEnv *j_env, 
+						    jobject j_obj, 
+						    jboolean j_on) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  data->queryInfo->needTermFreqs = j_on;
+ 
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_setQueryLevel(JNIEnv *j_env, 
+						   jobject j_obj, 
+						   jstring j_level){
+  
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+
+  const char * level = j_env->GetStringUTFChars(j_level, NULL);
+  if (level==NULL) {
+    return; // exception already thrown
+  }
+  
+  data->queryInfo->docLevel.clear();
+  SetCStr(data->queryInfo->docLevel, level);
+  
+  // release the java stuff
+  j_env->ReleaseStringUTFChars(j_level, level);
+ 
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_setReturnLevel(JNIEnv *j_env, 
+						    jobject j_obj, 
+						    jstring j_level){
+
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+
+  const char * level = j_env->GetStringUTFChars(j_level, NULL);
+  if (level==NULL) {
+    return; // exception already thrown
+  }
+  
+  data->level.clear();
+  SetCStr(data->level, level);
+  
+  // release the java stuff
+  j_env->ReleaseStringUTFChars(j_level, level);
+    
+
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_setMatchMode (JNIEnv *j_env,
+						   jobject j_obj,
+						   jint j_mode){
+
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  data->defaultBoolCombine=j_mode;
+
+}
+
+JNIEXPORT jstring JNICALL 
+Java_org_greenstone_mgpp_MGPPSearchWrapper_getQueryParams (JNIEnv *j_env,
+						     jobject j_obj){
+
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  
+  // print the data to a stringstream, then convert to char*, then to 
+  //jstring
+
+  stringstream output;
+  output << "Query params:"<<endl
+    // need to change this to use platform specific separator for niceness
+	 << "index\t\t"<<data->indexData->basePath<<"/"<<data->indexData->filename<<endl
+	 <<"search level\t"<<GetCStr(data->queryInfo->docLevel)<<endl
+	 <<"result level\t"<<GetCStr(data->level)<<endl
+	 <<"casefold\t"<<(data->defaultStemMethod&1)<<endl
+	 <<"stem\t\t"<<(data->defaultStemMethod&2)<<endl
+	 <<"order by rank\t"<<data->queryInfo->sortByRank<<endl
+	 <<"query type\t"<<(data->defaultBoolCombine==1?"all":"some")<<endl
+         <<"max docs\t"<<data->queryInfo->maxDocs<<endl<<ends;
+
+  const char *result = output.str().c_str();
+  jstring j_result = j_env->NewStringUTF(result);
+  delete (char *)result;
+  return j_result;
+}
Index: /indexers/branches/3.03a/mgpp/jni/MGPPWrapperImpl.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/jni/MGPPWrapperImpl.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/jni/MGPPWrapperImpl.cpp	(revision 14757)
@@ -0,0 +1,524 @@
+#ifdef __WIN32__
+#include <WIN32cfg.h>
+#include <strstream>
+#include <sstream>
+#else
+#ifdef __APPLE__
+#include <strstream>
+#include <sstream>
+#else
+#include <sstream>
+#endif
+#endif
+
+#include <jni.h>
+#include "org_greenstone_mgpp_MGPPWrapper.h"
+#include "MGPPWrapperImpl.h"
+#include "TextGet.h"
+#include "GSDLQueryParser.h"
+#include "MGQuery.h"
+  
+MGPPWrapperData::MGPPWrapperData() {
+  indexData = new IndexData();
+  queryInfo = new QueryInfo();
+
+  if (queryInfo==NULL) {
+    cerr<<"couldn't allocate new query info\n";
+    if (indexData!=NULL) {
+      delete indexData;
+    }
+  }
+
+  // set all the default params
+  SetCStr(queryInfo->docLevel, "Document"); // the level to search at
+  queryInfo->maxDocs = 50;
+  queryInfo->sortByRank = true;
+  queryInfo->exactWeights = false;
+  queryInfo->needRankInfo = true;
+  queryInfo->needTermFreqs = true;
+
+  UCArrayClear(level);
+  SetCStr(level, "Document"); // the level to return docs at
+  defaultStemMethod=0;
+  defaultBoolCombine=0;
+  maxNumeric = 4;
+}
+
+MGPPWrapperData::~MGPPWrapperData() { 
+  if (indexData !=NULL) {
+    delete indexData;
+  }
+  if (queryInfo !=NULL) {
+    delete queryInfo;
+  }
+}
+
+// ********************************************
+// initialisation stuff
+// ********************************************
+
+// cached ids for java stuff 
+jfieldID FID_mgpp_data = NULL; // MGPPWrapperData
+jfieldID FID_query_result = NULL; // MGPPQueryResult
+jmethodID MID_addDoc=NULL; // MGPPQueryResult.addDoc()
+jmethodID MID_addTerm=NULL; // MGPPQueryResult.addTerm()
+jmethodID MID_setTotalDocs=NULL; // MGPPQueryResult.setTotalDocs()
+jmethodID MID_clearResult=NULL; //MGPPQueryResult.clear()
+jmethodID MID_setSyntaxError=NULL; // MGPPQueryResult.setSyntaxError()
+jclass CID_String=NULL; // class ID of String
+
+/* to access objects and methods on java side, need their field/method ids - 
+ this initialises them at the start to avoid recalculating them each time they
+ are needed 
+Note: the descriptors need to be exactly right, otherwise you get an error 
+saying "no such field" but no reference to the fact that it has the right 
+name but the wrong type.
+Note: apparently the jclass is a local ref and should only work 
+in the method that created it. It seems to work ok, but I'll make it
+ global cos the book said I should, and it may avoid future hassles.
+*/
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_initIDs (JNIEnv *j_env, jclass j_cls) {
+  
+  FID_mgpp_data = j_env->GetFieldID(j_cls, "mgpp_data_ptr_", "J"); //a long-"J"
+  if (FID_mgpp_data==NULL) {
+      cerr <<"MGPP JNI: field mgpp_data_ptr_ not found"<<endl;
+  } 
+
+  FID_query_result = j_env->GetFieldID(j_cls, "mgpp_query_result_", "Lorg/greenstone/mgpp/MGPPQueryResult;"); // an object -"L<class name>;"
+  if (FID_query_result==NULL) {
+      cerr <<"MGPP JNI: field mgpp_query_result_ not found"<<endl;
+  }
+  // the methods we want to use
+
+  // addDoc(long doc, float rank)
+  jclass JC_MGPPQueryResult = j_env->FindClass("org/greenstone/mgpp/MGPPQueryResult");
+  MID_addDoc = j_env->GetMethodID(JC_MGPPQueryResult, "addDoc", "(JF)V");
+  if (MID_addDoc==NULL) {
+      cerr <<"MGPP JNI: addDoc method not found"<<endl;
+  }
+  // addTerm(String term, String tag, int stem_method, long match_docs, 
+  // long term_freq, String[] equiv_terms)
+  MID_addTerm = j_env->GetMethodID(JC_MGPPQueryResult, "addTerm", "(Ljava/lang/String;Ljava/lang/String;IJJ[Ljava/lang/String;)V");
+  if (MID_addTerm==NULL) {
+      cerr <<"MGPP JNI: method addTerm not found"<<endl;
+  }
+  
+  // setTotalDocs(long)
+  MID_setTotalDocs = j_env->GetMethodID(JC_MGPPQueryResult, "setTotalDocs", "(J)V");
+  if (MID_setTotalDocs==NULL) {
+      cerr <<"MGPP JNI: method setTotalDocs not found"<<endl;
+  }
+  
+  MID_clearResult = j_env->GetMethodID(JC_MGPPQueryResult, "clear", "()V");
+  if (MID_clearResult==NULL) {
+      cerr <<"MGPP JNI: method clear not found"<<endl;
+  }
+  MID_setSyntaxError = j_env->GetMethodID(JC_MGPPQueryResult, "setSyntaxError", "(Z)V");
+  if (MID_clearResult==NULL) {
+      cerr <<"MGPP JNI: method setSyntaxError not found"<<endl;
+  }
+
+  // get the class for String to use in NewObjectArray in runQuery()
+  // FindClass returns a local reference - have to convert it to a global one
+  jclass local_CID_String = j_env->FindClass("java/lang/String");
+  if (local_CID_String==NULL) {
+    cerr <<"MGPP JNI: java String class not found"<<endl;
+  } else { 
+    /* create a global ref */
+    CID_String = (jclass)j_env->NewGlobalRef(local_CID_String);
+    /* The local reference is no longer useful */
+    j_env->DeleteLocalRef(local_CID_String);
+ 
+    /* Is the global reference created successfully? */
+    if (CID_String == NULL) {
+      return; /* out of memory exception thrown */
+    }
+  }
+  
+}
+
+/* the java side MGPPWrapper has a pointer to a C++ object - MGPPWrapperData
+   initialise this and set the pointer 
+*/
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_initCppSide (JNIEnv *j_env, jobject j_obj){
+
+  MGPPWrapperData * data = new MGPPWrapperData();
+  j_env->SetIntField(j_obj, FID_mgpp_data, (long)data);
+
+  return true;
+
+}
+
+//****************************************************
+// retrieve a document
+//****************************************************
+
+/* returns a document from mgpp as a string
+Note: TextData isn't cached - just reloaded each time
+*/
+JNIEXPORT jstring JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_getDocument (JNIEnv *j_env, 
+ jobject j_obj, jstring j_text_name, jstring j_level, jlong j_docnum) {
+  
+#ifdef __WIN32__
+  const char* base_dir = "";
+#else
+  const char* base_dir = "/";
+#endif
+
+  const char * text_name = j_env->GetStringUTFChars(j_text_name, NULL);
+  if (text_name==NULL) {
+   return NULL;
+  }
+
+  const char * level = j_env->GetStringUTFChars( j_level, NULL);
+  if (level==NULL) {
+   j_env->ReleaseStringUTFChars(j_text_name, text_name);
+   return NULL;
+  }
+    
+  // does this work alright? j_docnum is a long (64 bit)
+  unsigned long docnum = j_docnum;
+  TextData td;
+
+  // cast to char* otherwise complains about const
+  td.LoadData((char *)base_dir, (char *)text_name);
+
+  UCArray mg_level;
+  SetCStr(mg_level, level);
+  UCArray docText;
+  docText.clear();
+  // get the actual text
+  if (!GetDocText(td, mg_level, docnum, docText)) {
+    cerr <<"MGPP JNI: couldn't retrieve doc text"<<endl;
+  }
+
+  td.UnloadData();
+  
+  char * doc = GetCStr(docText); // do I need to free this char *??
+  jstring result = j_env->NewStringUTF(doc);
+  // release any gets
+  j_env->ReleaseStringUTFChars(j_text_name, text_name);
+  j_env->ReleaseStringUTFChars(j_level, level);
+
+  // free any C++ stuff
+  delete doc;
+
+  return result;
+ 
+}
+
+//******************************************
+// do a query
+// ****************************************
+
+/* load the IndexData - cached for querying
+ */
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_loadIndexData (JNIEnv *j_env, jobject j_obj,  jstring j_index_name) {
+
+  jint data_ptr = j_env->GetIntField(j_obj, FID_mgpp_data);
+  MGPPWrapperData * data = (MGPPWrapperData *)data_ptr;
+
+#ifdef __WIN32__
+  const char* base_dir = "";
+#else
+  const char* base_dir = "/";
+#endif
+
+  const char * index_name = j_env->GetStringUTFChars( j_index_name, NULL);
+  if (index_name==NULL) {
+    return false;
+  }
+  
+  jboolean j_result=false;
+  
+  // why doesn't this complain about const??
+  if (data->indexData->LoadData(base_dir, index_name)) {
+    j_result=true;
+  }
+  
+  // release any gets
+  j_env->ReleaseStringUTFChars(j_index_name, index_name);
+  
+  return j_result;
+}
+
+/* unload the data 
+ */
+JNIEXPORT jboolean JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_unloadIndexData (JNIEnv *j_env, jobject j_obj) {
+
+  jint data_ptr = j_env->GetIntField(j_obj, FID_mgpp_data);
+  MGPPWrapperData * data = (MGPPWrapperData *)data_ptr;
+
+  data->indexData->UnloadData();
+  return true;
+
+}
+
+/* do the actual query - the results are written to query_result held on the 
+   java side */
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_runQuery (JNIEnv *j_env, jobject j_obj, jstring j_query){
+  
+  jthrowable exc; // an exception - check if something funny has happened
+  const char *query = j_env->GetStringUTFChars(j_query, NULL);
+  if (query==NULL) {
+    return; // exception already thrown
+  }
+  // turn to UCArray for mgpp and then release the string
+  UCArray queryArray;
+  SetCStr(queryArray, query);
+  j_env->ReleaseStringUTFChars(j_query, query);
+  
+  // the query data
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  
+  // the result to write to
+  jobject result_ptr = j_env->GetObjectField(j_obj, FID_query_result);
+  if (result_ptr==NULL) {
+    cerr <<"couldn't access the result to write to"<<endl;
+    return;
+  }
+  
+  // clear the result
+  j_env->CallVoidMethod(result_ptr, MID_clearResult);
+  exc = j_env->ExceptionOccurred(); // this catches teh exception I think - it
+  //wont be thrown any further
+  if (exc) {
+    j_env->ExceptionDescribe();
+    return;
+  }
+  // the mgpp QueryResult that we will use
+  ExtQueryResult queryResult;
+
+  QueryNode * queryTree = NULL;
+  // parse the query string into a tree structure
+  queryTree = ParseQuery(queryArray, data->defaultBoolCombine, 
+			 data->defaultStemMethod, data->maxNumeric);
+  if (queryTree == NULL) {
+    // invalid syntax
+    j_env->CallVoidMethod(result_ptr, MID_setSyntaxError, true);
+    cerr << "MGPPWrapperImpl: invalid query syntax!!\n";
+    return; 
+  }
+  // print the query
+  PrintNode (cout, queryTree);
+  // finally, do the query
+  MGQuery(*(data->indexData), *(data->queryInfo), queryTree, queryResult, data->level);
+
+  delete queryTree;
+
+  // convert queryResult to the java side version
+  // use levels rather than docs of ExtQueryResult
+  // CallVoidMethod(obj, method id, args to method)
+  for (int i=0; i<queryResult.levels.size(); i++) {
+    jlong doc = queryResult.levels[i];
+    jfloat rank = queryResult.ranks[i];
+    j_env->CallVoidMethod(result_ptr, MID_addDoc, doc, rank);
+    exc = j_env->ExceptionOccurred();
+    if (exc) {
+      j_env->ExceptionDescribe();
+      return;
+    }
+    
+  }
+
+  // actual num of docs
+  jlong total = queryResult.actualNumDocs;
+  j_env->CallVoidMethod(result_ptr, MID_setTotalDocs, total);
+  exc = j_env->ExceptionOccurred();
+  if (exc) {
+    j_env->ExceptionDescribe();
+    return;
+  }
+
+  // the terms
+  for (int j=0; j<queryResult.termFreqs.size(); j++) {
+    
+    TermFreqData tf = queryResult.termFreqs[j];
+    jstring term = j_env->NewStringUTF(GetCStr(tf.term));
+    jstring tag = j_env->NewStringUTF(GetCStr(tf.tag));
+    jint stem = tf.stemMethod;
+    jlong match = tf.matchDocs;
+    jlong freq = tf.termFreq;
+    
+    jobjectArray equivs=NULL;
+    jstring empty = j_env->NewStringUTF(""); // the initial object to fill the array
+    jint num_equivs = tf.equivTerms.size();
+    equivs = j_env->NewObjectArray(num_equivs, CID_String, empty);
+    if (equivs==NULL) {
+      cerr<<"couldn't create object array"<<endl;
+      
+    } else {
+      for (int k=0; k<num_equivs;k++) {
+	jstring equiv = j_env->NewStringUTF(GetCStr(tf.equivTerms[k]));
+	j_env->SetObjectArrayElement(equivs, k, equiv);
+      }
+      
+      
+      j_env->CallVoidMethod(result_ptr, MID_addTerm, term, tag, stem, match, freq, equivs);
+      exc = j_env->ExceptionOccurred();
+      if (exc) {
+	j_env->ExceptionDescribe();
+	return;
+      }
+    }
+  }
+
+
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_setStem (JNIEnv *j_env, 
+					      jobject j_obj, 
+					      jboolean j_on) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  if (j_on) {
+    data->defaultStemMethod |= 2;
+  } else {
+    data->defaultStemMethod &= 0xd;
+  }
+
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_setAccentFold (JNIEnv *j_env, 
+					      jobject j_obj, 
+					      jboolean j_on) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  if (j_on) {
+    data->defaultStemMethod |= 4;
+  } else {
+    data->defaultStemMethod &= 0xb;
+  }
+}
+
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_setCase (JNIEnv *j_env, 
+					      jobject j_obj, 
+					      jboolean j_on) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+
+  if (j_on) {
+    data->defaultStemMethod |= 1;
+  } else {
+    data->defaultStemMethod &= 0xe;
+  }
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_setMaxDocs (JNIEnv *j_env, 
+						 jobject j_obj, 
+						 jint j_max) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  data->queryInfo->maxDocs=j_max;
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_setMaxNumeric (JNIEnv *j_env, 
+						 jobject j_obj, 
+						 jint j_max) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  data->maxNumeric=j_max;
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_setSortByRank (JNIEnv *j_env, 
+						    jobject j_obj, 
+						    jboolean j_on) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  
+  data->queryInfo->sortByRank=j_on;
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_setReturnTerms(JNIEnv *j_env, 
+						    jobject j_obj, 
+						    jboolean j_on) {
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  data->queryInfo->needTermFreqs = j_on;
+ 
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_setQueryLevel(JNIEnv *j_env, 
+						   jobject j_obj, 
+						   jstring j_level){
+  
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+
+  const char * level = j_env->GetStringUTFChars(j_level, NULL);
+  if (level==NULL) {
+    return; // exception already thrown
+  }
+  
+  data->queryInfo->docLevel.clear();
+  SetCStr(data->queryInfo->docLevel, level);
+  
+  // release the java stuff
+  j_env->ReleaseStringUTFChars(j_level, level);
+ 
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_setReturnLevel(JNIEnv *j_env, 
+						    jobject j_obj, 
+						    jstring j_level){
+
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+
+  const char * level = j_env->GetStringUTFChars(j_level, NULL);
+  if (level==NULL) {
+    return; // exception already thrown
+  }
+  
+  data->level.clear();
+  SetCStr(data->level, level);
+  
+  // release the java stuff
+  j_env->ReleaseStringUTFChars(j_level, level);
+    
+
+}
+
+JNIEXPORT void JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_setMatchMode (JNIEnv *j_env,
+						   jobject j_obj,
+						   jint j_mode){
+
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  data->defaultBoolCombine=j_mode;
+
+}
+
+JNIEXPORT jstring JNICALL 
+Java_org_greenstone_mgpp_MGPPWrapper_getQueryParams (JNIEnv *j_env,
+						     jobject j_obj){
+
+  MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
+  
+  // print the data to a stringstream, then convert to char*, then to 
+  //jstring
+
+  stringstream output;
+  output << "Query params:"<<endl
+    // need to change this to use platform specific separator for niceness
+	 << "index\t\t"<<data->indexData->basePath<<"/"<<data->indexData->filename<<endl
+	 <<"search level\t"<<GetCStr(data->queryInfo->docLevel)<<endl
+	 <<"result level\t"<<GetCStr(data->level)<<endl
+	 <<"casefold\t"<<(data->defaultStemMethod&1)<<endl
+	 <<"stem\t\t"<<(data->defaultStemMethod&2)<<endl
+	 <<"order by rank\t"<<data->queryInfo->sortByRank<<endl
+	 <<"query type\t"<<(data->defaultBoolCombine==1?"all":"some")<<endl
+         <<"max docs\t"<<data->queryInfo->maxDocs<<endl<<ends;
+
+  const char *result = output.str().c_str();
+  jstring j_result = j_env->NewStringUTF(result);
+  delete (char *)result;
+  return j_result;
+}
Index: /indexers/branches/3.03a/mgpp/jni/MGPPWrapperImpl.h
===================================================================
--- /indexers/branches/3.03a/mgpp/jni/MGPPWrapperImpl.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/jni/MGPPWrapperImpl.h	(revision 14757)
@@ -0,0 +1,16 @@
+#include "MGQuery.h"
+
+// the global stuff we need to do a query
+class MGPPWrapperData {
+ public:
+  IndexData * indexData;
+  QueryInfo * queryInfo;
+  int defaultStemMethod;
+  int defaultBoolCombine;
+  int maxNumeric;
+  UCArray level; // the return level
+
+  MGPPWrapperData();
+  ~MGPPWrapperData();
+
+};
Index: /indexers/branches/3.03a/mgpp/jni/Makefile.in
===================================================================
--- /indexers/branches/3.03a/mgpp/jni/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/jni/Makefile.in	(revision 14757)
@@ -0,0 +1,83 @@
+
+SHELL = /bin/sh
+VPATH = @srcdir@
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+bindir = @bindir@
+srcdir = @srcdir@
+libdir = @libdir@
+subdir = jni
+top_srcdir = @top_srcdir@
+transform = @program_transform_name@
+
+UNAC_DIR=@UNAC_DIR@
+
+ENABLE_ACCENTFOLD = @ENABLE_ACCENTFOLD@
+ifeq ($(ENABLE_ACCENTFOLD), 1)
+AFLIBS = $(UNAC_DIR)/libunac.a 
+AFINCLUDES = -I$(UNAC_DIR)
+else
+AFLIBS = 
+AFINCLUDES =
+endif
+
+
+
+AR = ar
+CC = @CC@
+CXX = @CXX@
+CFLAGS = @CFLAGS@ -fPIC -ansi -DSILENT -DSHORT_SUFFIX
+CXXFLAGS = @CXXFLAGS@ -fPIC -DSILENT -DSHORT_SUFFIX
+DEFS = @DEFS@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LDFLAGS = @LDFLAGS@
+#NOTE: libmgpptext.a needs to come before libmgpplib.a !!!
+QUERY_LIBS = ../text/libmgpptext.a   ../lib/libmgpplib.a $(AFLIBS)  -lstdc++ @LIBS@
+PASSES_LIBS = ../text/libmgpppass.a ../lib/libmgpplib.a -lstdc++ @LIBS@
+TOUCH = echo timestamp >
+AWK = @AWK@
+
+JNIFLAGS=@JNIFLAGS@
+JNISUFFIX=@JNISUFFIX@
+JNIINC=@JNIINC@
+
+datadir = $(prefix)/share
+libexecdir = $(exec_prefix)/libexec
+localedir = $(datadir)/locale
+mandir = $(prefix)/man/man1
+
+CXXCOMPILE = $(CXX) -c $(DEFS) $(INCLUDES) $(CXXFLAGS)
+
+.SUFFIXES:
+
+.SUFFIXES: .cpp .o
+.cpp.o:
+	$(CXXCOMPILE) $<
+
+# can we get rid of JAVA_HOME from here??
+INCLUDES = -I.. -I../lib -I../text -I$(JAVA_HOME)/include $(JNIINC) $(AFINCLUDES)
+
+all: compile link
+
+compile:
+	$(CXXCOMPILE) MGPPSearchWrapperImpl.cpp MGPPRetrieveWrapperImpl.cpp MGPPPassesWrapperImpl.cpp
+link:
+	$(CXX) $(LDFLAGS) $(JNIFLAGS) -o libmgppretrievejni.$(JNISUFFIX) MGPPRetrieveWrapperImpl.o $(QUERY_LIBS)
+	$(CXX) $(LDFLAGS) $(JNIFLAGS) -o libmgppsearchjni.$(JNISUFFIX) MGPPSearchWrapperImpl.o $(QUERY_LIBS)
+	$(CXX) $(LDFLAGS) $(JNIFLAGS) -o libmgpppassjni.$(JNISUFFIX) MGPPPassesWrapperImpl.o $(PASSES_LIBS)
+
+clean:
+	rm -rf *.o libmgppretrievejni.$(JNISUFFIX) libmgppsearchjni.$(JNISUFFIX) libmgpppassjni.$(JNISUFFIX)
+
+distclean: clean
+	rm -f Makefile
+
+install:
+#	../mkinstalldirs $(libdir); \
+#	cp libmgppjni.$(JNISUFFIX)  libmgpppassjni.$(JNISUFFIX)  $(libdir)/;
+
+
+
Index: /indexers/branches/3.03a/mgpp/jni/org_greenstone_mgpp_MGPPPassesWrapper.h
===================================================================
--- /indexers/branches/3.03a/mgpp/jni/org_greenstone_mgpp_MGPPPassesWrapper.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/jni/org_greenstone_mgpp_MGPPPassesWrapper.h	(revision 14757)
@@ -0,0 +1,127 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_greenstone_mgpp_MGPPPassesWrapper */
+
+#ifndef _Included_org_greenstone_mgpp_MGPPPassesWrapper
+#define _Included_org_greenstone_mgpp_MGPPPassesWrapper
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef org_greenstone_mgpp_MGPPPassesWrapper_TEXT_PASS_1
+#define org_greenstone_mgpp_MGPPPassesWrapper_TEXT_PASS_1 0L
+#undef org_greenstone_mgpp_MGPPPassesWrapper_TEXT_PASS_2
+#define org_greenstone_mgpp_MGPPPassesWrapper_TEXT_PASS_2 1L
+#undef org_greenstone_mgpp_MGPPPassesWrapper_INDEX_PASS_1
+#define org_greenstone_mgpp_MGPPPassesWrapper_INDEX_PASS_1 2L
+#undef org_greenstone_mgpp_MGPPPassesWrapper_INDEX_PASS_2
+#define org_greenstone_mgpp_MGPPPassesWrapper_INDEX_PASS_2 3L
+#undef org_greenstone_mgpp_MGPPPassesWrapper_SPECIAL_PASS
+#define org_greenstone_mgpp_MGPPPassesWrapper_SPECIAL_PASS 4L
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    init
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_init
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    setBasePath
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_setBasePath
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    setFileName
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_setFileName
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    setDocumentTag
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_setDocumentTag
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    addLevelTag
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_addLevelTag
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    setIndexLevel
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_setIndexLevel
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    setInversionMemLimit
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_setInversionMemLimit
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    finish
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_finish
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    exitValue
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_exitValue
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_initIDs
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    initCSide
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_initCSide
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    addPass
+ * Signature: (CC)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_addPass
+  (JNIEnv *, jobject, jchar, jchar);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPPassesWrapper
+ * Method:    processMGPPDocument
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPPassesWrapper_processMGPPDocument
+  (JNIEnv *, jobject, jbyteArray);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: /indexers/branches/3.03a/mgpp/jni/org_greenstone_mgpp_MGPPRetrieveWrapper.h
===================================================================
--- /indexers/branches/3.03a/mgpp/jni/org_greenstone_mgpp_MGPPRetrieveWrapper.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/jni/org_greenstone_mgpp_MGPPRetrieveWrapper.h	(revision 14757)
@@ -0,0 +1,53 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_greenstone_mgpp_MGPPRetrieveWrapper */
+
+#ifndef _Included_org_greenstone_mgpp_MGPPRetrieveWrapper
+#define _Included_org_greenstone_mgpp_MGPPRetrieveWrapper
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_greenstone_mgpp_MGPPRetrieveWrapper
+ * Method:    initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPRetrieveWrapper_initIDs
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPRetrieveWrapper
+ * Method:    initCppSide
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPRetrieveWrapper_initCppSide
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPRetrieveWrapper
+ * Method:    getDocument
+ * Signature: (Ljava/lang/String;Ljava/lang/String;J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_greenstone_mgpp_MGPPRetrieveWrapper_getDocument
+  (JNIEnv *, jobject, jstring, jstring, jlong);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPRetrieveWrapper
+ * Method:    loadIndexData
+ * Signature: (Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPRetrieveWrapper_loadIndexData
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPRetrieveWrapper
+ * Method:    unloadIndexData
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPRetrieveWrapper_unloadIndexData
+  (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: /indexers/branches/3.03a/mgpp/jni/org_greenstone_mgpp_MGPPSearchWrapper.h
===================================================================
--- /indexers/branches/3.03a/mgpp/jni/org_greenstone_mgpp_MGPPSearchWrapper.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/jni/org_greenstone_mgpp_MGPPSearchWrapper.h	(revision 14757)
@@ -0,0 +1,141 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_greenstone_mgpp_MGPPSearchWrapper */
+
+#ifndef _Included_org_greenstone_mgpp_MGPPSearchWrapper
+#define _Included_org_greenstone_mgpp_MGPPSearchWrapper
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_initIDs
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    initCppSide
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_initCppSide
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    loadIndexData
+ * Signature: (Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_loadIndexData
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    unloadIndexData
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_unloadIndexData
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    setStem
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_setStem
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    setAccentFold
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_setAccentFold
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    setCase
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_setCase
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    setMaxDocs
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_setMaxDocs
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    setSortByRank
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_setSortByRank
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    setReturnTerms
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_setReturnTerms
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    setQueryLevel
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_setQueryLevel
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    setReturnLevel
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_setReturnLevel
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    setMatchMode
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_setMatchMode
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    setMaxNumeric
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_setMaxNumeric
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    getQueryParams
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_getQueryParams
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPSearchWrapper
+ * Method:    runQuery
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPSearchWrapper_runQuery
+  (JNIEnv *, jobject, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: /indexers/branches/3.03a/mgpp/jni/org_greenstone_mgpp_MGPPWrapper.h
===================================================================
--- /indexers/branches/3.03a/mgpp/jni/org_greenstone_mgpp_MGPPWrapper.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/jni/org_greenstone_mgpp_MGPPWrapper.h	(revision 14757)
@@ -0,0 +1,149 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_greenstone_mgpp_MGPPWrapper */
+
+#ifndef _Included_org_greenstone_mgpp_MGPPWrapper
+#define _Included_org_greenstone_mgpp_MGPPWrapper
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPWrapper_initIDs
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    initCppSide
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPWrapper_initCppSide
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    getDocument
+ * Signature: (Ljava/lang/String;Ljava/lang/String;J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_greenstone_mgpp_MGPPWrapper_getDocument
+  (JNIEnv *, jobject, jstring, jstring, jlong);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    loadIndexData
+ * Signature: (Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPWrapper_loadIndexData
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    unloadIndexData
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_greenstone_mgpp_MGPPWrapper_unloadIndexData
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    setStem
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPWrapper_setStem
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    setAccentFold
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPWrapper_setAccentFold
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    setCase
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPWrapper_setCase
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    setMaxDocs
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPWrapper_setMaxDocs
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    setSortByRank
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPWrapper_setSortByRank
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    setReturnTerms
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPWrapper_setReturnTerms
+  (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    setQueryLevel
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPWrapper_setQueryLevel
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    setReturnLevel
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPWrapper_setReturnLevel
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    setMatchMode
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPWrapper_setMatchMode
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    setMaxNumeric
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPWrapper_setMaxNumeric
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    getQueryParams
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_greenstone_mgpp_MGPPWrapper_getQueryParams
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_greenstone_mgpp_MGPPWrapper
+ * Method:    runQuery
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_greenstone_mgpp_MGPPWrapper_runQuery
+  (JNIEnv *, jobject, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: /indexers/branches/3.03a/mgpp/jni/win32.mak
===================================================================
--- /indexers/branches/3.03a/mgpp/jni/win32.mak	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/jni/win32.mak	(revision 14757)
@@ -0,0 +1,86 @@
+###########################################################################
+#
+# win32 makefile -- mgpp\jni
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999  The New Zealand Digital Library Project
+#
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+ 
+MGPPHOME = ..
+
+AR = lib
+CC = cl
+CPPFLAGS = -GX
+
+DEFS = -DQUIET -DHAVE_CONFIG_H -DSHORT_SUFFIX -DHAVE_STRING_H -D__WIN32__
+INCLUDES = -I"$(MGPPHOME)" -I"$(MGPPHOME)\lib" -I"$(MGPPHOME)\text" \
+           -I"$(JAVA_HOME)\include" -I"$(JAVA_HOME)\include\win32"           
+
+COMPILE = $(CC) -c $(CPPFLAGS) $(DEFS) $(INCLUDES) 
+ 
+.SUFFIXES:
+.SUFFIXES: .c .obj
+.c.obj:
+	$(COMPILE) $<
+
+ANSI2KNR = 
+o = .obj
+ 
+HEADERS = \
+    MGPPSearchWrapperImpl.h   MGPPRetrieveWrapperImpl.h   org_greenstone_mgpp_MGPPSearchWrapper.h \
+   org_greenstone_mgpp_MGPPRetrieveWrapper.h org_greenstone_mgpp_MGPPPassesWrapperImpl.h
+
+SOURCES = \
+    MGPPSearchWrapperImpl.cpp MGPPRetrieveWrapperImpl.cpp MGPPPassesWrapperImpl.cpp
+
+RETRIEVEOBJECTS = \
+    MGPPRetrieveWrapperImpl$o  $(MGPPHOME)\text\libmgpptext.lib \
+    $(MGPPHOME)\lib\libmgpplib.lib
+
+SEARCHOBJETCS =  \
+    MGPPSearchWrapperImpl$o $(MGPPHOME)\text\libmgpptext.lib \
+    $(MGPPHOME)\lib\libmgpplib.lib
+
+
+PASSES_OBJECTS = \
+    MGPPPassesWrapperImpl$o $(MGPPHOME)\text\libmgpppass.lib \
+    $(MGPPHOME)\lib\libmgpplib.lib
+
+DISTFILES = Makefile.in $(HEADERS) $(SOURCES)
+ 
+all : compile link
+
+compile:
+        $(COMPILE) MGPPSearchWrapperImpl.cpp MGPPRetrieveWrapperImpl.cpp MGPPPassesWrapperImpl.cpp
+
+link:
+	$(CC) -MD -LD $(SEARCHOBJETCS) -Femgppsearchjni.dll
+	$(CC) -MD -LD $(RETRIEVEOBJECTS) -Femgppretrievejni.dll
+	$(CC) -MD -LD $(PASSES_OBJECTS) -Femgpppassjni.dll
+
+install: 
+
+clean:
+	del *$o mgppsearchjni.dll mgppretrievejni.dll mgppjni.exp mgppjni.lib mgpppassjni.dll mgpppassjni.exp mgpppassjni.lib 
+	if exist mgppsearchjni.lib del mgppsearchjni.lib
+	if exist mgppretrievejni.lib del mgppretrievejni.lib
+	if exist mgjni.lib del mgjni.lib
+
Index: /indexers/branches/3.03a/mgpp/lib/Makefile.in
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/Makefile.in	(revision 14757)
@@ -0,0 +1,156 @@
+###########################################################################
+#
+# Makefile.in -- Makefile for the general purpose library
+# Copyright (C) 1994  Neil Sharman; (C) 1995 Tim Shimmin
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#       @(#)Makefile.in	1.3 16 Mar 1994
+#
+###########################################################################
+
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+ 
+SHELL = /bin/sh
+srcdir = @srcdir@
+subdir = lib
+VPATH = @srcdir@
+ 
+AR = ar
+CC = @CC@
+CXX = @CXX@
+ifneq ($(NZDL), 1)
+CFLAGS = @CFLAGS@ -ansi -fPIC
+else 
+CFLAGS = @CFLAGS@ -ansi -fPIC -DSILENT
+endif
+CXXFLAGS = @CXXFLAGS@ -fPIC
+DEFS = @DEFS@
+RANLIB = @RANLIB@
+
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+libdir = @libdir@
+datadir = $(prefix)/share
+localedir = $(datadir)/locale
+ 
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES)  $(CFLAGS)
+CXXCOMPILE = $(CXX) -c $(DEFS) $(INCLUDES) $(CXXFLAGS)
+ 
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+	$(COMPILE) $<
+
+.SUFFIXES: .cpp .o
+.cpp.o:
+	$(COMPILE) -D__cplusplus $<
+
+ANSI2KNR = @ANSI2KNR@
+o = .@U@o
+ 
+.SUFFIXES: ._c ._o
+.c._c:
+	./ansi2knr $< > $*.tmp && mv $*.tmp $@
+._c._o:
+	@echo $(COMPILE) $<
+	@rm -f _$*.c
+	@ln $< _$*.c && $(COMPILE) _$*.c && mv _$*.o $@ && rm _$*.c
+.c._o:
+	./ansi2knr $< > $*.tmp && mv $*.tmp $*._c
+	@echo $(COMPILE) $*._c
+	@rm -f _$*.c
+	@ln $*._c _$*.c && $(COMPILE) _$*.c && mv _$*.o $@ && rm _$*.c
+
+INCLUDES = -I.. -I$(srcdir)
+ 
+HEADERS = \
+    bitio_m_random.h   local_strings.h    lovinstem.h \
+    bitio_m_stdio.h    memlib.h           netorder.h \
+    bitio_gen.h        mgheap.h           messages.h \
+    bitio_m.h          huffman.h  \
+    bitio_m_mem.h      perf_hash.h \
+    bitio_m_mems.h      \
+    pathmax.h          getpagesize.h      sysfuncs.h         bitio_m_abstract.h  \
+    random.h           simplefrenchstem.h unitool.h	     longlong.h \
+    non_ansi.h
+
+
+SOURCES = \
+    mgheap.cpp         \
+    huffman.cpp       messages.cpp \
+    bitio_gen.cpp     perf_hash.cpp \
+    local_strings.cpp lovinstem.cpp \
+    bitio_m_mem.cpp   bitio_m_stdio.cpp bitio_m_mems.cpp \
+    alloca.c          xmalloc.c         strstr.cpp \
+    ftruncate.cpp     strcasecmp.cpp    random.cpp \
+    simplefrenchstem.cpp                unitool.cpp       bitio_m_random.cpp \
+    bitio_m_abstract.cpp
+# memlib.cpp removed
+
+OBJECTS =  mgheap$o   \
+    huffman$o         messages$o \
+    bitio_gen$o       perf_hash$o \
+     local_strings$o   lovinstem$o \
+    bitio_m_mem$o     bitio_m_stdio$o   bitio_m_mems$o \
+    xmalloc$o         bitio_m_random$o  bitio_m_abstract$o \
+     random$o          simplefrenchstem$o \
+    unitool$o
+
+DISTFILES = Makefile.in $(HEADERS) $(SOURCES)
+
+all : libmgpplib.a
+
+libmgpplib.a : $(OBJECTS)
+	rm -f libmgpplib.a
+	$(AR) cru libmgpplib.a $(OBJECTS)
+	$(RANLIB) libmgpplib.a
+
+install: 
+installdirs:
+uninstall:
+execinstall:
+execuninstall:
+maninstall:
+manuninstall:
+ 
+dist: $(DISTFILES)
+	for file in $(DISTFILES); do \
+	  ln $$file $(distdir) 2> /dev/null \
+	  || cp -p $$file $(distdir); \
+	done
+
+mostlyclean:
+	rm -f *.o *_.o
+ 
+clean: mostlyclean
+	rm -f libmgpplib.a
+ 
+distclean: clean
+	rm -f Makefile
+ 
+maintainer-clean: distclean
+	@echo "This command is intended only for maintainers to use;"
+	@echo "rebuilding the deleted files may require special tools."
+
+# breaks make distclean (jrm21)
+#Makefile: Makefile.in ../../../config.status
+#	cd ../../.. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
+ 
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /indexers/branches/3.03a/mgpp/lib/WIN32.MAK
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/WIN32.MAK	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/WIN32.MAK	(revision 14757)
@@ -0,0 +1,96 @@
+###########################################################################
+#
+# win32 makefile -- mgpp\lib
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999  The New Zealand Digital Library Project
+#
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+MGPPHOME = ..
+
+AR = lib
+CC = cl
+CPPFLAGS = 
+
+DEFS = -DQUIET -DHAVE_CONFIG_H -D__WIN32__ -DSHORT_SUFFIX
+INCLUDES = -I"." -I"$(MGPPHOME)"
+
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS)
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .obj
+.c.obj:
+	$(COMPILE) $<
+.cpp.obj:
+	$(COMPILE) $<
+
+ANSI2KNR = 
+o = .obj
+
+HEADERS = \
+    bitio_m_random.h   local_strings.h    lovinstem.h \
+    bitio_m_stdio.h    memlib.h           netorder.h \
+    bitio_gen.h        mgheap.h           messages.h \
+    bitio_m.h          huffman.h  \
+    bitio_m_mem.h      perf_hash.h \
+    bitio_m_mems.h      \
+    pathmax.h          getpagesize.h      sysfuncs.h         bitio_m_abstract.h  \
+    random.h           simplefrenchstem.h unitool.h	     longlong.h \
+    non_ansi.h         getopt_old.h       win32in.h
+
+
+SOURCES = \
+    mgheap.cpp         \
+    huffman.cpp       messages.cpp \
+    bitio_gen.cpp     perf_hash.cpp \
+    local_strings.cpp lovinstem.cpp \
+    bitio_m_mem.cpp   bitio_m_stdio.cpp bitio_m_mems.cpp \
+    alloca.c          xmalloc.c         strstr.cpp \
+    ftruncate.cpp     strcasecmp.cpp    random.cpp \
+    simplefrenchstem.cpp                unitool.cpp       bitio_m_random.cpp \
+    bitio_m_abstract.cpp                getopt_old.c      win32in.c
+# memlib.cpp removed
+
+
+OBJECTS =  mgheap$o   \
+    huffman$o         messages$o \
+    bitio_gen$o       perf_hash$o \
+     local_strings$o   lovinstem$o \
+    bitio_m_mem$o     bitio_m_stdio$o   bitio_m_mems$o \
+    xmalloc$o         bitio_m_random$o  bitio_m_abstract$o \
+     random$o          simplefrenchstem$o \
+    unitool$o         getopt_old$o      win32in$o
+
+ 
+DISTFILES = Makefile.in $(HEADERS) $(SOURCES)
+ 
+all : libmgpplib.lib
+
+libmgpplib.lib : $(OBJECTS)
+	if EXIST libmgpplib.lib del libmgpplib.lib
+	$(AR) /out:libmgpplib.lib $(OBJECTS)
+
+$(OBJECTS): "$(MGPPHOME)\win32cfg.h"
+
+install: 
+clean:
+	del *$o 
+	del libmgpplib.lib
Index: /indexers/branches/3.03a/mgpp/lib/alloca.c
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/alloca.c	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/alloca.c	(revision 14757)
@@ -0,0 +1,496 @@
+/* alloca.c -- allocate automatically reclaimed memory
+   (Mostly) portable public-domain implementation -- D A Gwyn
+
+   This implementation of the PWB library alloca function,
+   which is used to allocate space off the run-time stack so
+   that it is automatically reclaimed upon procedure exit,
+   was inspired by discussions with J. Q. Johnson of Cornell.
+   J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+   There are some preprocessor constants that can
+   be defined when compiling for your specific system, for
+   improved efficiency; however, the defaults should be okay.
+
+   The general concept of this implementation is to keep
+   track of all alloca-allocated blocks, and reclaim any
+   that are found to be deeper in the stack than the current
+   invocation.  This heuristic does not reclaim storage as
+   soon as it becomes invalid, but it will do so eventually.
+
+   As a special case, alloca(0) reclaims storage without
+   allocating any.  It is a good idea to use alloca(0) in
+   your main control loop, etc. to force garbage collection.  */
+
+#ifdef HAVE_CONFIG_H
+# ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+#  include <win32cfg.h>
+# else
+#  include <sysfuncs.h>
+# endif
+#endif
+
+#ifdef emacs
+#include "blockinput.h"
+#endif
+
+/* If compiling with GCC 2, this file's not needed.  */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If someone has defined alloca as a macro,
+   there must be some other way alloca is supposed to work.  */
+#ifndef alloca
+
+#ifdef emacs
+#ifdef static
+/* actually, only want this if static is defined as ""
+   -- this is for usg, in which emacs must undefine static
+   in order to make unexec workable
+   */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+   provide an "address metric" ADDRESS_FUNCTION macro.  */
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+#else
+#define ADDRESS_FUNCTION(arg) &(arg)
+#endif
+
+#if __STDC__
+typedef void *pointer;
+#else
+typedef char *pointer;
+#endif
+
+#define	NULL	0
+
+/* Different portions of Emacs need to call different versions of
+   malloc.  The Emacs executable needs alloca to call xmalloc, because
+   ordinary malloc isn't protected from input signals.  On the other
+   hand, the utilities in lib-src need alloca to call malloc; some of
+   them are very simple, and don't have an xmalloc routine.
+
+   Non-Emacs programs expect this to call use xmalloc.
+
+   Callers below should use malloc.  */
+
+#ifndef emacs
+#define malloc xmalloc
+#endif
+extern pointer malloc ();
+
+/* Define STACK_DIRECTION if you know the direction of stack
+   growth for your system; otherwise it will be automatically
+   deduced at run-time.
+
+   STACK_DIRECTION > 0 => grows toward higher addresses
+   STACK_DIRECTION < 0 => grows toward lower addresses
+   STACK_DIRECTION = 0 => direction of growth unknown  */
+
+#ifndef STACK_DIRECTION
+#define	STACK_DIRECTION	0	/* Direction unknown.  */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define	STACK_DIR	STACK_DIRECTION	/* Known at compile-time.  */
+
+#else /* STACK_DIRECTION == 0; need run-time code.  */
+
+static int stack_dir;		/* 1 or -1 once known.  */
+#define	STACK_DIR	stack_dir
+
+static void
+find_stack_direction ()
+{
+  static char *addr = NULL;	/* Address of first `dummy', once known.  */
+  auto char dummy;		/* To get stack address.  */
+
+  if (addr == NULL)
+    {				/* Initial entry.  */
+      addr = ADDRESS_FUNCTION (dummy);
+
+      find_stack_direction ();	/* Recurse once.  */
+    }
+  else
+    {
+      /* Second entry.  */
+      if (ADDRESS_FUNCTION (dummy) > addr)
+	stack_dir = 1;		/* Stack grew upward.  */
+      else
+	stack_dir = -1;		/* Stack grew downward.  */
+    }
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+   (a) chain together all alloca'ed blocks;
+   (b) keep track of stack depth.
+
+   It is very important that sizeof(header) agree with malloc
+   alignment chunk size.  The following default should work okay.  */
+
+#ifndef	ALIGN_SIZE
+#define	ALIGN_SIZE	sizeof(double)
+#endif
+
+typedef union hdr
+{
+  char align[ALIGN_SIZE];	/* To force sizeof(header).  */
+  struct
+    {
+      union hdr *next;		/* For chaining headers.  */
+      char *deep;		/* For stack depth measure.  */
+    } h;
+} header;
+
+static header *last_alloca_header = NULL;	/* -> last alloca header.  */
+
+/* Return a pointer to at least SIZE bytes of storage,
+   which will be automatically reclaimed upon exit from
+   the procedure that called alloca.  Originally, this space
+   was supposed to be taken from the current stack frame of the
+   caller, but that method cannot be made to work for some
+   implementations of C, for example under Gould's UTX/32.  */
+
+pointer
+alloca (size)
+     unsigned size;
+{
+  auto char probe;		/* Probes stack depth: */
+  register char *depth = ADDRESS_FUNCTION (probe);
+
+#if STACK_DIRECTION == 0
+  if (STACK_DIR == 0)		/* Unknown growth direction.  */
+    find_stack_direction ();
+#endif
+
+  /* Reclaim garbage, defined as all alloca'd storage that
+     was allocated from deeper in the stack than currently. */
+
+  {
+    register header *hp;	/* Traverses linked list.  */
+
+#ifdef emacs
+    BLOCK_INPUT;
+#endif
+
+    for (hp = last_alloca_header; hp != NULL;)
+      if ((STACK_DIR > 0 && hp->h.deep > depth)
+	  || (STACK_DIR < 0 && hp->h.deep < depth))
+	{
+	  register header *np = hp->h.next;
+
+	  free ((pointer) hp);	/* Collect garbage.  */
+
+	  hp = np;		/* -> next header.  */
+	}
+      else
+	break;			/* Rest are not deeper.  */
+
+    last_alloca_header = hp;	/* -> last valid storage.  */
+
+#ifdef emacs
+    UNBLOCK_INPUT;
+#endif
+  }
+
+  if (size == 0)
+    return NULL;		/* No allocation required.  */
+
+  /* Allocate combined header + user data storage.  */
+
+  {
+    register pointer new = malloc (sizeof (header) + size);
+    /* Address of header.  */
+
+    ((header *) new)->h.next = last_alloca_header;
+    ((header *) new)->h.deep = depth;
+
+    last_alloca_header = (header *) new;
+
+    /* User storage begins just after header.  */
+
+    return (pointer) ((char *) new + sizeof (header));
+  }
+}
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+#ifdef DEBUG_I00AFUNC
+#include <stdio.h>
+#endif
+
+#ifndef CRAY_STACK
+#define CRAY_STACK
+#ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+  {
+    long shgrow:32;		/* Number of times stack has grown.  */
+    long shaseg:32;		/* Size of increments to stack.  */
+    long shhwm:32;		/* High water mark of stack.  */
+    long shsize:32;		/* Current size of stack (all segments).  */
+  };
+
+/* The stack segment linkage control information occurs at
+   the high-address end of a stack segment.  (The stack
+   grows from low addresses to high addresses.)  The initial
+   part of the stack segment linkage control information is
+   0200 (octal) words.  This provides for register storage
+   for the routine which overflows the stack.  */
+
+struct stack_segment_linkage
+  {
+    long ss[0200];		/* 0200 overflow words.  */
+    long sssize:32;		/* Number of words in this segment.  */
+    long ssbase:32;		/* Offset to stack base.  */
+    long:32;
+    long sspseg:32;		/* Offset to linkage control of previous
+				   segment of stack.  */
+    long:32;
+    long sstcpt:32;		/* Pointer to task common address block.  */
+    long sscsnm;		/* Private control structure number for
+				   microtasking.  */
+    long ssusr1;		/* Reserved for user.  */
+    long ssusr2;		/* Reserved for user.  */
+    long sstpid;		/* Process ID for pid based multi-tasking.  */
+    long ssgvup;		/* Pointer to multitasking thread giveup.  */
+    long sscray[7];		/* Reserved for Cray Research.  */
+    long ssa0;
+    long ssa1;
+    long ssa2;
+    long ssa3;
+    long ssa4;
+    long ssa5;
+    long ssa6;
+    long ssa7;
+    long sss0;
+    long sss1;
+    long sss2;
+    long sss3;
+    long sss4;
+    long sss5;
+    long sss6;
+    long sss7;
+  };
+
+#else /* CRAY2 */
+/* The following structure defines the vector of words
+   returned by the STKSTAT library routine.  */
+struct stk_stat
+  {
+    long now;			/* Current total stack size.  */
+    long maxc;			/* Amount of contiguous space which would
+				   be required to satisfy the maximum
+				   stack demand to date.  */
+    long high_water;		/* Stack high-water mark.  */
+    long overflows;		/* Number of stack overflow ($STKOFEN) calls.  */
+    long hits;			/* Number of internal buffer hits.  */
+    long extends;		/* Number of block extensions.  */
+    long stko_mallocs;		/* Block allocations by $STKOFEN.  */
+    long underflows;		/* Number of stack underflow calls ($STKRETN).  */
+    long stko_free;		/* Number of deallocations by $STKRETN.  */
+    long stkm_free;		/* Number of deallocations by $STKMRET.  */
+    long segments;		/* Current number of stack segments.  */
+    long maxs;			/* Maximum number of stack segments so far.  */
+    long pad_size;		/* Stack pad size.  */
+    long current_address;	/* Current stack segment address.  */
+    long current_size;		/* Current stack segment size.  This
+				   number is actually corrupted by STKSTAT to
+				   include the fifteen word trailer area.  */
+    long initial_address;	/* Address of initial segment.  */
+    long initial_size;		/* Size of initial segment.  */
+  };
+
+/* The following structure describes the data structure which trails
+   any stack segment.  I think that the description in 'asdef' is
+   out of date.  I only describe the parts that I am sure about.  */
+
+struct stk_trailer
+  {
+    long this_address;		/* Address of this block.  */
+    long this_size;		/* Size of this block (does not include
+				   this trailer).  */
+    long unknown2;
+    long unknown3;
+    long link;			/* Address of trailer block of previous
+				   segment.  */
+    long unknown5;
+    long unknown6;
+    long unknown7;
+    long unknown8;
+    long unknown9;
+    long unknown10;
+    long unknown11;
+    long unknown12;
+    long unknown13;
+    long unknown14;
+  };
+
+#endif /* CRAY2 */
+#endif /* not CRAY_STACK */
+
+#ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+   I doubt that "lint" will like this much. */
+
+static long
+i00afunc (long *address)
+{
+  struct stk_stat status;
+  struct stk_trailer *trailer;
+  long *block, size;
+  long result = 0;
+
+  /* We want to iterate through all of the segments.  The first
+     step is to get the stack status structure.  We could do this
+     more quickly and more directly, perhaps, by referencing the
+     $LM00 common block, but I know that this works.  */
+
+  STKSTAT (&status);
+
+  /* Set up the iteration.  */
+
+  trailer = (struct stk_trailer *) (status.current_address
+				    + status.current_size
+				    - 15);
+
+  /* There must be at least one stack segment.  Therefore it is
+     a fatal error if "trailer" is null.  */
+
+  if (trailer == 0)
+    abort ();
+
+  /* Discard segments that do not contain our argument address.  */
+
+  while (trailer != 0)
+    {
+      block = (long *) trailer->this_address;
+      size = trailer->this_size;
+      if (block == 0 || size == 0)
+	abort ();
+      trailer = (struct stk_trailer *) trailer->link;
+      if ((block <= address) && (address < (block + size)))
+	break;
+    }
+
+  /* Set the result to the offset in this segment and add the sizes
+     of all predecessor segments.  */
+
+  result = address - block;
+
+  if (trailer == 0)
+    {
+      return result;
+    }
+
+  do
+    {
+      if (trailer->this_size <= 0)
+	abort ();
+      result += trailer->this_size;
+      trailer = (struct stk_trailer *) trailer->link;
+    }
+  while (trailer != 0);
+
+  /* We are done.  Note that if you present a bogus address (one
+     not in any segment), you will get a different number back, formed
+     from subtracting the address of the first block.  This is probably
+     not what you want.  */
+
+  return (result);
+}
+
+#else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+   Determine the number of the cell within the stack,
+   given the address of the cell.  The purpose of this
+   routine is to linearize, in some sense, stack addresses
+   for alloca.  */
+
+static long
+i00afunc (long address)
+{
+  long stkl = 0;
+
+  long size, pseg, this_segment, stack;
+  long result = 0;
+
+  struct stack_segment_linkage *ssptr;
+
+  /* Register B67 contains the address of the end of the
+     current stack segment.  If you (as a subprogram) store
+     your registers on the stack and find that you are past
+     the contents of B67, you have overflowed the segment.
+
+     B67 also points to the stack segment linkage control
+     area, which is what we are really interested in.  */
+
+  stkl = CRAY_STACKSEG_END ();
+  ssptr = (struct stack_segment_linkage *) stkl;
+
+  /* If one subtracts 'size' from the end of the segment,
+     one has the address of the first word of the segment.
+
+     If this is not the first segment, 'pseg' will be
+     nonzero.  */
+
+  pseg = ssptr->sspseg;
+  size = ssptr->sssize;
+
+  this_segment = stkl - size;
+
+  /* It is possible that calling this routine itself caused
+     a stack overflow.  Discard stack segments which do not
+     contain the target address.  */
+
+  while (!(this_segment <= address && address <= stkl))
+    {
+#ifdef DEBUG_I00AFUNC
+      fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+#endif
+      if (pseg == 0)
+	break;
+      stkl = stkl - pseg;
+      ssptr = (struct stack_segment_linkage *) stkl;
+      size = ssptr->sssize;
+      pseg = ssptr->sspseg;
+      this_segment = stkl - size;
+    }
+
+  result = address - this_segment;
+
+  /* If you subtract pseg from the current end of the stack,
+     you get the address of the previous stack segment's end.
+     This seems a little convoluted to me, but I'll bet you save
+     a cycle somewhere.  */
+
+  while (pseg != 0)
+    {
+#ifdef DEBUG_I00AFUNC
+      fprintf (stderr, "%011o %011o\n", pseg, size);
+#endif
+      stkl = stkl - pseg;
+      ssptr = (struct stack_segment_linkage *) stkl;
+      size = ssptr->sssize;
+      pseg = ssptr->sspseg;
+      result += size;
+    }
+  return (result);
+}
+
+#endif /* not CRAY2 */
+#endif /* CRAY */
+
+#endif /* no alloca */
+#endif /* not GCC version 2 */
Index: /indexers/branches/3.03a/mgpp/lib/bitio_gen.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/bitio_gen.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/bitio_gen.cpp	(revision 14757)
@@ -0,0 +1,134 @@
+/**************************************************************************
+ *
+ * bitio_gen.c -- General supoport routines for bitio
+ * Copyright (C) 1994  Neil Sharman and Alistair Moffat
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "bitio_m_abstract.h"
+
+int fprintf (FILE *, const char *,...);
+
+unsigned long 
+BIO_Unary_Length (unsigned long val)
+{
+  register unsigned long num;
+  num = bitio_buffer::unary_length(val);
+  //  UNARY_LENGTH (val, num);
+  return (num);
+}
+
+
+unsigned long 
+BIO_Binary_Length (unsigned long val, unsigned long b)
+{
+  register unsigned long num;
+  num = bitio_buffer::binary_length (val, b);
+  return (num);
+}
+
+
+unsigned long BIO_Gamma_Length (unsigned long val) {
+  register unsigned long num;
+  num = bitio_buffer::gamma_length(val);
+  return (num);
+}
+
+
+unsigned long 
+BIO_Delta_Length (unsigned long val)
+{
+  register unsigned long num;
+  num = bitio_buffer::delta_length(val);
+  return (num);
+}
+
+
+unsigned long 
+BIO_Elias_Length (unsigned long val, unsigned long b, double s)
+{
+  register unsigned long num;
+  num = bitio_buffer::elias_length(val, b, s);
+  return (num);
+}
+
+unsigned long 
+BIO_Bblock_Length (unsigned long val, unsigned long b)
+{
+  register unsigned long num;
+  num = bitio_buffer::bblock_length (val, b);
+  return (num);
+}
+
+
+int 
+BIO_Bblock_Init (int N, int p)
+{
+  int b;
+  b = (int) (0.5 + 0.6931471 * N / p);
+  return (b ? b : 1);
+}
+
+
+int 
+BIO_Bblock_Init_W (int N, int p)
+{
+  int logb;
+  logb = bitio_buffer::floor_log2 ((N - p) / p);
+  return (logb < 0 ? 1 : (1 << logb));
+}
+
+int 
+BIO_Bblock_Bound_b (int N, int p, int b)
+{
+  int clogb;
+  clogb = bitio_buffer::ceil_log2 (b);
+  return (p * (1 + clogb) + (N - p * ((1 << clogb) - b + 1)) / b);
+}
+
+int 
+BIO_Bblock_Bound (int N, int p)
+{
+  int b;
+  b = BIO_Bblock_Init_W (N, p);
+  return (BIO_Bblock_Bound_b (N, p, b));
+}
+
+/* adjustment is a hack to overcome inaccuracies in floating point,
+   where (int)(ln4/ln2) can equal 1, not 2. */
+int 
+BIO_Gamma_Bound (int N, int p)
+{
+  return ((int) (p * (2 * log2 (((double) N * 1.0001) / p) + 1)));
+}
+
+int 
+floorlog_2 (int b)
+{
+  int logb;
+  logb = bitio_buffer::floor_log2 (b);
+  return logb;
+}
+
+int 
+ceillog_2 (int b)
+{
+  int logb;
+  logb = bitio_buffer::ceil_log2 (b);
+  return logb;
+}
Index: /indexers/branches/3.03a/mgpp/lib/bitio_gen.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/bitio_gen.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/bitio_gen.h	(revision 14757)
@@ -0,0 +1,61 @@
+/**************************************************************************
+ *
+ * bitio_gen.h -- General supoport routines for bitio
+ * Copyright (C) 1994  Neil Sharman and Alistair Moffat
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains function definitions for doing general bitio operations.
+ *
+ *  This file defines functions for calculation the length in bits of a number
+ *  coded unary, binary, delta, gamma, elias, and  bblock coding. It defines 
+ *  routines for calculating the parameter and bounds for bblock coding. 
+ *  Routines for calculating ceil and floor lg are also defined.
+ *
+ *
+ **************************************************************************/
+
+#ifndef H_BITIO_GEN
+#define H_BITIO_GEN
+
+unsigned long BIO_Unary_Length (unsigned long val);
+
+unsigned long BIO_Binary_Length (unsigned long val, unsigned long b);
+
+unsigned long BIO_Gamma_Length (unsigned long val);
+
+unsigned long BIO_Delta_Length (unsigned long val);
+
+unsigned long BIO_Elias_Length (unsigned long val, unsigned long b, double s);
+
+unsigned long BIO_Bblock_Length (unsigned long val, unsigned long b);
+
+int BIO_Bblock_Init (int N, int p);
+
+int BIO_Bblock_Init_W (int N, int p);
+
+int BIO_Bblock_Bound_b (int N, int p, int b);
+
+int BIO_Bblock_Bound (int N, int p);
+
+int BIO_Gamma_Bound (int N, int p);
+
+int floorlog_2 (int b);
+
+int ceillog_2 (int b);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/bitio_m_abstract.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/bitio_m_abstract.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/bitio_m_abstract.cpp	(revision 14757)
@@ -0,0 +1,9 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "bitio_m_abstract.h"
+
+
+
+
+
Index: /indexers/branches/3.03a/mgpp/lib/bitio_m_abstract.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/bitio_m_abstract.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/bitio_m_abstract.h	(revision 14757)
@@ -0,0 +1,340 @@
+#ifndef H_BITIO_ABSTRACT
+#define H_BITIO_ABSTRACT
+
+class bitio_buffer {
+public:
+  virtual int bit() = 0;
+  virtual void encodeBit(int bit) = 0;
+  virtual void seek(unsigned long topos) = 0;
+  
+  static inline void check_positive(char *type, unsigned long x) {
+    if (x <= 0) {
+      fprintf(stderr, "Error: Cannot %s encode %lu\n", type, x);
+      exit(1);
+    }
+  }
+
+  static inline int floor_log2(unsigned long x) {
+    unsigned long  _B_x = x;
+    int reply;
+    
+    reply = -1;
+    while (_B_x != 0) {
+      _B_x >>= 1;
+      ++reply;
+    }
+    return reply;
+  }
+  
+  static inline int ceil_log2(unsigned long x) {
+    register int _B_x;
+    unsigned long reply;
+    
+    _B_x = x - 1;
+    reply = 0;
+    while (_B_x != 0) {
+      _B_x >>= 1;
+      ++reply;
+    }
+    return reply;
+  }
+
+  inline unsigned long unary_decode(unsigned long *count) {
+    unsigned long x;
+    
+    x = 1;
+    while (!this->bit()) ++x;
+    if (count != NULL) {
+      *count += x;
+    }
+    return x;
+  }
+
+  inline void unary_encode(unsigned long x, unsigned long *count) {
+    register unsigned long _B_x = x;
+    check_positive("unary", _B_x);
+    if (count != NULL) {
+      *count += _B_x;
+    }
+    while(--_B_x) 
+      encodeBit(0);
+    encodeBit(1);
+  }
+
+
+  inline unsigned long binary_decode(unsigned long b, unsigned long *count) {
+    register unsigned long _B_x = 0;
+    register unsigned long _B_b = b;
+    register int _B_i, _B_logofb, _B_thresh;
+    register unsigned long reply;
+    
+    if (_B_b != 1) {					
+      _B_logofb = ceil_log2(_B_b);
+      _B_thresh = (1<<_B_logofb) - _B_b;
+      --_B_logofb;
+      
+      if (count != NULL) {
+	*count += _B_logofb;
+      }
+      
+      for (_B_i=0; _B_i < _B_logofb; ++_B_i) {
+	_B_x += _B_x + this->bit();
+      }
+
+      if ((int)_B_x >= _B_thresh) {
+	_B_x += _B_x + this->bit();
+	_B_x -= _B_thresh;
+	if (count != NULL) {
+	  *count = *count + 1;
+	}
+      }
+      reply = _B_x+1;
+      
+    } else reply = 1;
+    
+    return reply;
+  }
+
+  inline void binary_encode(unsigned long x, unsigned long b, unsigned long *count) {
+    register unsigned long _B_x = (x);
+    register unsigned long _B_b = (b);
+    register int _B_nbits, _B_logofb, _B_thresh;
+    
+    check_positive("binary", _B_x);
+    _B_logofb = ceil_log2(_B_b);
+    
+    _B_thresh = (1<<_B_logofb) - _B_b;
+    if ((int)(--_B_x) < _B_thresh) _B_nbits = _B_logofb-1;
+    else {
+      _B_nbits = _B_logofb;
+      _B_x += _B_thresh;
+    }
+    if (count != NULL) {
+      *count += _B_nbits;
+    }
+    while (--_B_nbits>=0)
+      encodeBit((_B_x>>_B_nbits) & 0x1);
+  }
+
+  inline unsigned long bblock_decode(unsigned long b, unsigned long *count) {
+    register unsigned long _B_x1, _B_xx = 0;
+    register unsigned long _B_bb = (b);
+    register int _B_xdivb;
+    
+    _B_xdivb = this->unary_decode(count);
+    --_B_xdivb;				       
+    while (_B_xdivb--) {
+      _B_xx += _B_bb;
+    }
+    _B_x1 = this->binary_decode(_B_bb, count);
+    return (_B_xx + _B_x1);
+  }
+  
+  inline void bblock_encode(unsigned long x, unsigned long b, unsigned long *count) {
+    register unsigned long _B_xx = (x);
+    register unsigned long _B_bb = (b);
+    register int _B_xdivb = 0;
+    check_positive("bblock", _B_xx);
+    --_B_xx;
+    while (_B_xx >= _B_bb) {
+      ++_B_xdivb;
+      _B_xx -= _B_bb;
+    }
+    unary_encode(_B_xdivb+1, count);
+    binary_encode(_B_xx+1, _B_bb, count);
+  }
+
+  inline unsigned long elias_decode(unsigned long b, double s, unsigned long *count) {
+    register unsigned long _B_xx;
+    register unsigned long _B_b = b;
+    register double _B_s = s;
+    register int _B_lower=1, _B_upper=1;
+    register int _B_k;
+    register double _B_pow=1.0;
+    
+    _B_k = this->unary_decode(count);
+    --_B_k;
+    while (_B_k--) {
+      _B_lower = _B_upper+1;
+      _B_pow *= _B_s;
+      _B_upper += (int) (_B_b*_B_pow);
+    }
+    _B_xx = this->binary_decode(_B_upper-_B_lower+1, count);
+    --_B_xx;
+    check_positive("gamma", _B_xx+_B_lower);
+    return _B_xx+_B_lower;
+  }
+  
+  inline void elias_encode(unsigned long x, unsigned long b, double s, unsigned long *count) {
+    register unsigned long _B_xx = x;
+    register unsigned long _B_b = b;
+    register double _B_s = s;
+    register int _B_lower=1, _B_upper=1;
+    register int _B_k=0;
+    register double _B_pow=1.0;
+    
+    check_positive("elias", _B_xx);
+    
+    while ((int)_B_xx>_B_upper) {
+      ++_B_k;
+      _B_lower = _B_upper+1;
+      _B_pow *= _B_s;
+      _B_upper += (int) (_B_b*_B_pow);
+    }
+    unary_encode(_B_k+1, count);
+    binary_encode(_B_xx-_B_lower+1, _B_upper-_B_lower+1, count);
+  }
+  
+  inline unsigned long gamma_decode(unsigned long *count) {
+    register unsigned long _B_xx = 1;
+    register int _B_nbits = 0;
+    
+    while(!this->bit()) ++_B_nbits;
+    if (count != NULL) {
+      *count += _B_nbits*2+1;
+    }
+    while (_B_nbits-- > 0)
+      _B_xx += _B_xx + this->bit();
+    return _B_xx;
+  }
+
+  inline void gamma_encode(unsigned long x, unsigned long *count) {
+    register unsigned long _B_xx = x;
+    register int _B_logofb;
+    register int _B_nbits;
+    
+    check_positive("gamma", _B_xx);
+    _B_logofb = floor_log2(_B_xx);
+    _B_nbits = _B_logofb+1;
+    
+    if (count != NULL) { 
+      *count += _B_logofb*2+1;
+    }
+    while(_B_logofb--) encodeBit(0);
+    while (--_B_nbits>=0) encodeBit((_B_xx>>_B_nbits) & 0x1);
+  }
+  
+  inline unsigned long delta_decode(unsigned long *count) {
+    register unsigned long _B_xxx;
+    register int _B_logx;
+    _B_logx = gamma_decode(count);
+    --_B_logx;
+    _B_xxx = binary_decode(1<<_B_logx, count); 
+    --_B_xxx;
+    return (_B_xxx + (1<<_B_logx));
+  }
+
+  inline void delta_encode(unsigned long x, unsigned long *count) {
+    register unsigned long _B_xxx = x;
+    register int _B_logx;
+    _B_logx = floor_log2(_B_xxx);
+    gamma_encode(_B_logx+1, count);
+    binary_encode(_B_xxx+1, 1<<_B_logx, count);
+  }
+
+  inline unsigned long huff_decode(unsigned long *mcodes, unsigned long **values,
+				   unsigned long *count = NULL) {
+    register unsigned long *__min_code = mcodes;
+    register unsigned long *__mclen    = mcodes;
+    register unsigned long **__values  = values;
+    register unsigned long __code = 0;
+    do {
+      __code += __code + bit();
+      if (count != NULL) ++(*count);
+    } while (__code < *++__mclen);
+    
+    return __values[__mclen - __min_code][__code - *__mclen];
+  }
+
+  inline void huff_encode(unsigned long x, unsigned long *codes, char *lens,
+			  unsigned long *count = NULL) {
+    register int __i;
+    register int __clen = lens[x];
+    register unsigned long __code = codes[x];
+    for (__i=__clen-1; __i>=0; --__i) {
+      encodeBit((__code >> __i) & 1);
+    }
+    if (count != NULL) {
+      *count += lens[x];
+    }
+  }
+
+  static inline unsigned long unary_length(unsigned long x) {
+    check_positive("unary", x);
+    return x;
+  }
+
+  static inline int binary_length(unsigned long x, unsigned long b) {
+    register unsigned long _B_x = (x);
+    register unsigned long _B_b = (b);
+    register int _B_nbits, _B_logofb, _B_thresh;
+    
+    check_positive("binary", _B_x);
+    _B_logofb = ceil_log2(_B_b);
+    _B_thresh = (1<<_B_logofb) - _B_b;
+    if ((int)(--_B_x) < _B_thresh) _B_nbits = _B_logofb-1;
+    else _B_nbits = _B_logofb;
+    return _B_nbits;
+  }
+
+  static inline unsigned long bblock_length(unsigned long x, unsigned long b) {
+    register unsigned long _B_bcount, count, _B_xx = (x);
+    register unsigned long _B_bb = (b);
+    register int _B_xdivb = 0;
+    
+    check_positive("bblock", _B_xx);
+    --_B_xx;
+    while (_B_xx >= _B_bb) {
+      ++_B_xdivb;
+      _B_xx -= _B_bb;
+    }
+    count = unary_length(_B_xdivb+1);
+    _B_bcount = binary_length(_B_xx+1, _B_bb);
+    count += _B_bcount;
+    return count;
+  }
+  
+  static inline unsigned long elias_length(unsigned long x, unsigned long b, 
+					   double s) {
+    register unsigned long _B_xx = x;
+    register unsigned long _B_b = b;
+    register double _B_s = s;
+    register int _B_lower=1, _B_upper=1;
+    register int _B_k=0, _B_ecount;
+    register double _B_pow=1.0;
+    register unsigned long count;
+    check_positive("gamma", _B_xx);
+    
+    while ((int)(_B_xx)>_B_upper) {
+      ++_B_k;
+      _B_lower = _B_upper+1;
+      _B_pow *= _B_s;
+      _B_upper += (int) (_B_b*_B_pow);
+    }
+    count = unary_length(_B_k+1);
+    _B_ecount = binary_length(_B_xx-_B_lower+1, _B_upper-_B_lower+1);
+    count += _B_ecount;
+    return count;
+  }
+  
+  static inline unsigned long gamma_length(unsigned long x) {
+    register unsigned long _B_xx = x;
+    register int _B_logofb;
+    check_positive("gamma", _B_xx);
+    _B_logofb = floor_log2(_B_xx);
+    return _B_logofb*2+1;
+  }
+
+  static inline unsigned long delta_length(unsigned long x) {
+    register unsigned long _B_xxx = x;
+    register int _B_logx, _B_dcount;
+    register unsigned long count;
+    _B_logx = floor_log2 (_B_xxx);
+    count = gamma_length(_B_logx+1);
+    _B_dcount = binary_length (_B_xxx+1, 1<<_B_logx);
+    count += _B_dcount;
+    return count;
+  }
+};
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/bitio_m_mem.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/bitio_m_mem.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/bitio_m_mem.cpp	(revision 14757)
@@ -0,0 +1,128 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "bitio_m_abstract.h"
+#include "bitio_m_mem.h"
+
+mem_bitio_buffer::mem_bitio_buffer() {
+}
+
+mem_bitio_buffer::mem_bitio_buffer(unsigned char *readbuffer, int size) { 
+  pos       = readbuffer;
+  base      = readbuffer;
+  remaining = size;
+  buffer    = 0;
+  btg       = 0;
+}
+
+
+void mem_bitio_buffer::error() {
+  fprintf (stderr, "Unexpected EOF in \"%s\" on line %d\n", __FILE__, __LINE__);
+  exit(1);
+}
+
+void mem_bitio_buffer::encodeStart() {
+  btg = sizeof(buffer) * 8;
+}
+
+
+void mem_bitio_buffer::seek(unsigned long toPos) { 
+  register long _newPos;
+  do {
+    _newPos = toPos;
+    
+    pos    = base + (_newPos >> 3);
+    buffer = *pos++;
+    btg    = 8 - (_newPos & 0x07);
+  } while (0);
+}
+
+long mem_bitio_buffer::addff(long b) {
+  do {
+    if (btg == 0) {
+      if (remaining != 0) {
+	buffer = *pos++;
+	--remaining;
+      } else {
+	buffer = 0xff;
+      }
+      btg = sizeof(buffer) * 8;
+    }
+    b = b + b + ((buffer >> --btg) & 1);
+  } while(0);
+
+  return b;
+}
+
+long mem_bitio_buffer::add00(long b) {
+  do {
+    if (btg == 0) {
+      if (remaining != 0) {
+	buffer = *pos++;
+	--remaining;
+      } else {
+	buffer = 0x00;
+      }
+      btg = sizeof(buffer) * 8;
+    }
+    b = b + b + ((buffer >> --btg) & 1);
+  } while(0);
+  
+  return b;
+}
+
+int mem_bitio_buffer::bit() {
+  if (btg == 0) {
+
+    if (remaining == 0) { 
+      this->error();
+      return 0;
+
+    } else {
+      buffer = *pos++;
+      --remaining;
+      btg = sizeof(buffer) * 8;
+    }
+    
+  }
+  return ((buffer >> --btg) & 0x01);
+}
+
+void mem_bitio_buffer::encodeBit(int b) {
+  --btg;
+  if (b) buffer |= (1 << btg);
+  
+  if (btg == 0) {
+    if (remaining) {
+      *pos++ = buffer;
+      --remaining;
+    }
+    buffer = 0;
+    btg = sizeof(buffer)*8;
+  }
+}
+
+void mem_bitio_buffer::flush() {
+  if (btg != sizeof(buffer)*8) {
+    if (remaining) {
+      *pos++ = buffer;
+      --remaining;
+    }
+  }
+  btg = sizeof(buffer)*8;
+}
+
+void mem_bitio_buffer::done() {
+  // do nothing
+}
+
+int mem_bitio_buffer::encodeLength() {
+  return pos - base;
+}
+
+int mem_bitio_buffer::encodeVerify() {
+  return (remaining != 0);
+}
+
+
+
Index: /indexers/branches/3.03a/mgpp/lib/bitio_m_mem.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/bitio_m_mem.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/bitio_m_mem.h	(revision 14757)
@@ -0,0 +1,104 @@
+/**************************************************************************
+ *
+ * bitio_m_mem.h -- Macros for bitio to memory
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains macros for doing bitwise input and output on an array 
+ *  of chars. These routines are faster than the ones in "mems" files. But 
+ *  with these routines you cannot mix reads and writes on the array of chars,
+ *  or multiple write, at the same time and guarantee them to work, also you 
+ *  cannot seek to a point and do a write. The decode routine can detect when
+ *  you run off the end of the array and will produce an approate error 
+ *  message, and the encode routine will stop when it gets to the end of the 
+ *  character array. 
+ *
+ **************************************************************************/
+
+#ifndef H_BITIO_M_MEM
+#define H_BITIO_M_MEM
+
+#include "bitio_m_abstract.h"
+
+
+class mem_bitio_buffer : public bitio_buffer {
+protected:
+  unsigned char *pos;
+  unsigned char *base;
+  int            remaining;
+  unsigned char  buffer;
+  unsigned char  btg;
+  
+public:
+  mem_bitio_buffer ();
+  mem_bitio_buffer (unsigned char *buffer, int size);
+  void seek (unsigned long topos);
+  void error ();
+  long add00 (long b);
+  long addff (long b);
+  int  bit ();
+  void done ();
+
+  void encodeStart ();
+  void encodeBit (int bit);
+  void encodeDone () { flush(); }
+  int  encodeVerify ();
+  int  encodeLength ();
+  void flush ();
+};
+
+
+/*
+#define ENCODE_START(p,r)						\
+  {									\
+    mem_bitio_buffer buffer(p, r);                                     \
+    buffer.encodeStart();
+
+#define ENCODE_CONTINUE(b)						\
+  {									\
+    mem_bitio_buffer buffer;                                           \
+    buffer.unpause(b);
+
+#define ENCODE_PAUSE(b)	buffer.pause(&b);}
+
+#define ENCODE_FLUSH buffer.flush()
+
+#define ENCODE_DONE buffer.flush();}
+
+
+#define DECODE_START(p,r)						\
+  {	                                                                \
+    mem_bitio_buffer buffer(p,r);
+
+#define DECODE_CONTINUE(b)						\
+  {	                                                                \
+    mem_bitio_buffer buffer;                                           \
+    buffer.unpause(b);
+
+#define DECODE_ADD_FF(b) b = buffer.addff(b)
+
+#define DECODE_ADD_00(b) b = buffer.add00(b)
+
+#define DECODE_BIT buffer.bit()
+
+#define DECODE_DONE buffer.done();}
+
+#define DECODE_PAUSE(b) buffer.pause(&b);}
+*/
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/bitio_m_mems.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/bitio_m_mems.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/bitio_m_mems.cpp	(revision 14757)
@@ -0,0 +1,89 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "bitio_m_abstract.h"
+#include "bitio_m_mems.h"
+
+/**
+ * Create decoding "stream"/"file"
+ */
+mems_bitio_buffer::mems_bitio_buffer()
+{
+}
+
+mems_bitio_buffer::mems_bitio_buffer(unsigned char *readbuffer, long _pos)
+{ 
+  base = readbuffer;
+  pos  = _pos;
+}
+
+void mems_bitio_buffer::encodeStart()
+{
+  // Do nothing
+}
+
+
+void mems_bitio_buffer::error()
+{
+  fprintf(stderr, "Unexpected EOF in \"%s\" on line %d\n", __FILE__, __LINE__);
+  exit(1);
+}
+
+
+void mems_bitio_buffer::seek(unsigned long toPos)
+{ 
+  pos = toPos;
+}
+
+unsigned long mems_bitio_buffer::position()
+{
+  return pos;
+}
+
+long mems_bitio_buffer::addff(long b)
+{
+  do
+    {
+      b = b + b + (base[pos>>3] & (0x80 >> (pos & 0x07)) != 0);
+      ++pos;
+    }
+  while(0);
+
+  return b;
+}
+
+long mems_bitio_buffer::add00(long b)
+{
+  return addff(b);
+}
+
+int mems_bitio_buffer::bit()
+{
+  ++pos;
+  return ((base[(pos-1)>>3] & (0x80 >> ((pos-1) & 0x07))) != 0);
+}
+
+void mems_bitio_buffer::encodeBit(int bit)
+{
+  if (bit)
+    base[pos>>3] |= 0x80 >> (pos & 0x07);
+  else
+    base[pos>>3] &= 0xff7f >> (pos & 0x07);
+  ++pos;
+}
+
+void mems_bitio_buffer::flush()
+{
+  // do nothing
+}
+
+void mems_bitio_buffer::done()
+{
+  // do nothing
+}
+
+void mems_bitio_buffer::encodeDone()
+{
+  flush();
+}
+
Index: /indexers/branches/3.03a/mgpp/lib/bitio_m_mems.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/bitio_m_mems.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/bitio_m_mems.h	(revision 14757)
@@ -0,0 +1,100 @@
+/**************************************************************************
+ *
+ * bitio_m_mems.h -- Macros for bitio to memory (random access)
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains macros for doing bitwise input and output on an array 
+ *  of chars. These routines are slower than the ones in "mem" files. but 
+ *  with these routines you can mix reads and writes, or multiple writes,  on
+ *  the array of chars at the same time and guarantee them to work, also you 
+ *  can seek to a point and do a write. The decode and encode macros cannot 
+ *  detect when the end off the character is reached and just continue 
+ *  processing.
+ *
+ **************************************************************************/
+
+#ifndef H_BITIO_M_MEMS
+#define H_BITIO_M_MEMS
+
+#include "bitio_m_abstract.h"
+
+
+class mems_bitio_buffer : public bitio_buffer {
+protected:
+  unsigned char *base;
+  unsigned long  pos;
+  
+public:
+  mems_bitio_buffer();
+  mems_bitio_buffer(unsigned char *readbuffer, long _pos);
+  void seek(unsigned long topos);
+  void error();
+  long add00(long b);
+  long addff(long b);
+  int  bit();
+  //  int  bitOffset();
+  void done();
+
+  unsigned long position();
+
+  void encodeStart();
+  void encodeBit(int b);
+  void encodeDone();
+  void flush();
+};
+
+
+/*#define ENCODE_START(b,p)						\
+  {									\
+    mems_bitio_buffer buffer(b, p);
+
+#define ENCODE_CONTINUE(b)						\
+  {									\
+    mems_bitio_buffer buffer;                                          \
+    buffer.unpause(b);
+
+#define ENCODE_PAUSE(b)	buffer.pause(&b);}
+
+#define ENCODE_FLUSH buffer.flush();
+
+
+#define ENCODE_DONE buffer.encodeDone();}
+
+
+#define DECODE_START(b,p)						\
+  {		                                                        \
+    mems_bitio_buffer buffer(b, p);
+
+#define DECODE_CONTINUE(b)						\
+  {									\
+    mems_bitio_buffer buffer;                                          \
+    buffer.unpause(b);
+
+#define DECODE_ADD_FF(b) b = buffer.addff(b);
+
+#define DECODE_ADD_00(b) b = buffer.add00(b);
+
+#define DECODE_BIT buffer.bit()
+
+#define DECODE_DONE buffer.done();}
+
+#define DECODE_PAUSE(b) buffer.pause(&b);}
+*/
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/bitio_m_random.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/bitio_m_random.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/bitio_m_random.cpp	(revision 14757)
@@ -0,0 +1,218 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "longlong.h"
+#include "sysfuncs.h"
+#include "memlib.h"
+
+#include "bitio_m_abstract.h"
+#include "bitio_m_random.h"
+
+random_bitio_buffer::random_bitio_buffer(FILE *f, unsigned long length)
+{
+  buffer = NULL;
+  attachFile (f, length);
+}
+
+random_bitio_buffer::~random_bitio_buffer() {
+  if (buffer != NULL) delete []buffer;
+}
+
+void random_bitio_buffer::attachFile (FILE *f, unsigned long length) {
+  // delete the old buffer
+  if (buffer != NULL) {
+    delete []buffer;
+    buffer = NULL;
+  }
+
+  // reset all the values
+  file   = f;
+  pos    = 0;
+  base   = 0;
+  used   = 0;
+  len    = length - 1;
+  shift  = 0;
+
+  // make sure the length is a power of 2
+  while (len != 0) {
+    ++shift;
+    len = len >> 1;
+  }
+  len = 1 << shift;
+
+  // allocate a new buffer
+  buffer = new u_char[len];
+
+  // fill up the buffer
+  if (file != NULL) {
+    fseek(file, 0, 0);
+    fread(buffer, 1, len, file);
+  }
+}
+
+random_bitio_buffer &random_bitio_buffer::operator= (const random_bitio_buffer &_rbb) {
+  // delete the old buffer
+  if (buffer != NULL) {
+    delete []buffer;
+    buffer = NULL;
+  }
+
+  file = _rbb.file;
+
+  base = _rbb.base;
+  used = _rbb.used;
+  pos = _rbb.pos;
+  len = _rbb.len;
+  shift = _rbb.shift;
+
+  // copy the buffer
+  buffer = new u_char [len];
+  //  memcpy (buffer, _rbb.buffer, len);
+memcpy (buffer, _rbb.buffer, len);
+  
+  return (*this);
+}
+
+void random_bitio_buffer::error() {
+}
+
+void random_bitio_buffer::writeRead()
+{
+  if (used)
+    {
+      fseek(file, base, 0);
+      fwrite(buffer, 1, len, file);
+    }
+  //  else
+  //    {
+      base += len;
+      fseek(file, base, 0);
+      fread(buffer, 1, len, file);
+      pos = 0;
+      used = 0;
+  //    }
+}
+
+void random_bitio_buffer::encodeBit(int bit)
+{
+  do
+    {
+      if (bit != 0)
+	{
+	  buffer[pos >> 3] |= 0x80 >> (pos & 0x07);
+	}
+      else
+	{
+	  buffer[pos >> 3] &= 0xff7f >> (pos & 0x07);
+	}
+      used = 1;
+      ++pos;
+
+      if ((pos >> 3) >= len)
+	{
+	  writeRead();
+	}
+    }
+  while (0);
+}
+
+void random_bitio_buffer::flush()
+{
+  if (used != 0)
+    {
+      fseek(file, base, 0);
+      fwrite(buffer, 1, len, file);
+      used = 0;
+    }
+}
+
+void random_bitio_buffer::encodeDone()
+{
+  flush();
+  if (buffer != NULL) {
+    delete []buffer;
+    buffer = NULL;
+  }
+}
+
+unsigned long random_bitio_buffer::tell()
+{
+  return ((base << 3) + pos);
+}
+
+void random_bitio_buffer::seek(unsigned long toPos)
+{
+  if (((toPos >> 3) >= base) && (((toPos+7) >> 3) < (base + len)))
+    {
+      pos = toPos - (base << 3);
+    }
+  else
+    {
+      flush();
+      base = toPos >> 3;
+      base = (toPos >> (shift + 3)) << shift;
+      fseek(file, base, 0);
+      fread(buffer, 1, len, file);
+      pos = toPos & 0x07;
+      pos = toPos & ((8 << shift) - 1);
+    }
+}
+
+int random_bitio_buffer::bit()
+{
+  //  fprintf(stderr, "Bit in");
+  ++pos;
+  if (((pos - 1) >> 3) >= len)
+    {
+      writeRead();
+      pos = 1;
+    }
+  return (buffer[(pos - 1) >> 3] & (0x80 >> ((pos - 1) & 0x07))) != 0;
+}
+
+long random_bitio_buffer::addff(long b)
+{
+  return b + b + bit();
+}
+
+long random_bitio_buffer::add00(long b)
+{
+  return addff(b);
+}
+
+int random_bitio_buffer::bitOffset()
+{
+  return 0;
+}
+
+void random_bitio_buffer::done()
+{
+  encodeDone();
+}
+
+
+#ifdef USE_LONG_LONG
+void random_bitio_buffer::seek_LL(mg_ullong toPos)
+{
+  if (((toPos >> 3) >= (mg_ullong) base) &&
+      (((toPos + 7) >> 3) < (mg_ullong) (base + len)))
+    {
+      pos = (long) (toPos - (mg_ullong) (base << 3));
+    }
+  else
+    {
+      flush();
+      base = (long) ((toPos >> (shift + 3)) << shift);
+
+      fseek(file, base, 0);
+      fread(buffer, 1, len, file);
+      pos = (long) (toPos & ((8 << shift) - 1));
+    }
+}
+
+mg_ullong random_bitio_buffer::tell_LL()
+{
+  return (((mg_ullong) base) << 3ull) + pos;
+}
+#endif
+
Index: /indexers/branches/3.03a/mgpp/lib/bitio_m_random.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/bitio_m_random.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/bitio_m_random.h	(revision 14757)
@@ -0,0 +1,127 @@
+/**************************************************************************
+ *
+ * bitio_m_random.h -- Macros for bitio to a file (random access)
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains macros for doing bitwise input and output on an array 
+ *  of chars. These routines are slower than the ones in "mem" files. but 
+ *  with these routines you can mix reads and writes, or multiple writes,  on
+ *  the array of chars at the same time and guarantee them to work, also you 
+ *  can seek to a point and do a write. The decode and encode macros cannot 
+ *  detect when the end off the character is reached and just continue 
+ *  processing.
+ *
+ *
+ **************************************************************************/
+
+#ifndef H_BITIO_M_RANDOM
+#define H_BITIO_M_RANDOM
+
+#include "longlong.h"
+#include "bitio_m_abstract.h"
+
+
+class random_bitio_buffer : public bitio_buffer { 
+public:
+  FILE *file;
+  unsigned char *buffer;
+  unsigned long  base;
+  unsigned long  used;
+  unsigned long  pos;
+  unsigned long  len;
+  unsigned long  shift;
+  void writeRead();
+
+  random_bitio_buffer(FILE *f = 0,
+		      unsigned long length = 8*1024);
+  virtual ~random_bitio_buffer();
+  
+  void attachFile (FILE *f, unsigned long length);
+
+  random_bitio_buffer &operator= (const random_bitio_buffer &_rbb);
+  
+  void encodeDone();
+  void encodeBit(int b);
+  void flush();
+  unsigned long tell();
+
+  void seek(unsigned long topos);
+  void error();
+  long add00(long b);
+  long addff(long b);
+  int  bit();
+  int  bitOffset();
+  void done();
+
+#ifdef USE_LONG_LONG
+  // extras for longlong.h
+  void seek_LL(mg_ullong pos);
+  mg_ullong tell_LL();
+#endif
+};
+
+
+/*#define ENCODE_START(f,l)						\
+  {									\
+    random_bitio_buffer buffer(f, l);
+
+#define ENCODE_CONTINUE(b)						\
+  {									\
+    random_bitio_buffer buffer;                                               \
+    buffer.unpause(b);
+
+#define SEEK fprintf(stderr, "Seek to %d\n",buffer.base)
+#define READ fprintf(stderr, "Read of %d\n",buffer.len)
+#define WRITE fprintf(stderr, "Write of %d\n",buffer.used)
+
+#define WRITE_READ buffer.writeRead()
+
+#define ENCODE_PAUSE(b)	buffer.pause(&b);}
+
+#define ENCODE_FLUSH buffer.flush();
+
+#define ENCODE_DONE buffer.done();}							
+
+#define DECODE_START(f,l) \
+  {									\
+    random_bitio_buffer buffer(f, l);
+
+#define DECODE_CONTINUE(b) \
+  {									\
+    random_bitio_buffer buffer;                                               \
+    buffer.unpause(b);
+
+#define DECODE_BIT buffer.bit()
+
+#define DECODE_ADD_FF(b) b = buffer.addff(b)
+
+#define DECODE_ADD_00(b) b = buffer.add00(b)
+
+#define DECODE_DONE buffer.done();}
+
+#define DECODE_PAUSE(b)	buffer.pause(&b);}
+
+#define ENCODE_TELL buffer.tell()
+
+#define DECODE_TELL buffer.tell()
+*/
+
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/bitio_m_stdio.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/bitio_m_stdio.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/bitio_m_stdio.cpp	(revision 14757)
@@ -0,0 +1,125 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "bitio_m_stdio.h"
+
+stdio_bitio_buffer::stdio_bitio_buffer(FILE *f) {
+  attachFile (f);
+}
+
+void stdio_bitio_buffer::attachFile (FILE *f) {
+  file = f;
+  buffer = 0;
+  btg = 0;
+  bytesWritten = 0;
+}
+
+void stdio_bitio_buffer::encodeStart() {
+  btg = sizeof(buffer) * 8;
+}
+
+void stdio_bitio_buffer::error() {
+  fprintf(stderr, "Unexpected EOF in \"%s\" on line %d", __FILE__, __LINE__);
+  exit(1);
+}
+
+void stdio_bitio_buffer::seek (unsigned long byte, unsigned char bit) {
+  if (fseek (file, byte, SEEK_SET) != 0) return;
+  buffer = getc(file);
+  btg = bit;
+  bytesWritten = 0;
+}
+
+void stdio_bitio_buffer::seek(unsigned long topos) {
+  if (fseek(file, topos >> 3, SEEK_SET) != 0) return;
+  buffer = getc(file);
+  btg = 8 - (topos & 0x07);
+  bytesWritten = 0;
+}
+
+long stdio_bitio_buffer::addff(long b)
+{
+  if (!btg)
+    {
+      register int val;
+      val = getc(file);
+      if (val == EOF)
+	{
+	  buffer = 0x0ff;
+	}
+      else
+	{
+	  buffer = val;
+	}
+      btg = sizeof(buffer) * 8;
+    }
+  b = b + b + ((buffer >> --btg) & 0x01);
+
+  return b;
+}
+
+long stdio_bitio_buffer::add00(long b)
+{
+  if (!btg)
+    {
+      register int val;
+      val = getc(file);
+      if (val == EOF)
+	{
+	  buffer = 0xff;
+	}
+      else
+	{
+	  buffer = val;
+	}
+      btg = sizeof(buffer) * 8;
+    }
+  b = b + b + ((buffer >> --btg) & 0x01);
+  
+  return b;
+}
+
+void stdio_bitio_buffer::encodeBit(int b)
+{
+  --btg;
+  if (b != 0)
+    buffer |= (1 << btg);
+
+  if (btg == 0)
+    {
+      putc(buffer, file);
+      bytesWritten += sizeof (buffer);
+      buffer = 0;
+      btg = sizeof(buffer)*8;
+    }
+}
+
+int stdio_bitio_buffer::bit()
+{
+  if (btg == 0)
+    {
+      buffer = getc(file);
+      if (feof(file))
+	{
+	  error();
+	  return 0;
+	}
+      else
+	{
+	  btg = sizeof(buffer) * 8;
+	}
+    }
+  return ((buffer >> --btg) & 0x01);
+}
+
+void stdio_bitio_buffer::done() {
+  // no tidying required
+}
+
+void stdio_bitio_buffer::encodeDone() {
+  if (btg != sizeof(buffer) * 8) {
+    putc(buffer, file);
+    bytesWritten += sizeof (buffer);
+  }
+}
+
Index: /indexers/branches/3.03a/mgpp/lib/bitio_m_stdio.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/bitio_m_stdio.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/bitio_m_stdio.h	(revision 14757)
@@ -0,0 +1,101 @@
+/**************************************************************************
+ *
+ * bitio_m_stdio.h -- Macros for bitio to a file
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ *  This file contains macros for doing bitwise input and output on a FILE*.
+ *  With these routines you cannot mix reads and writes on the FILE,
+ *  or multiple writes, at the same time and guarantee them to work, also you 
+ *  cannot seek to a point and do a write. The decode routine can detect when
+ *  you run off the end of the file and will produce an approate error message.
+ *
+ *
+ **************************************************************************/
+
+#ifndef H_BITIO_M_STDIO
+#define H_BITIO_M_STDIO
+
+#include "bitio_m_abstract.h"
+
+
+class stdio_bitio_buffer : public bitio_buffer {
+protected:
+  FILE *file;
+  unsigned char buffer;
+  unsigned char btg;
+  unsigned long bytesWritten;
+  
+public:
+  stdio_bitio_buffer (FILE *f = NULL);
+
+  void attachFile (FILE *f);
+
+  unsigned char GetBtg () { return btg; }
+  unsigned long GetBytesWritten () { return bytesWritten; }
+  
+  void seek (unsigned long byte, unsigned char bit);
+  void seek (unsigned long topos);
+  void error();
+  long add00(long b);
+  long addff(long b);
+  int  bit();
+  int  bitOffset() { return btg; }
+  void done();
+
+  void encodeStart();
+  void encodeBit(int bit);
+  void encodeDone();
+};
+
+
+/*#define ENCODE_START(f)							\
+  {									\
+    stdio_bitio_buffer buffer(f);                                       \
+    buffer.encodeStart();
+
+#define ENCODE_CONTINUE(b)						\
+  {									\
+    stdio_bitio_buffer buffer;                                          \
+    buffer.unpause(b);
+
+#define ENCODE_PAUSE(b) buffer.pause(&b);}
+
+#define ENCODE_DONE buffer.encodeDone();}
+
+#define DECODE_START(f)							\
+  {		                                                        \
+    stdio_bitio_buffer buffer(f);
+
+#define DECODE_CONTINUE(b)						\
+  {									\
+    stdio_bitio_buffer buffer;                                          \
+     buffer.unpause(b);
+
+#define DECODE_ADD_FF(b) b = buffer.addff(b)
+
+#define DECODE_ADD_00(b) b = buffer.add00(b)
+
+#define DECODE_BIT buffer.bit()
+
+#define DECODE_DONE buffer.done();}
+
+#define DECODE_PAUSE(b) buffer.pause(&b);}
+*/
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/ftruncate.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/ftruncate.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/ftruncate.cpp	(revision 14757)
@@ -0,0 +1,99 @@
+/* ftruncate emulations that work on some System V's.
+   This file is in the public domain.  */
+
+#ifdef HAVE_CONFIG_H
+# ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+#  include <win32cfg.h>
+# else
+#  include <sysfuncs.h>
+# endif
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+
+#ifdef F_CHSIZE
+
+int
+ftruncate (int fd, off_t length)
+{
+  return fcntl (fd, F_CHSIZE, length);
+}
+
+#else /* not F_CHSIZE */
+#ifdef F_FREESP
+
+/* By William Kucharski <kucharsk@netcom.com>.  */
+
+#include <sys/stat.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+int
+ftruncate (int fd, off_t length)
+{
+  struct flock fl;
+  struct stat filebuf;
+
+  if (fstat (fd, &filebuf) < 0)
+    return -1;
+
+  if (filebuf.st_size < length)
+    {
+      /* Extend file length. */
+      if (lseek (fd, (length - 1), SEEK_SET) < 0)
+	return -1;
+
+      /* Write a "0" byte. */
+      if (write (fd, "", 1) != 1)
+	return -1;
+    }
+  else
+    {
+
+      /* Truncate length. */
+
+      fl.l_whence = 0;
+      fl.l_len = 0;
+      fl.l_start = length;
+      fl.l_type = F_WRLCK;	/* write lock on file space */
+
+      /* This relies on the *undocumented* F_FREESP argument to fcntl,
+	 which truncates the file so that it ends at the position
+	 indicated by fl.l_start.  Will minor miracles never cease?  */
+
+      if (fcntl (fd, F_FREESP, &fl) < 0)
+	return -1;
+    }
+
+  return 0;
+}
+
+#else /* not F_CHSIZE nor F_FREESP */
+#ifdef HAVE_CHSIZE
+
+int
+ftruncate (int fd, off_t length)
+{
+  return chsize (fd, length);
+}
+
+#else /* not F_CHSIZE nor F_FREESP nor HAVE_CHSIZE */
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+int
+ftruncate (int fd, off_t length)
+{
+  errno = EIO;
+  return -1;
+}
+
+#endif /* not HAVE_CHSIZE */
+#endif /* not F_FREESP */
+#endif /* not F_CHSIZE */
Index: /indexers/branches/3.03a/mgpp/lib/getopt_old.c
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/getopt_old.c	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/getopt_old.c	(revision 14757)
@@ -0,0 +1,748 @@
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+   before changing it!
+
+   Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+   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 program; if not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+
+#if !__STDC__ && !defined(const) && IN_GCC
+#define const
+#endif
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.  */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef	__GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+   contain conflicting prototypes for getopt.  */
+#include <stdlib.h>
+#endif /* GNU C library.  */
+
+/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
+   long-named option.  Because this is not POSIX.2 compliant, it is
+   being phased out.  */
+/* #define GETOPT_COMPAT */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable POSIXLY_CORRECT disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+/* jrm21 - GSDL: getopt.h -> getopt_old.h */
+#include "getopt_old.h"
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg = 0;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* XXX 1003.2 says this must be 1 before any call.  */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   If the caller did not specify anything,
+   the default is REQUIRE_ORDER if the environment variable
+   POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+   REQUIRE_ORDER means don't recognize them as options;
+   stop option processing when the first non-option is seen.
+   This is what Unix does.
+   This mode of operation is selected by either setting the environment
+   variable POSIXLY_CORRECT, or using `+' as the first character
+   of the list of option characters.
+
+   PERMUTE is the default.  We permute the contents of ARGV as we scan,
+   so that eventually all the non-options are at the end.  This allows options
+   to be given in any order, even with programs that were not written to
+   expect this.
+
+   RETURN_IN_ORDER is an option available to programs that were written
+   to expect options and other ARGV-elements in any order and that care about
+   the ordering of the two.  We describe each non-option ARGV-element
+   as if it were the argument of an option with character code 1.
+   Using `-' as the first character of the list of option characters
+   selects this mode of operation.
+
+   The special argument `--' forces an end of option-scanning regardless
+   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
+
+static enum
+  {
+    REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+  }
+ordering;
+
+
+#ifdef	__GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+   because there are many ways it can cause trouble.
+   On some systems, it contains special magic macros that don't work
+   in GCC.  */
+#include <string.h>
+#define	my_index	strchr
+#else
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+     const char *str;
+     int chr;
+{
+  while (*str)
+    {
+      if (*str == chr)
+	return (char *) str;
+      str++;
+    }
+  return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+   If not using GCC, it is ok not to declare it.  */
+#ifdef __GNUC__
+#ifdef IN_GCC
+#include "gstddef.h"
+#else
+#include <stddef.h>
+#endif
+extern size_t strlen (const char *);
+#endif
+
+#endif /* GNU C library.  */
+
+
+/* Handle permutation of arguments.  */
+
+/* Describe the part of ARGV that contains non-options that have
+   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+   `last_nonopt' is the index after the last of them.  */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+static void
+exchange (argv)
+     char **argv;
+{
+  int bottom = first_nonopt;
+  int middle = last_nonopt;
+  int top = optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+	{
+	  /* Bottom segment is the short one.  */
+	  int len = middle - bottom;
+	  register int i;
+
+	  /* Swap it with the top part of the top segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[top - (middle - bottom) + i];
+	      argv[top - (middle - bottom) + i] = tem;
+	    }
+	  /* Exclude the moved bottom segment from further swapping.  */
+	  top -= len;
+	}
+      else
+	{
+	  /* Top segment is the short one.  */
+	  int len = top - middle;
+	  register int i;
+
+	  /* Swap it with the bottom part of the bottom segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[middle + i];
+	      argv[middle + i] = tem;
+	    }
+	  /* Exclude the moved top segment from further swapping.  */
+	  bottom += len;
+	}
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  first_nonopt += (optind - last_nonopt);
+  last_nonopt = optind;
+}
+
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns `EOF'.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.  */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+     const struct option *longopts;
+     int *longind;
+     int long_only;
+{
+  int option_index;
+
+  optarg = 0;
+
+  /* Initialize the internal data when the first call is made.
+     Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  if (optind == 0)
+    {
+      first_nonopt = last_nonopt = optind = 1;
+
+      nextchar = NULL;
+
+      /* Determine how to handle the ordering of options and nonoptions.  */
+
+      if (optstring[0] == '-')
+	{
+	  ordering = RETURN_IN_ORDER;
+	  ++optstring;
+	}
+      else if (optstring[0] == '+')
+	{
+	  ordering = REQUIRE_ORDER;
+	  ++optstring;
+	}
+      else if (getenv ("POSIXLY_CORRECT") != NULL)
+	ordering = REQUIRE_ORDER;
+      else
+	ordering = PERMUTE;
+    }
+
+  if (nextchar == NULL || *nextchar == '\0')
+    {
+      if (ordering == PERMUTE)
+	{
+	  /* If we have just processed some options following some non-options,
+	     exchange them so that the options come first.  */
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (last_nonopt != optind)
+	    first_nonopt = optind;
+
+	  /* Now skip any additional non-options
+	     and extend the range of non-options previously skipped.  */
+
+	  while (optind < argc
+		 && (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+		 && (longopts == NULL
+		     || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+	    )
+	    optind++;
+	  last_nonopt = optind;
+	}
+
+      /* Special ARGV-element `--' means premature end of options.
+         Skip it like a null option,
+         then exchange with previous non-options as if it were an option,
+         then skip everything else like a non-option.  */
+
+      if (optind != argc && !strcmp (argv[optind], "--"))
+	{
+	  optind++;
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (first_nonopt == last_nonopt)
+	    first_nonopt = optind;
+	  last_nonopt = argc;
+
+	  optind = argc;
+	}
+
+      /* If we have done all the ARGV-elements, stop the scan
+         and back over any non-options that we skipped and permuted.  */
+
+      if (optind == argc)
+	{
+	  /* Set the next-arg-index to point at the non-options
+	     that we previously skipped, so the caller will digest them.  */
+	  if (first_nonopt != last_nonopt)
+	    optind = first_nonopt;
+	  return EOF;
+	}
+
+      /* If we have come to a non-option and did not permute it,
+         either stop the scan or describe it to the caller and pass it by.  */
+
+      if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+	  && (longopts == NULL
+	      || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+	)
+	{
+	  if (ordering == REQUIRE_ORDER)
+	    return EOF;
+	  optarg = argv[optind++];
+	  return 1;
+	}
+
+      /* We have found another option-ARGV-element.
+         Start decoding its characters.  */
+
+      nextchar = (argv[optind] + 1
+		  + (longopts != NULL && argv[optind][1] == '-'));
+    }
+
+  if (longopts != NULL
+      && ((argv[optind][0] == '-'
+	   && (argv[optind][1] == '-' || long_only))
+#ifdef GETOPT_COMPAT
+	  || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+      ))
+    {
+      const struct option *p;
+      char *s = nextchar;
+      int exact = 0;
+      int ambig = 0;
+      const struct option *pfound = NULL;
+      int indfound;
+
+      while (*s && *s != '=')
+	s++;
+
+      /* Test all options for either exact match or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name;
+	   p++, option_index++)
+	if (!strncmp (p->name, nextchar, s - nextchar))
+	  {
+	    if (s - nextchar == strlen (p->name))
+	      {
+		/* Exact match found.  */
+		pfound = p;
+		indfound = option_index;
+		exact = 1;
+		break;
+	      }
+	    else if (pfound == NULL)
+	      {
+		/* First nonexact match found.  */
+		pfound = p;
+		indfound = option_index;
+	      }
+	    else
+	      /* Second nonexact match found.  */
+	      ambig = 1;
+	  }
+
+      if (ambig && !exact)
+	{
+	  if (opterr)
+	    fprintf (stderr, "%s: option `%s' is ambiguous\n",
+		     argv[0], argv[optind]);
+	  nextchar += strlen (nextchar);
+	  optind++;
+	  return '?';
+	}
+
+      if (pfound != NULL)
+	{
+	  option_index = indfound;
+	  optind++;
+	  if (*s)
+	    {
+	      /* Don't test has_arg with >, because some C compilers don't
+	         allow it to be used on enums.  */
+	      if (pfound->has_arg)
+		optarg = s + 1;
+	      else
+		{
+		  if (opterr)
+		    {
+		      if (argv[optind - 1][1] == '-')
+			/* --option */
+			fprintf (stderr,
+			    "%s: option `--%s' doesn't allow an argument\n",
+				 argv[0], pfound->name);
+		      else
+			/* +option or -option */
+			fprintf (stderr,
+			    "%s: option `%c%s' doesn't allow an argument\n",
+				 argv[0], argv[optind - 1][0], pfound->name);
+		    }
+		  nextchar += strlen (nextchar);
+		  return '?';
+		}
+	    }
+	  else if (pfound->has_arg == 1)
+	    {
+	      if (optind < argc)
+		optarg = argv[optind++];
+	      else
+		{
+		  if (opterr)
+		    fprintf (stderr, "%s: option `%s' requires an argument\n",
+			     argv[0], argv[optind - 1]);
+		  nextchar += strlen (nextchar);
+		  return optstring[0] == ':' ? ':' : '?';
+		}
+	    }
+	  nextchar += strlen (nextchar);
+	  if (longind != NULL)
+	    *longind = option_index;
+	  if (pfound->flag)
+	    {
+	      *(pfound->flag) = pfound->val;
+	      return 0;
+	    }
+	  return pfound->val;
+	}
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+         or the option starts with '--' or is not a valid short
+         option, then it's an error.
+         Otherwise interpret it as a short option.  */
+      if (!long_only || argv[optind][1] == '-'
+#ifdef GETOPT_COMPAT
+	  || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+	  || my_index (optstring, *nextchar) == NULL)
+	{
+	  if (opterr)
+	    {
+	      if (argv[optind][1] == '-')
+		/* --option */
+		fprintf (stderr, "%s: unrecognized option `--%s'\n",
+			 argv[0], nextchar);
+	      else
+		/* +option or -option */
+		fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+			 argv[0], argv[optind][0], nextchar);
+	    }
+	  nextchar = (char *) "";
+	  optind++;
+	  return '?';
+	}
+    }
+
+  /* Look at and handle the next option-character.  */
+
+  {
+    char c = *nextchar++;
+    char *temp = my_index (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*nextchar == '\0')
+      ++optind;
+
+    if (temp == NULL || c == ':')
+      {
+	if (opterr)
+	  {
+#if 0
+	    if (c < 040 || c >= 0177)
+	      fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
+		       argv[0], c);
+	    else
+	      fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
+#else
+	    /* 1003.2 specifies the format of this message.  */
+	    fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+#endif
+	  }
+	optopt = c;
+	return '?';
+      }
+    if (temp[1] == ':')
+      {
+	if (temp[2] == ':')
+	  {
+	    /* This is an option that accepts an argument optionally.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		optind++;
+	      }
+	    else
+	      optarg = 0;
+	    nextchar = NULL;
+	  }
+	else
+	  {
+	    /* This is an option that requires an argument.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		/* If we end this ARGV-element by taking the rest as an arg,
+		   we must advance to the next element now.  */
+		optind++;
+	      }
+	    else if (optind == argc)
+	      {
+		if (opterr)
+		  {
+#if 0
+		    fprintf (stderr, "%s: option `-%c' requires an argument\n",
+			     argv[0], c);
+#else
+		    /* 1003.2 specifies the format of this message.  */
+		    fprintf (stderr, "%s: option requires an argument -- %c\n",
+			     argv[0], c);
+#endif
+		  }
+		optopt = c;
+		if (optstring[0] == ':')
+		  c = ':';
+		else
+		  c = '?';
+	      }
+	    else
+	      /* We already incremented `optind' once;
+	         increment it again when taking next ARGV-elt as argument.  */
+	      optarg = argv[optind++];
+	    nextchar = NULL;
+	  }
+      }
+    return c;
+  }
+}
+
+int
+getopt (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  return _getopt_internal (argc, argv, optstring,
+			   (const struct option *) 0,
+			   (int *) 0,
+			   0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__.  */
+
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == EOF)
+	break;
+
+      switch (c)
+	{
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
Index: /indexers/branches/3.03a/mgpp/lib/getopt_old.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/getopt_old.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/getopt_old.h	(revision 14757)
@@ -0,0 +1,134 @@
+/* Declarations for getopt.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993 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 program; if not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef HAVE_DECL_GETOPT
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef	__cplusplus
+extern "C"
+{
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+  extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+  extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+  extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+  extern int optopt;
+
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument          (or 0) if the option does not take an argument,
+   required_argument    (or 1) if the option requires an argument,
+   optional_argument    (or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+  struct option
+    {
+#if	__STDC__
+      const char *name;
+#else
+      char *name;
+#endif
+      /* has_arg can't be an enum because some compilers complain about
+         type mismatches in all the code that assumes it is an int.  */
+      int has_arg;
+      int *flag;
+      int val;
+    };
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+#define	no_argument		0
+#define required_argument	1
+#define optional_argument	2
+
+#if __STDC__
+#if defined(__GNU_LIBRARY__)
+/* Many other libraries have conflicting prototypes for getopt, with
+   differences in the consts, in stdlib.h.  To avoid compilation
+   errors, only prototype getopt for the GNU C library.  */
+  extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else				/* not __GNU_LIBRARY__ */
+  int getopt (int, char * const *, const char *);
+#endif				/* not __GNU_LIBRARY__ */
+  extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+			  const struct option *longopts, int *longind);
+  extern int getopt_long_only (int argc, char *const *argv,
+			       const char *shortopts,
+			       const struct option *longopts, int *longind);
+
+/* Internal only.  Users should not call this directly.  */
+  extern int _getopt_internal (int argc, char *const *argv,
+			       const char *shortopts,
+			       const struct option *longopts, int *longind,
+			       int long_only);
+#else				/* not __STDC__ */
+  extern int getopt ();
+  extern int getopt_long ();
+  extern int getopt_long_only ();
+
+  extern int _getopt_internal ();
+#endif				/* not __STDC__ */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif				/* _GETOPT_H */
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/getpagesize.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/getpagesize.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/getpagesize.h	(revision 14757)
@@ -0,0 +1,38 @@
+/* Emulate getpagesize on systems that lack it.  */
+
+#ifndef HAVE_GETPAGESIZE
+
+#ifdef VMS
+#define getpagesize() 512
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef _SC_PAGESIZE
+#define getpagesize() sysconf(_SC_PAGESIZE)
+#else
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifndef __WIN32__
+#include <sys/param.h>
+#endif
+
+#ifdef EXEC_PAGESIZE
+#define getpagesize() EXEC_PAGESIZE
+#else
+#ifdef NBPG
+#define getpagesize() NBPG * CLSIZE
+#ifndef CLSIZE
+#define CLSIZE 1
+#endif /* no CLSIZE */
+#else /* no NBPG */
+#ifdef NBPC
+#define getpagesize() NBPC
+#endif /* NBPC */
+#endif /* no NBPG */
+#endif /* no EXEC_PAGESIZE */
+#endif /* no _SC_PAGESIZE */
+
+#endif /* not HAVE_GETPAGESIZE */
Index: /indexers/branches/3.03a/mgpp/lib/gmalloc.c
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/gmalloc.c	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/gmalloc.c	(revision 14757)
@@ -0,0 +1,1318 @@
+/* DO NOT EDIT THIS FILE -- it is automagically generated.  -*- C -*- */
+
+#define _MALLOC_INTERNAL
+
+/* The malloc headers and source files from the C library follow here.  */
+
+/* Declarations for `malloc' and friends.
+   Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+		  Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef _MALLOC_H
+
+#define _MALLOC_H	1
+
+#ifdef _MALLOC_INTERNAL
+
+#ifdef	HAVE_CONFIG_H
+#include <sysfuncs.h>
+#endif
+
+#if	defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
+#include <string.h>
+#else
+#ifndef memset
+#define	memset(s, zero, n)	bzero ((s), (n))
+#endif
+#ifndef memcpy
+#define	memcpy(d, s, n)		bcopy ((s), (d), (n))
+#endif
+#endif
+
+#if	defined(__GNU_LIBRARY__) || __STDC__
+#include <limits.h>
+#else
+#define	CHAR_BIT	8
+#endif
+
+#ifdef	HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#endif	/* _MALLOC_INTERNAL.  */
+
+
+#ifdef	__cplusplus
+extern "C"
+{
+#endif
+
+#if defined (__cplusplus) || __STDC__
+#undef	__P
+#define	__P(args)	args
+#undef	__ptr_t
+#define	__ptr_t		void *
+#else /* Not C++ or ANSI C.  */
+#undef	__P
+#define	__P(args)	()
+#undef	const
+#define	const
+#undef	__ptr_t
+#define	__ptr_t		char *
+#endif /* C++ or ANSI C.  */
+
+#if	__STDC__
+#include <stddef.h>
+#else
+#undef	size_t
+#define	size_t		unsigned int
+#undef	ptrdiff_t
+#define	ptrdiff_t	int
+#endif
+
+#ifndef	NULL
+#define	NULL	0
+#endif
+
+
+/* Allocate SIZE bytes of memory.  */
+extern __ptr_t malloc __P ((size_t __size));
+/* Re-allocate the previously allocated block
+   in __ptr_t, making the new block SIZE bytes long.  */
+extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size));
+/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0.  */
+extern __ptr_t calloc __P ((size_t __nmemb, size_t __size));
+/* Free a block allocated by `malloc', `realloc' or `calloc'.  */
+extern void free __P ((__ptr_t __ptr));
+
+/* Allocate SIZE bytes allocated to ALIGNMENT bytes.  */
+extern __ptr_t memalign __P ((size_t __alignment, size_t __size));
+
+/* Allocate SIZE bytes on a page boundary.  */
+extern __ptr_t valloc __P ((size_t __size));
+
+
+#ifdef _MALLOC_INTERNAL
+
+/* The allocator divides the heap into blocks of fixed size; large
+   requests receive one or more whole blocks, and small requests
+   receive a fragment of a block.  Fragment sizes are powers of two,
+   and all fragments of a block are the same size.  When all the
+   fragments in a block have been freed, the block itself is freed.  */
+#define INT_BIT		(CHAR_BIT * sizeof(int))
+#define BLOCKLOG	(INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE	(1 << BLOCKLOG)
+#define BLOCKIFY(SIZE)	(((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* Determine the amount of memory spanned by the initial heap table
+   (not an absolute limit).  */
+#define HEAP		(INT_BIT > 16 ? 4194304 : 65536)
+
+/* Number of contiguous free blocks allowed to build up at the end of
+   memory before they will be returned to the system.  */
+#define FINAL_FREE_BLOCKS	8
+
+/* Data structure giving per-block information.  */
+typedef union
+  {
+    /* Heap information for a busy block.  */
+    struct
+      {
+	/* Zero for a large block, or positive giving the
+	   logarithm to the base two of the fragment size.  */
+	int type;
+	union
+	  {
+	    struct
+	      {
+		size_t nfree;	/* Free fragments in a fragmented block.  */
+		size_t first;	/* First free fragment of the block.  */
+	      } frag;
+	    /* Size (in blocks) of a large cluster.  */
+	    size_t size;
+	  } info;
+      } busy;
+    /* Heap information for a free block
+       (that may be the first of a free cluster).  */
+    struct
+      {
+	size_t size;		/* Size (in blocks) of a free cluster.  */
+	size_t next;		/* Index of next free cluster.  */
+	size_t prev;		/* Index of previous free cluster.  */
+      } free;
+  } malloc_info;
+
+/* Pointer to first block of the heap.  */
+extern char *_heapbase;
+
+/* Table indexed by block number giving per-block information.  */
+extern malloc_info *_heapinfo;
+
+/* Address to block number and vice versa.  */
+#define BLOCK(A)	(((char *) (A) - _heapbase) / BLOCKSIZE + 1)
+#define ADDRESS(B)	((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
+
+/* Current search index for the heap table.  */
+extern size_t _heapindex;
+
+/* Limit of valid info table indices.  */
+extern size_t _heaplimit;
+
+/* Doubly linked lists of free fragments.  */
+struct list
+  {
+    struct list *next;
+    struct list *prev;
+  };
+
+/* Free list headers for each fragment size.  */
+extern struct list _fraghead[];
+
+/* List of blocks allocated with `memalign' (or `valloc').  */
+struct alignlist
+  {
+    struct alignlist *next;
+    __ptr_t aligned;		/* The address that memaligned returned.  */
+    __ptr_t exact;		/* The address that malloc returned.  */
+  };
+extern struct alignlist *_aligned_blocks;
+
+/* Instrumentation.  */
+extern size_t _chunks_used;
+extern size_t _bytes_used;
+extern size_t _chunks_free;
+extern size_t _bytes_free;
+
+/* Internal version of `free' used in `morecore' (malloc.c). */
+extern void _free_internal __P ((__ptr_t __ptr));
+
+#endif /* _MALLOC_INTERNAL.  */
+
+/* Underlying allocation function; successive calls should
+   return contiguous pieces of memory.  */
+extern __ptr_t (*__morecore) __P ((ptrdiff_t __size));
+
+/* Default value of `__morecore'.  */
+extern __ptr_t __default_morecore __P ((ptrdiff_t __size));
+
+/* If not NULL, this function is called after each time
+   `__morecore' is called to increase the data size.  */
+extern void (*__after_morecore_hook) __P ((void));
+
+/* Nonzero if `malloc' has been called and done its initialization.  */
+extern int __malloc_initialized;
+
+/* Hooks for debugging versions.  */
+extern void (*__free_hook) __P ((__ptr_t __ptr));
+extern __ptr_t (*__malloc_hook) __P ((size_t __size));
+extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
+
+/* Return values for `mprobe': these are the kinds of inconsistencies that
+   `mcheck' enables detection of.  */
+enum mcheck_status
+  {
+    MCHECK_DISABLED = -1,	/* Consistency checking is not turned on.  */
+    MCHECK_OK,			/* Block is fine.  */
+    MCHECK_FREE,		/* Block freed twice.  */
+    MCHECK_HEAD,		/* Memory before the block was clobbered.  */
+    MCHECK_TAIL			/* Memory after the block was clobbered.  */
+  };
+
+/* Activate a standard collection of debugging hooks.  This must be called
+   before `malloc' is ever called.  ABORTFUNC is called with an error code
+   (see enum above) when an inconsistency is detected.  If ABORTFUNC is
+   null, the standard function prints on stderr and then calls `abort'.  */
+extern int mcheck __P ((void (*__abortfunc) __P ((enum mcheck_status))));
+
+/* Check for aberrations in a particular malloc'd block.  You must have
+   called `mcheck' already.  These are the same checks that `mcheck' does
+   when you free or reallocate a block.  */
+extern enum mcheck_status mprobe __P ((__ptr_t __ptr));
+
+/* Activate a standard collection of tracing hooks.  */
+extern void mtrace __P ((void));
+
+/* Statistics available to the user.  */
+struct mstats
+  {
+    size_t bytes_total;		/* Total size of the heap. */
+    size_t chunks_used;		/* Chunks allocated by the user. */
+    size_t bytes_used;		/* Byte total of user-allocated chunks. */
+    size_t chunks_free;		/* Chunks in the free list. */
+    size_t bytes_free;		/* Byte total of chunks in the free list. */
+  };
+
+/* Pick up the current statistics. */
+extern struct mstats mstats __P ((void));
+
+/* Call WARNFUN with a warning message when memory usage is high.  */
+extern void memory_warnings __P ((__ptr_t __start,
+				  void (*__warnfun) __P ((const char *))));
+
+
+/* Relocating allocator.  */
+
+/* Allocate SIZE bytes, and store the address in *HANDLEPTR.  */
+extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, size_t __size));
+
+/* Free the storage allocated in HANDLEPTR.  */
+extern void r_alloc_free __P ((__ptr_t *__handleptr));
+
+/* Adjust the block at HANDLEPTR to be SIZE bytes long.  */
+extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, size_t __size));
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* malloc.h  */
+/* Allocate memory on a page boundary.
+   Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#if defined (__GNU_LIBRARY__) || defined (_LIBC)
+#include <stddef.h>
+#include <sys/cdefs.h>
+extern size_t __getpagesize __P ((void));
+#else
+#include "getpagesize.h"
+#define	 __getpagesize()	getpagesize()
+#endif
+
+#ifndef	_MALLOC_INTERNAL
+#define	_MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+static size_t pagesize;
+
+__ptr_t
+valloc (size)
+     size_t size;
+{
+  if (pagesize == 0)
+    pagesize = __getpagesize ();
+
+  return memalign (pagesize, size);
+}
+/* Memory allocator `malloc'.
+   Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation
+		  Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* How to really get more memory.  */
+__ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore;
+
+/* Debugging hook for `malloc'.  */
+__ptr_t (*__malloc_hook) __P ((size_t __size));
+
+/* Pointer to the base of the first block.  */
+char *_heapbase;
+
+/* Block information table.  Allocated with align/__free (not malloc/free).  */
+malloc_info *_heapinfo;
+
+/* Number of info entries.  */
+static size_t heapsize;
+
+/* Search index in the info table.  */
+size_t _heapindex;
+
+/* Limit of valid info table indices.  */
+size_t _heaplimit;
+
+/* Free lists for each fragment size.  */
+struct list _fraghead[BLOCKLOG];
+
+/* Instrumentation.  */
+size_t _chunks_used;
+size_t _bytes_used;
+size_t _chunks_free;
+size_t _bytes_free;
+
+/* Are you experienced?  */
+int __malloc_initialized;
+
+void (*__after_morecore_hook) __P ((void));
+
+/* Aligned allocation.  */
+static __ptr_t align __P ((size_t));
+static __ptr_t
+align (size)
+     size_t size;
+{
+  __ptr_t result;
+  unsigned long int adj;
+
+  result = (*__morecore) (size);
+  adj = (unsigned long int) ((unsigned long int) ((char *) result -
+						  (char *) NULL)) % BLOCKSIZE;
+  if (adj != 0)
+    {
+      adj = BLOCKSIZE - adj;
+      (void) (*__morecore) (adj);
+      result = (char *) result + adj;
+    }
+
+  if (__after_morecore_hook)
+    (*__after_morecore_hook) ();
+
+  return result;
+}
+
+/* Set everything up and remember that we have.  */
+static int initialize __P ((void));
+static int
+initialize ()
+{
+  heapsize = HEAP / BLOCKSIZE;
+  _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));
+  if (_heapinfo == NULL)
+    return 0;
+  memset (_heapinfo, 0, heapsize * sizeof (malloc_info));
+  _heapinfo[0].free.size = 0;
+  _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
+  _heapindex = 0;
+  _heapbase = (char *) _heapinfo;
+
+  /* Account for the _heapinfo block itself in the statistics.  */
+  _bytes_used = heapsize * sizeof (malloc_info);
+  _chunks_used = 1;
+
+  __malloc_initialized = 1;
+  return 1;
+}
+
+/* Get neatly aligned memory, initializing or
+   growing the heap info table as necessary. */
+static __ptr_t morecore __P ((size_t));
+static __ptr_t
+morecore (size)
+     size_t size;
+{
+  __ptr_t result;
+  malloc_info *newinfo, *oldinfo;
+  size_t newsize;
+
+  result = align (size);
+  if (result == NULL)
+    return NULL;
+
+  /* Check if we need to grow the info table.  */
+  if ((size_t) BLOCK ((char *) result + size) > heapsize)
+    {
+      newsize = heapsize;
+      while ((size_t) BLOCK ((char *) result + size) > newsize)
+	newsize *= 2;
+      newinfo = (malloc_info *) align (newsize * sizeof (malloc_info));
+      if (newinfo == NULL)
+	{
+	  (*__morecore) (-size);
+	  return NULL;
+	}
+      memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info));
+      memset (&newinfo[heapsize], 0,
+	      (newsize - heapsize) * sizeof (malloc_info));
+      oldinfo = _heapinfo;
+      newinfo[BLOCK (oldinfo)].busy.type = 0;
+      newinfo[BLOCK (oldinfo)].busy.info.size
+	= BLOCKIFY (heapsize * sizeof (malloc_info));
+      _heapinfo = newinfo;
+      /* Account for the _heapinfo block itself in the statistics.  */
+      _bytes_used += newsize * sizeof (malloc_info);
+      ++_chunks_used;
+      _free_internal (oldinfo);
+      heapsize = newsize;
+    }
+
+  _heaplimit = BLOCK ((char *) result + size);
+  return result;
+}
+
+/* Allocate memory from the heap.  */
+__ptr_t
+malloc (size)
+     size_t size;
+{
+  __ptr_t result;
+  size_t block, blocks, lastblocks, start;
+  register size_t i;
+  struct list *next;
+
+  /* ANSI C allows `malloc (0)' to either return NULL, or to return a
+     valid address you can realloc and free (though not dereference).
+
+     It turns out that some extant code (sunrpc, at least Ultrix's version)
+     expects `malloc (0)' to return non-NULL and breaks otherwise.
+     Be compatible.  */
+
+#if	0
+  if (size == 0)
+    return NULL;
+#endif
+
+  if (__malloc_hook != NULL)
+    return (*__malloc_hook) (size);
+
+  if (!__malloc_initialized)
+    if (!initialize ())
+      return NULL;
+
+  if (size < sizeof (struct list))
+      size = sizeof (struct list);
+
+#ifdef SUNOS_LOCALTIME_BUG
+  if (size < 16)
+    size = 16;
+#endif
+
+  /* Determine the allocation policy based on the request size.  */
+  if (size <= BLOCKSIZE / 2)
+    {
+      /* Small allocation to receive a fragment of a block.
+	 Determine the logarithm to base two of the fragment size. */
+      register size_t log = 1;
+      --size;
+      while ((size /= 2) != 0)
+	++log;
+
+      /* Look in the fragment lists for a
+	 free fragment of the desired size. */
+      next = _fraghead[log].next;
+      if (next != NULL)
+	{
+	  /* There are free fragments of this size.
+	     Pop a fragment out of the fragment list and return it.
+	     Update the block's nfree and first counters. */
+	  result = (__ptr_t) next;
+	  next->prev->next = next->next;
+	  if (next->next != NULL)
+	    next->next->prev = next->prev;
+	  block = BLOCK (result);
+	  if (--_heapinfo[block].busy.info.frag.nfree != 0)
+	    _heapinfo[block].busy.info.frag.first = (unsigned long int)
+	      ((unsigned long int) ((char *) next->next - (char *) NULL)
+	       % BLOCKSIZE) >> log;
+
+	  /* Update the statistics.  */
+	  ++_chunks_used;
+	  _bytes_used += 1 << log;
+	  --_chunks_free;
+	  _bytes_free -= 1 << log;
+	}
+      else
+	{
+	  /* No free fragments of the desired size, so get a new block
+	     and break it into fragments, returning the first.  */
+	  result = malloc (BLOCKSIZE);
+	  if (result == NULL)
+	    return NULL;
+
+	  /* Link all fragments but the first into the free list.  */
+	  for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i)
+	    {
+	      next = (struct list *) ((char *) result + (i << log));
+	      next->next = _fraghead[log].next;
+	      next->prev = &_fraghead[log];
+	      next->prev->next = next;
+	      if (next->next != NULL)
+		next->next->prev = next;
+	    }
+
+	  /* Initialize the nfree and first counters for this block.  */
+	  block = BLOCK (result);
+	  _heapinfo[block].busy.type = log;
+	  _heapinfo[block].busy.info.frag.nfree = i - 1;
+	  _heapinfo[block].busy.info.frag.first = i - 1;
+
+	  _chunks_free += (BLOCKSIZE >> log) - 1;
+	  _bytes_free += BLOCKSIZE - (1 << log);
+	  _bytes_used -= BLOCKSIZE - (1 << log);
+	}
+    }
+  else
+    {
+      /* Large allocation to receive one or more blocks.
+	 Search the free list in a circle starting at the last place visited.
+	 If we loop completely around without finding a large enough
+	 space we will have to get more memory from the system.  */
+      blocks = BLOCKIFY (size);
+      start = block = _heapindex;
+      while (_heapinfo[block].free.size < blocks)
+	{
+	  block = _heapinfo[block].free.next;
+	  if (block == start)
+	    {
+	      /* Need to get more from the system.  Check to see if
+		 the new core will be contiguous with the final free
+		 block; if so we don't need to get as much.  */
+	      block = _heapinfo[0].free.prev;
+	      lastblocks = _heapinfo[block].free.size;
+	      if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
+		  (*__morecore) (0) == ADDRESS (block + lastblocks) &&
+		  (morecore ((blocks - lastblocks) * BLOCKSIZE)) != NULL)
+		{
+ 		  /* Which block we are extending (the `final free
+ 		     block' referred to above) might have changed, if
+ 		     it got combined with a freed info table.  */
+ 		  block = _heapinfo[0].free.prev;
+  		  _heapinfo[block].free.size += (blocks - lastblocks);
+		  _bytes_free += (blocks - lastblocks) * BLOCKSIZE;
+		  continue;
+		}
+	      result = morecore (blocks * BLOCKSIZE);
+	      if (result == NULL)
+		return NULL;
+	      block = BLOCK (result);
+	      _heapinfo[block].busy.type = 0;
+	      _heapinfo[block].busy.info.size = blocks;
+	      ++_chunks_used;
+	      _bytes_used += blocks * BLOCKSIZE;
+	      return result;
+	    }
+	}
+
+      /* At this point we have found a suitable free list entry.
+	 Figure out how to remove what we need from the list. */
+      result = ADDRESS (block);
+      if (_heapinfo[block].free.size > blocks)
+	{
+	  /* The block we found has a bit left over,
+	     so relink the tail end back into the free list. */
+	  _heapinfo[block + blocks].free.size
+	    = _heapinfo[block].free.size - blocks;
+	  _heapinfo[block + blocks].free.next
+	    = _heapinfo[block].free.next;
+	  _heapinfo[block + blocks].free.prev
+	    = _heapinfo[block].free.prev;
+	  _heapinfo[_heapinfo[block].free.prev].free.next
+	    = _heapinfo[_heapinfo[block].free.next].free.prev
+	    = _heapindex = block + blocks;
+	}
+      else
+	{
+	  /* The block exactly matches our requirements,
+	     so just remove it from the list. */
+	  _heapinfo[_heapinfo[block].free.next].free.prev
+	    = _heapinfo[block].free.prev;
+	  _heapinfo[_heapinfo[block].free.prev].free.next
+	    = _heapindex = _heapinfo[block].free.next;
+	  --_chunks_free;
+	}
+
+      _heapinfo[block].busy.type = 0;
+      _heapinfo[block].busy.info.size = blocks;
+      ++_chunks_used;
+      _bytes_used += blocks * BLOCKSIZE;
+      _bytes_free -= blocks * BLOCKSIZE;
+    }
+
+  return result;
+}
+
+
+#ifndef _LIBC
+
+/* On some ANSI C systems, some libc functions call _malloc, _free
+   and _realloc.  Make them use the GNU functions.  */
+
+__ptr_t
+_malloc (size)
+     size_t size;
+{
+  return malloc (size);
+}
+
+void
+_free (ptr)
+     __ptr_t ptr;
+{
+  free (ptr);
+}
+
+__ptr_t
+_realloc (ptr, size)
+     __ptr_t ptr;
+     size_t size;
+{
+  return realloc (ptr, size);
+}
+
+#endif
+/* Free a block of memory allocated by `malloc'.
+   Copyright 1990, 1991, 1992 Free Software Foundation
+		  Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* Debugging hook for free.  */
+void (*__free_hook) __P ((__ptr_t __ptr));
+
+/* List of blocks allocated by memalign.  */
+struct alignlist *_aligned_blocks = NULL;
+
+/* Return memory to the heap.
+   Like `free' but don't call a __free_hook if there is one.  */
+void
+_free_internal (ptr)
+     __ptr_t ptr;
+{
+  int type;
+  size_t block, blocks;
+  register size_t i;
+  struct list *prev, *next;
+
+  block = BLOCK (ptr);
+
+  type = _heapinfo[block].busy.type;
+  switch (type)
+    {
+    case 0:
+      /* Get as many statistics as early as we can.  */
+      --_chunks_used;
+      _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
+      _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
+
+      /* Find the free cluster previous to this one in the free list.
+	 Start searching at the last block referenced; this may benefit
+	 programs with locality of allocation.  */
+      i = _heapindex;
+      if (i > block)
+	while (i > block)
+	  i = _heapinfo[i].free.prev;
+      else
+	{
+	  do
+	    i = _heapinfo[i].free.next;
+	  while (i > 0 && i < block);
+	  i = _heapinfo[i].free.prev;
+	}
+
+      /* Determine how to link this block into the free list.  */
+      if (block == i + _heapinfo[i].free.size)
+	{
+	  /* Coalesce this block with its predecessor.  */
+	  _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
+	  block = i;
+	}
+      else
+	{
+	  /* Really link this block back into the free list.  */
+	  _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
+	  _heapinfo[block].free.next = _heapinfo[i].free.next;
+	  _heapinfo[block].free.prev = i;
+	  _heapinfo[i].free.next = block;
+	  _heapinfo[_heapinfo[block].free.next].free.prev = block;
+	  ++_chunks_free;
+	}
+
+      /* Now that the block is linked in, see if we can coalesce it
+	 with its successor (by deleting its successor from the list
+	 and adding in its size).  */
+      if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)
+	{
+	  _heapinfo[block].free.size
+	    += _heapinfo[_heapinfo[block].free.next].free.size;
+	  _heapinfo[block].free.next
+	    = _heapinfo[_heapinfo[block].free.next].free.next;
+	  _heapinfo[_heapinfo[block].free.next].free.prev = block;
+	  --_chunks_free;
+	}
+
+      /* Now see if we can return stuff to the system.  */
+      blocks = _heapinfo[block].free.size;
+      if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
+	  && (*__morecore) (0) == ADDRESS (block + blocks))
+	{
+	  register size_t bytes = blocks * BLOCKSIZE;
+	  _heaplimit -= blocks;
+	  (*__morecore) (-bytes);
+	  _heapinfo[_heapinfo[block].free.prev].free.next
+	    = _heapinfo[block].free.next;
+	  _heapinfo[_heapinfo[block].free.next].free.prev
+	    = _heapinfo[block].free.prev;
+	  block = _heapinfo[block].free.prev;
+	  --_chunks_free;
+	  _bytes_free -= bytes;
+	}
+
+      /* Set the next search to begin at this block.  */
+      _heapindex = block;
+      break;
+
+    default:
+      /* Do some of the statistics.  */
+      --_chunks_used;
+      _bytes_used -= 1 << type;
+      ++_chunks_free;
+      _bytes_free += 1 << type;
+
+      /* Get the address of the first free fragment in this block.  */
+      prev = (struct list *) ((char *) ADDRESS (block) +
+			   (_heapinfo[block].busy.info.frag.first << type));
+
+      if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
+	{
+	  /* If all fragments of this block are free, remove them
+	     from the fragment list and free the whole block.  */
+	  next = prev;
+	  for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
+	    next = next->next;
+	  prev->prev->next = next;
+	  if (next != NULL)
+	    next->prev = prev->prev;
+	  _heapinfo[block].busy.type = 0;
+	  _heapinfo[block].busy.info.size = 1;
+
+	  /* Keep the statistics accurate.  */
+	  ++_chunks_used;
+	  _bytes_used += BLOCKSIZE;
+	  _chunks_free -= BLOCKSIZE >> type;
+	  _bytes_free -= BLOCKSIZE;
+
+	  free (ADDRESS (block));
+	}
+      else if (_heapinfo[block].busy.info.frag.nfree != 0)
+	{
+	  /* If some fragments of this block are free, link this
+	     fragment into the fragment list after the first free
+	     fragment of this block. */
+	  next = (struct list *) ptr;
+	  next->next = prev->next;
+	  next->prev = prev;
+	  prev->next = next;
+	  if (next->next != NULL)
+	    next->next->prev = next;
+	  ++_heapinfo[block].busy.info.frag.nfree;
+	}
+      else
+	{
+	  /* No fragments of this block are free, so link this
+	     fragment into the fragment list and announce that
+	     it is the first free fragment of this block. */
+	  prev = (struct list *) ptr;
+	  _heapinfo[block].busy.info.frag.nfree = 1;
+	  _heapinfo[block].busy.info.frag.first = (unsigned long int)
+	    ((unsigned long int) ((char *) ptr - (char *) NULL)
+	     % BLOCKSIZE >> type);
+	  prev->next = _fraghead[type].next;
+	  prev->prev = &_fraghead[type];
+	  prev->prev->next = prev;
+	  if (prev->next != NULL)
+	    prev->next->prev = prev;
+	}
+      break;
+    }
+}
+
+/* Return memory to the heap.  */
+void
+free (ptr)
+     __ptr_t ptr;
+{
+  register struct alignlist *l;
+
+  if (ptr == NULL)
+    return;
+
+  for (l = _aligned_blocks; l != NULL; l = l->next)
+    if (l->aligned == ptr)
+      {
+	l->aligned = NULL;	/* Mark the slot in the list as free.  */
+	ptr = l->exact;
+	break;
+      }
+
+  if (__free_hook != NULL)
+    (*__free_hook) (ptr);
+  else
+    _free_internal (ptr);
+}
+/* Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#ifdef _LIBC
+
+#include <ansidecl.h>
+#include <gnu-stabs.h>
+
+#undef	cfree
+
+function_alias(cfree, free, void, (ptr),
+	       DEFUN(cfree, (ptr), PTR ptr))
+
+#else
+
+void
+cfree (ptr)
+     __ptr_t ptr;
+{
+  free (ptr);
+}
+
+#endif
+/* Change the size of a block allocated by `malloc'.
+   Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+		     Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#if  (defined (MEMMOVE_MISSING) || \
+      !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG))
+
+/* Snarfed directly from Emacs src/dispnew.c:
+   XXX Should use system bcopy if it handles overlap.  */
+#ifndef emacs
+
+/* Like bcopy except never gets confused by overlap.  */
+
+static void
+safe_bcopy (from, to, size)
+     char *from, *to;
+     int size;
+{
+  if (size <= 0 || from == to)
+    return;
+
+  /* If the source and destination don't overlap, then bcopy can
+     handle it.  If they do overlap, but the destination is lower in
+     memory than the source, we'll assume bcopy can handle that.  */
+  if (to < from || from + size <= to)
+    bcopy (from, to, size);
+
+  /* Otherwise, we'll copy from the end.  */
+  else
+    {
+      register char *endf = from + size;
+      register char *endt = to + size;
+
+      /* If TO - FROM is large, then we should break the copy into
+	 nonoverlapping chunks of TO - FROM bytes each.  However, if
+	 TO - FROM is small, then the bcopy function call overhead
+	 makes this not worth it.  The crossover point could be about
+	 anywhere.  Since I don't think the obvious copy loop is too
+	 bad, I'm trying to err in its favor.  */
+      if (to - from < 64)
+	{
+	  do
+	    *--endt = *--endf;
+	  while (endf != from);
+	}
+      else
+	{
+	  for (;;)
+	    {
+	      endt -= (to - from);
+	      endf -= (to - from);
+
+	      if (endt < to)
+		break;
+
+	      bcopy (endf, endt, to - from);
+	    }
+
+	  /* If SIZE wasn't a multiple of TO - FROM, there will be a
+	     little left over.  The amount left over is
+	     (endt + (to - from)) - to, which is endt - from.  */
+	  bcopy (from, to, endt - from);
+	}
+    }
+}     
+#endif	/* Not emacs.  */
+
+#define memmove(to, from, size) safe_bcopy ((from), (to), (size))
+
+#endif
+
+
+#define min(A, B) ((A) < (B) ? (A) : (B))
+
+/* Debugging hook for realloc.  */
+__ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
+
+/* Resize the given region to the new size, returning a pointer
+   to the (possibly moved) region.  This is optimized for speed;
+   some benchmarks seem to indicate that greater compactness is
+   achieved by unconditionally allocating and copying to a
+   new region.  This module has incestuous knowledge of the
+   internals of both free and malloc. */
+__ptr_t
+realloc (ptr, size)
+     __ptr_t ptr;
+     size_t size;
+{
+  __ptr_t result;
+  int type;
+  size_t block, blocks, oldlimit;
+
+  if (size == 0)
+    {
+      free (ptr);
+      return malloc (0);
+    }
+  else if (ptr == NULL)
+    return malloc (size);
+
+  if (__realloc_hook != NULL)
+    return (*__realloc_hook) (ptr, size);
+
+  block = BLOCK (ptr);
+
+  type = _heapinfo[block].busy.type;
+  switch (type)
+    {
+    case 0:
+      /* Maybe reallocate a large block to a small fragment.  */
+      if (size <= BLOCKSIZE / 2)
+	{
+	  result = malloc (size);
+	  if (result != NULL)
+	    {
+	      memcpy (result, ptr, size);
+	      _free_internal (ptr);
+	      return result;
+	    }
+	}
+
+      /* The new size is a large allocation as well;
+	 see if we can hold it in place. */
+      blocks = BLOCKIFY (size);
+      if (blocks < _heapinfo[block].busy.info.size)
+	{
+	  /* The new size is smaller; return
+	     excess memory to the free list. */
+	  _heapinfo[block + blocks].busy.type = 0;
+	  _heapinfo[block + blocks].busy.info.size
+	    = _heapinfo[block].busy.info.size - blocks;
+	  _heapinfo[block].busy.info.size = blocks;
+	  /* We have just created a new chunk by splitting a chunk in two.
+	     Now we will free this chunk; increment the statistics counter
+	     so it doesn't become wrong when _free_internal decrements it.  */
+	  ++_chunks_used;
+	  _free_internal (ADDRESS (block + blocks));
+	  result = ptr;
+	}
+      else if (blocks == _heapinfo[block].busy.info.size)
+	/* No size change necessary.  */
+	result = ptr;
+      else
+	{
+	  /* Won't fit, so allocate a new region that will.
+	     Free the old region first in case there is sufficient
+	     adjacent free space to grow without moving. */
+	  blocks = _heapinfo[block].busy.info.size;
+	  /* Prevent free from actually returning memory to the system.  */
+	  oldlimit = _heaplimit;
+	  _heaplimit = 0;
+	  _free_internal (ptr);
+	  _heaplimit = oldlimit;
+	  result = malloc (size);
+	  if (result == NULL)
+	    {
+	      /* Now we're really in trouble.  We have to unfree
+		 the thing we just freed.  Unfortunately it might
+		 have been coalesced with its neighbors.  */
+	      if (_heapindex == block)
+	        (void) malloc (blocks * BLOCKSIZE);
+	      else
+		{
+		  __ptr_t previous = malloc ((block - _heapindex) * BLOCKSIZE);
+		  (void) malloc (blocks * BLOCKSIZE);
+		  _free_internal (previous);
+		}
+	      return NULL;
+	    }
+	  if (ptr != result)
+	    memmove (result, ptr, blocks * BLOCKSIZE);
+	}
+      break;
+
+    default:
+      /* Old size is a fragment; type is logarithm
+	 to base two of the fragment size.  */
+      if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))
+	/* The new size is the same kind of fragment.  */
+	result = ptr;
+      else
+	{
+	  /* The new size is different; allocate a new space,
+	     and copy the lesser of the new size and the old. */
+	  result = malloc (size);
+	  if (result == NULL)
+	    return NULL;
+	  memcpy (result, ptr, min (size, (size_t) 1 << type));
+	  free (ptr);
+	}
+      break;
+    }
+
+  return result;
+}
+/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define	_MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* Allocate an array of NMEMB elements each SIZE bytes long.
+   The entire array is initialized to zeros.  */
+__ptr_t
+calloc (nmemb, size)
+     register size_t nmemb;
+     register size_t size;
+{
+  register __ptr_t result = malloc (nmemb * size);
+
+  if (result != NULL)
+    (void) memset (result, 0, nmemb * size);
+
+  return result;
+}
+/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library 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.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define	_MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#ifndef	__GNU_LIBRARY__
+#define	__sbrk	sbrk
+#endif
+
+#ifdef __GNU_LIBRARY__
+/* It is best not to declare this and cast its result on foreign operating
+   systems with potentially hostile include files.  */
+extern __ptr_t __sbrk __P ((int increment));
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Allocate INCREMENT more bytes of data space,
+   and return the start of data space, or NULL on errors.
+   If INCREMENT is negative, shrink data space.  */
+__ptr_t
+__default_morecore (increment)
+     ptrdiff_t increment;
+{
+  __ptr_t result = (__ptr_t) __sbrk ((int) increment);
+  if (result == (__ptr_t) -1)
+    return NULL;
+  return result;
+}
+/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef	_MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+__ptr_t
+memalign (alignment, size)
+     size_t alignment;
+     size_t size;
+{
+  __ptr_t result;
+  unsigned long int adj;
+
+  size = ((size + alignment - 1) / alignment) * alignment;
+
+  result = malloc (size);
+  if (result == NULL)
+    return NULL;
+  adj = (unsigned long int) ((unsigned long int) ((char *) result -
+						  (char *) NULL)) % alignment;
+  if (adj != 0)
+    {
+      struct alignlist *l;
+      for (l = _aligned_blocks; l != NULL; l = l->next)
+	if (l->aligned == NULL)
+	  /* This slot is free.  Use it.  */
+	  break;
+      if (l == NULL)
+	{
+	  l = (struct alignlist *) malloc (sizeof (struct alignlist));
+	  if (l == NULL)
+	    {
+	      free (result);
+	      return NULL;
+	    }
+	  l->next = _aligned_blocks;
+	  _aligned_blocks = l;
+	}
+      l->exact = result;
+      result = l->aligned = (char *) result + alignment - adj;
+    }
+
+  return result;
+}
Index: /indexers/branches/3.03a/mgpp/lib/huffman.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/huffman.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/huffman.cpp	(revision 14757)
@@ -0,0 +1,385 @@
+/**************************************************************************
+ *
+ * huffman.c -- Huffman coding functions
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "huffman.h"
+#include "messages.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+/* ->data on success,  
+   NULL on error 
+ */
+huff_data *
+Generate_Huffman_Data (int num, long *freqs, huff_data * data,
+		       u_long * mem)
+{
+  int HNum, i, count;
+  unsigned long *heap;
+  huff_data *hd = data;
+  if (!hd)
+    {
+      if (!(hd = new huff_data))
+	goto error0;
+    }
+  if (!(heap = new unsigned long[num * 2]))
+    goto error1;
+  if (!(hd->clens = new char[num]))
+      goto error2;
+  hd->num_codes = num;
+  if (mem)
+    {
+      if (hd != data)
+	*mem += sizeof (huff_data);
+      *mem += num * sizeof (char);
+    }
+  memcpy (&heap[num], freqs, num * sizeof (*heap));
+  memset (heap, '\0', num * sizeof (*heap));
+
+  /* Initialise the pointers to the leaves */
+  for (count = i = 0; i < num; ++i)
+    if (heap[num + i])
+      heap[count++] = num + i;
+
+  /* Reorganise the pointers so that it is a heap */
+  HNum = count;
+  for (i = HNum / 2; i > 0; --i)
+    {
+      register int curr, child;
+      curr = i;
+      child = curr * 2;
+      while (child <= HNum)
+	{
+	  if (child < HNum && heap[heap[child]] < heap[heap[child - 1]])
+	    ++child;
+	  if (heap[heap[curr - 1]] > heap[heap[child - 1]])
+	    {
+	      register u_long temp;
+	      temp = heap[child - 1];
+	      heap[child - 1] = heap[curr - 1];
+	      heap[curr - 1] = temp;
+	      curr = child;
+	      child = 2 * curr;
+	    }
+	  else
+	    break;
+	}
+    }
+
+
+  /* Form the huffman tree */
+  while (HNum > 1)
+    {
+      int pos[2];
+
+      for (i = 0; i < 2; ++i)
+	{
+	  register int curr, child;
+	  pos[i] = heap[0];
+	  heap[0] = heap[--HNum];
+	  curr = 1;
+	  child = 2;
+	  while (child <= HNum)
+	    {
+	      if (child < HNum &&
+		  heap[heap[child]] < heap[heap[child - 1]])
+		++child;
+	      if (heap[heap[curr - 1]] > heap[heap[child - 1]])
+		{
+		  register int temp;
+		  temp = heap[child - 1];
+		  heap[child - 1] = heap[curr - 1];
+		  heap[curr - 1] = temp;
+		  curr = child;
+		  child = 2 * curr;
+		}
+	      else
+		break;
+	    }
+	}
+
+      heap[HNum + 1] = heap[pos[0]] + heap[pos[1]];
+      heap[pos[0]] = heap[pos[1]] = HNum + 1;
+
+      heap[HNum] = HNum + 1;
+
+      {
+	register int parent, curr;
+	++HNum;
+	curr = HNum;
+	parent = curr >> 1;
+	while (parent && heap[heap[parent - 1]] > heap[heap[curr - 1]])
+	  {
+	    register int temp;
+	    temp = heap[parent - 1];
+	    heap[parent - 1] = heap[curr - 1];
+	    heap[curr - 1] = temp;
+	    curr = parent;
+	    parent = curr >> 1;
+	  }
+      }
+    }
+
+
+  /* Calculate the code lens */
+  heap[0] = -1UL;
+  heap[1] = 0;
+  for (i = 2; i < num * 2; ++i)
+    heap[i] = heap[heap[i]] + 1;
+
+  /* zero the lencount's array */
+  memset (hd->lencount, '\0', sizeof (hd->lencount));
+  hd->maxcodelen = 0;
+  hd->mincodelen = 100;
+
+  /* Set the code length of each leaf in the huffman tree */
+  for (i = 0; i < num; ++i)
+    {
+      register u_long codelen = heap[i + num];
+      hd->clens[i] = (char) codelen;
+      if (!codelen)
+	continue;
+      if (codelen > hd->maxcodelen)
+	hd->maxcodelen = codelen;
+      if (codelen < hd->mincodelen)
+	hd->mincodelen = codelen;
+      ++hd->lencount[codelen];
+    }
+
+
+  if (hd->maxcodelen == 0 && hd->mincodelen == 100)
+    {
+      hd->num_codes = 0;
+    }
+  else
+    {
+      /* Calculate the current codes for each different code length */
+      hd->min_code[hd->maxcodelen] = 0;
+      for (i = hd->maxcodelen - 1; i>=0; --i)
+	hd->min_code[i] = (hd->min_code[i + 1] + hd->lencount[i + 1]) >> 1;
+    }
+  delete []heap;
+  return (hd);
+
+error2:
+  delete []heap;
+error1:
+  if (!data)
+    delete hd;
+error0:
+  return (NULL);
+
+}
+
+unsigned long *
+Generate_Huffman_Codes (huff_data * data, u_long * mem)
+{
+  int i;
+  unsigned long *codes;
+  unsigned long mc[MAX_HUFFCODE_LEN + 1];
+
+  if (!data)
+    return (NULL);
+  if (!(codes = new unsigned long[data->num_codes]))
+    return (NULL);
+  if (mem)
+    *mem += data->num_codes * sizeof (*codes);
+  memcpy (mc, data->min_code, sizeof (mc));
+  for (i = 0; i < data->num_codes; ++i)
+    if (data->clens[i])
+      codes[i] = mc[(int) (data->clens[i])]++;
+
+  return (codes);
+}
+
+
+unsigned long **
+Generate_Huffman_Vals (huff_data * data, u_long * mem)
+{
+  int i;
+  unsigned long *fcode[MAX_HUFFCODE_LEN + 1];
+  unsigned long **values;
+  unsigned long *vals;
+
+  if (!data)
+    return (NULL);
+  if (!(vals = new unsigned long[data->num_codes]))
+    return (NULL);
+  if (!(values = new unsigned long *[MAX_HUFFCODE_LEN + 1]))
+    {
+      delete []vals;
+      return (NULL);
+    }
+
+  memset (values, '\0', (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *));
+
+  if (mem)
+    *mem += data->num_codes * sizeof (*vals) +
+      (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *);
+
+  fcode[0] = values[0] = &vals[0];
+  for (i = 1; i <= data->maxcodelen; ++i)
+    fcode[i] = values[i] = &vals[(values[i - 1] - vals) + data->lencount[i - 1]];
+
+  for (i = 0; i < data->num_codes; ++i)
+    if (data->clens[i])
+      *fcode[(int) (data->clens[i])]++ = i;
+  return (values);
+}
+
+
+
+double 
+Calculate_Huffman_Size (int num, long *freqs, long *counts)
+{
+  double size = 0;
+  huff_data hd;
+  int i;
+  if (!Generate_Huffman_Data (num, freqs, &hd, NULL))
+    return -1;
+  for (i = 0; i < num; ++i)
+    size += counts[i] * hd.clens[i];
+  delete []hd.clens;
+  return size;
+}
+
+
+
+int 
+Write_Huffman_Data (FILE * f, huff_data * hd)
+{
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONSI(hd->num_codes);
+  HTONSI(hd->mincodelen);
+  HTONSI(hd->maxcodelen);
+
+  if (fwrite (&hd->num_codes, sizeof (hd->num_codes), 1, f) != 1)
+    return -1;
+
+  if (fwrite (&hd->mincodelen, sizeof (hd->mincodelen), 1, f) != 1)
+    return -1;
+
+  if (fwrite (&hd->maxcodelen, sizeof (hd->maxcodelen), 1, f) != 1)
+    return -1;
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHSI(hd->num_codes);
+  NTOHSI(hd->mincodelen);
+  NTOHSI(hd->maxcodelen);
+
+  if (hd->num_codes)
+    {
+      /* [RPAP - Jan 97: Endian Ordering] */
+      int i;
+      for (i = hd->mincodelen; i < hd->maxcodelen + 1; ++i)
+	HTONSI(hd->lencount[i]);
+      for (i = 0; i < hd->maxcodelen + 1; ++i)
+	HTONUL(hd->min_code[i]);
+
+      if (fwrite (hd->lencount + hd->mincodelen, sizeof (*hd->lencount),
+		  hd->maxcodelen - hd->mincodelen + 1, f) !=
+	  hd->maxcodelen - hd->mincodelen + 1)
+	return -1;
+
+      if (fwrite (hd->min_code, sizeof (*hd->min_code), hd->maxcodelen + 1, f) !=
+	  hd->maxcodelen + 1)
+	return -1;
+
+      if (fwrite (hd->clens, sizeof (*hd->clens), hd->num_codes, f) != hd->num_codes)
+	return -1;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (i = hd->mincodelen; i < hd->maxcodelen + 1; ++i)
+	NTOHSI(hd->lencount[i]);
+      for (i = 0; i < hd->maxcodelen + 1; ++i)
+	NTOHUL(hd->min_code[i]);
+    }
+  return 0;
+}
+
+
+
+int Read_Huffman_Data (FILE * f, huff_data * hd, u_long * mem, u_long * disk) {
+  if (fread (&hd->num_codes, sizeof (hd->num_codes), 1, f) != 1)
+    return -1;
+
+  if (fread (&hd->mincodelen, sizeof (hd->mincodelen), 1, f) != 1)
+    return -1;
+
+  if (fread (&hd->maxcodelen, sizeof (hd->maxcodelen), 1, f) != 1)
+    return -1;
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHSI(hd->num_codes);
+  NTOHSI(hd->mincodelen);
+  NTOHSI(hd->maxcodelen);
+
+  if (disk)
+    (*disk) += sizeof (hd->num_codes) + sizeof (hd->mincodelen) +
+      sizeof (hd->maxcodelen);
+
+  hd->clens = NULL;
+
+  if (hd->num_codes)
+    {
+      int i;  /* [RPAP - Jan 97: Endian Ordering] */
+
+      memset (hd->lencount, '\0', sizeof (hd->lencount));
+      if (fread (hd->lencount + hd->mincodelen, sizeof (*hd->lencount),
+	      hd->maxcodelen - hd->mincodelen + 1, f) !=
+	  hd->maxcodelen - hd->mincodelen + 1)
+	return -1;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (i = hd->mincodelen; i < hd->maxcodelen + 1; ++i)
+	NTOHSI(hd->lencount[i]);
+
+      if (disk)
+	(*disk) += sizeof (*hd->lencount) * (hd->maxcodelen - hd->mincodelen + 1);
+
+      memset (hd->min_code, '\0', sizeof (hd->min_code));
+
+      if (fread (hd->min_code, sizeof (*hd->min_code), hd->maxcodelen + 1, f) !=
+	  hd->maxcodelen + 1)
+	return -1;
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (i = 0; i < hd->maxcodelen + 1; ++i)
+	NTOHUL(hd->min_code[i]);
+
+      if (disk)
+	(*disk) += sizeof (*hd->min_code) * (hd->maxcodelen + 1);
+
+      if (!(hd->clens = new char[hd->num_codes]))
+	return -1;
+
+
+      if (fread (hd->clens, sizeof (*hd->clens), hd->num_codes, f) != hd->num_codes)
+	return -1;
+
+      if (disk)
+	(*disk) += sizeof (*hd->clens) * hd->num_codes;
+    }
+
+  if (mem)
+    *mem += sizeof (*hd->clens) * hd->num_codes;
+  return 0;
+}
Index: /indexers/branches/3.03a/mgpp/lib/huffman.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/huffman.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/huffman.h	(revision 14757)
@@ -0,0 +1,57 @@
+/**************************************************************************
+ *
+ * huffman.h -- Huffman coding functions
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_HUFFMAN
+#define H_HUFFMAN
+
+#include "sysfuncs.h"
+#include "bitio_m_abstract.h"
+
+#define MAX_HUFFCODE_LEN 31
+
+struct huff_data {
+  int num_codes;
+  int mincodelen;
+  int maxcodelen;
+  int lencount[MAX_HUFFCODE_LEN + 1];
+  unsigned long min_code[MAX_HUFFCODE_LEN + 1];
+  char *clens;
+};
+
+
+huff_data *Generate_Huffman_Data (int num, long *freqs, huff_data * data,
+				  u_long * mem);
+
+unsigned long *Generate_Huffman_Codes (huff_data * data, u_long * mem);
+
+unsigned long **Generate_Huffman_Vals (huff_data * data, u_long * mem);
+
+int Write_Huffman_Data (FILE * f, huff_data * hd);
+
+int Read_Huffman_Data (FILE * f, huff_data * hd, u_long * mem, u_long * disk);
+
+/* Calculate the number of bits required to code the data with the
+   specified frequencies. Normally freqs and counts should point to
+   the same array. */
+double Calculate_Huffman_Size (int num, long *freqs, long *counts);
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/local_strings.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/local_strings.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/local_strings.cpp	(revision 14757)
@@ -0,0 +1,411 @@
+/**************************************************************************
+ *
+ * local_strings -- provides some extra string routines
+ * Copyright (C) 1994  Authors
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "local_strings.h"
+#include "memlib.h"
+
+/* =========================================================================
+ * Function: arg_atoi
+ * Description: 
+ *      Converts an ascii string to an integer
+ *      but allows a scale string immediately following.
+ *      i.e. "10Mb" or "20Kb" or "40Megabytes"
+ *      There must be no gap between the last digit and the scale.
+ *      Only the fist letter is significant.
+ *      K = Kilo
+ *      M = Mega
+ *      G = Giga
+ * Input: 
+ *      string of form: xxxxxxK or xxxxxxxM or xxxxxxxG
+ *      where x is a digit
+ * Output: 
+ *      a scaled integer
+ * ========================================================================= */
+
+#define KILO 	1024
+#define MEGA	1024*1024
+#define GIGA	1024*1024*1024
+
+int 
+arg_atoi (char *str)
+{
+  char *str_ptr = str;
+  char ch = '\0';
+  long scale = 1;
+
+  /* find any scale letter immediately after digits */
+  ch = *str_ptr;
+  while (!isalpha (ch) && (ch != '\0'))
+    ch = *str_ptr++;
+
+  /* replace scale letter by end-of-string character */
+  *str_ptr = '\0';
+
+  /* set scale appropriately */
+  switch (ch)
+    {
+    case 'K':
+      scale = KILO;
+      break;
+    case 'M':
+      scale = MEGA;
+      break;
+    case 'G':
+      scale = GIGA;
+      break;
+    default:
+      scale = 1;
+      break;
+    }
+
+  return (atoi (str) * scale);
+
+}
+
+/* ===============================================================================
+ * Function: compare
+ * Description: Compare two strings. 
+ * Input: Two binary strings, first byte of string indicates length. 
+ * Output: Like standard strcmp.
+ *      = 0 if s1 = s2
+ *      < 0 if s1 < s2
+ *      > 0 if s1 > s2
+ * =============================================================================== */
+int 
+compare (u_char * s1, u_char * s2)
+{
+  int l1 = *s1, l2 = *s2;
+  int l = (l1 < l2) ? l1 : l2;
+
+  while (l--)
+    if (*++s1 != *++s2)
+      return (*s1 - *s2);
+  return (l1 - l2);
+
+}
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static unsigned char casecharmap[] = {
+	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+	'\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
+	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+/* ===============================================================================
+ * Function: casecompare   [RPAP - Jan 97: Stem Index Change]
+ * Description: Compare two strings in dictionary order
+ * Input: Two binary strings, first byte of string indicates length. 
+ * Output:
+ *      = 0 if s1 = s2
+ *      < 0 if s1 < s2
+ *      > 0 if s1 > s2
+ * =============================================================================== */
+int 
+casecompare (u_char * s1, u_char * s2)
+{
+  int l1 = *s1, l2 = *s2;
+  int l = (l1 < l2) ? l1 : l2;
+  int pos = 0;
+  register int diff = 0;
+
+  while (l--)
+    if ((diff = casecharmap[*++s1] - casecharmap[*++s2]) != 0)
+      return (diff);
+    else if ((diff = *s1 - *s2) != 0)
+      if (!pos)
+	pos = diff;
+
+  return ((l1 - l2) ? (l1 - l2) : (pos));
+
+}
+
+/* =========================================================================
+ * Function: copy_string
+ * Description: 
+ *      Copies a string with the len in 1st byte
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+u_char *
+copy_string (u_char * src_str)
+{
+  u_char *copy = new u_char(src_str[0] + 1);
+
+  if (!copy)
+    return NULL;
+
+  memcpy (copy, src_str, src_str[0] + 1);
+  return copy;
+
+}
+
+
+/* ===============================================================================
+ * Function: prefixlen
+ * Description: Returns length of common prefix string between s1 and s2.
+ * Input: two binary strings
+ * Output: prefix length
+ * =============================================================================== */
+int 
+prefixlen (u_char * s1, u_char * s2)
+{
+  int l = (*s1 < *s2) ? *s1 : *s2;
+  int i = 0;
+
+  while (i < l && *++s1 == *++s2)
+    ++i;
+  return (i);
+}
+
+
+/* ===============================================================================
+ * Function: char2str
+ * Description: 
+ *      Ensures that non-printable characters are converted to a string
+ *      which is printable i.e. it indentifies the character.
+ *      e.g. carriage-return = "\n".
+ * Input: character (may be non-printable)
+ * Output: pointer to static string
+ * =============================================================================== */
+
+char *
+char2str (u_char c)
+{
+  static char buf[10];
+  switch (c)
+    {
+    case '\n':
+      sprintf (buf, "\\n");
+      break;
+    case '\b':
+      sprintf (buf, "\\b");
+      break;
+    case '\f':
+      sprintf (buf, "\\f");
+      break;
+    case '\t':
+      sprintf (buf, "\\t");
+      break;
+    default:
+	if (c >= ' ' && c <= 126)
+	switch (c)
+	  {
+	  case '\\':
+	    sprintf (buf, "\\\\");
+	    break;
+	  case '\"':
+	    sprintf (buf, "\\\"");
+	    break;
+	  case '\'':
+	    sprintf (buf, "\\\'");
+	    break;
+	  default:
+	    buf[0] = c;
+	    buf[1] = '\0';
+	    break;
+	  }
+      else
+	sprintf (buf, "\\x%02x", c);
+      break;
+    }
+  return buf;
+}
+
+/* ===============================================================================
+ * Function: word2str
+ * Description: 
+ *      Converts a string with possible non-printable characters into a string
+ *      consisting entirely of printable characters.
+ * Input: string, length stored in first byte
+ * Output: pointer to static string
+ * =============================================================================== */
+
+char *
+word2str (u_char * s)
+{
+  static char buf[1024];
+  char *p = buf;
+  int i, len = (int) *s++;
+
+  memset (buf, '\0', sizeof(buf));
+  for (i = 0; i < len; ++i)
+    {
+      strcpy (p, char2str (s[i]));
+      p = strchr (p, '\0');
+    }
+  return buf;
+}
+
+
+/* =========================================================================
+ * Function: de_escape_string
+ * Description: 
+ *      Turn a string containing \ escapes into real characters
+ *      Note this destroys the string s in the process
+ * Input: string to de-escape 
+ * Output: the de-escaped string
+ * ========================================================================= */
+char *
+de_escape_string (char *s)
+{
+  char *org = s;
+  char *d = s;
+  while (*s)
+    {
+      if (*s == '\\')
+	{
+	  ++s;
+	  switch (*s++)
+	    {
+	    case '\0':
+	      *d++ = '\\';
+	      --s;
+	      break;
+	    case '\\':
+	      *d++ = '\\';
+	      break;
+	    case 'b':
+	      *d++ = '\b';
+	      break;
+	    case 'f':
+	      *d++ = '\f';
+	      break;
+	    case 'n':
+	      *d++ = '\n';
+	      break;
+	    case 'r':
+	      *d++ = '\r';
+	      break;
+	    case 't':
+	      *d++ = '\r';
+	      break;
+	    case '\"':
+	      *d++ = '\"';
+	      break;
+	    case '\'':
+	      *d++ = '\'';
+	      break;
+	    case 'x':
+	      {
+		int num = 0;
+		if (isxdigit (*s))
+		  {
+		    char ch = toupper (*s++);
+		    num = ch <= '9' ? ch - '0' : ch - 'A' + 10;
+		  }
+		if (isxdigit (*s))
+		  {
+		    char ch = toupper (*s++);
+		    num = (num << 4) + (ch <= '9' ? ch - '0' : ch - 'A' + 10);
+		  }
+		*d++ = num;
+		break;
+	      }
+	    case '0':
+	    case '1':
+	    case '2':
+	    case '3':
+	    case '4':
+	    case '5':
+	    case '6':
+	    case '7':
+	      {
+		int num = *(s - 1) - '0';
+		if (*s >= '0' && *s <= '7')
+		  num = (num << 3) + *s++ - '0';
+		if (*s >= '0' && *s <= '7')
+		  num = (num << 3) + *s++ - '0';
+		*d++ = num;
+		break;
+	      }
+	    }
+	}
+      else
+	*d++ = *s++;
+    }
+  *d = '\0';
+  return (org);
+}
+
+/* =========================================================================
+ * Function: str255_to_string 
+ * Description: 
+ * Input: 
+ * Output: 
+ * ========================================================================= */
+
+char *
+str255_to_string (u_char * str255, char *str)
+{
+  static char buf[256];
+  char *str_base = NULL;
+  int len = *str255++;
+  int i = 0;
+
+  /* if haven't been given a str to write to then use local buffer */
+  if (!str)
+    str = &(buf[0]);
+
+  str_base = str;
+  for (i = 0; i < len; ++i)
+    {
+      *str++ = *str255++;
+    }
+  *str = '\0';
+
+  return str_base;
+}
Index: /indexers/branches/3.03a/mgpp/lib/local_strings.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/local_strings.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/local_strings.h	(revision 14757)
@@ -0,0 +1,79 @@
+/**************************************************************************
+ *
+ * local_strings.h -- string routines
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef LOCAL_STRINGS_H
+#define LOCAL_STRINGS_H
+
+#include "sysfuncs.h"
+
+class mgString
+{
+  u_char *data;
+ public:
+  inline int length()
+    {
+      return data[0];
+    }
+  inline u_char *rawdata()
+    {
+      return data;
+    }
+  inline void read(u_char **base)
+    {
+      unsigned int copy, suff;
+      
+      copy  = **base;
+      *base = *base + 1;
+      suff  = **base;
+      *base = *base + 1;
+      memcpy( (data + copy + 1), *base, suff);
+      *data = copy + suff;
+      *base += suff;
+    }
+  inline void read(FILE *dict)
+    {
+      unsigned int copy, suff;
+      copy = fgetc(dict);
+      suff = fgetc(dict);
+      fread(data + copy + 1, sizeof(u_char), suff, dict);
+      *data = copy + suff;
+    }
+  inline static void readString(u_char **base, u_char *prev)
+    {
+      ((mgString *) &prev)->read(base);
+    }
+  inline static void readString(FILE *dict, u_char *prev)
+    { 
+      ((mgString *) &prev)->read(dict);
+    }
+};
+
+int arg_atoi (char *str);
+int compare (u_char * s1, u_char * s2);
+int casecompare (u_char * s1, u_char * s2);   /* [RPAP - Jan 97: Stem Index Change] */
+u_char *copy_string (u_char * src_str);
+char *str255_to_string (u_char * str255, char *str);
+int prefixlen (u_char * s1, u_char * s2);
+char *char2str (u_char c);
+char *word2str (u_char * s);
+char *de_escape_string (char *s);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/longlong.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/longlong.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/longlong.h	(revision 14757)
@@ -0,0 +1,85 @@
+/**************************************************************************
+ *
+ * longlong.h -- Use of GCC's long long integer types
+ * Copyright (C) 1999 Tim A.H. Bell
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_LONGLONG
+#define H_LONGLONG
+
+#ifdef HAVE_CONFIG_H
+# ifdef __WIN32__
+#  include <WIN32cfg.h>
+# else
+#  include <config.h>
+# endif
+#endif
+
+/*
+  Use GCC's "long long" integer types for certain variables, to avoid
+  overflowing 32 bit integers.
+
+  Other files affected:
+  
+    lib:
+        bitio_random.c
+        bitio_random.h
+	
+    src/text:
+        ivf.pass1.c
+        ivf.pass2.c
+        build.h
+        mg_passes.c
+        text.h
+    
+*/
+
+/*#define TESTING_OVERFLOW*/
+
+#ifdef TESTING_OVERFLOW
+
+/* Test the overflow detection by using tiny (16-bit) types */
+typedef unsigned short int mg_ullong;
+typedef short int mg_llong;
+
+#define ULL_FS "u"
+#define LL_FS "d"
+
+#elif defined __GNUC__ && ! defined DISABLE_LONG_LONG
+
+/* We're using GCC, so it's okay to use "long long" (64-bit) types */
+#define USE_LONG_LONG
+
+typedef unsigned long long int mg_ullong;
+typedef long long int mg_llong;
+
+#define ULL_FS "llu"
+#define LL_FS "lld"
+
+#else
+
+/* Not using GCC, so fall back on plain "long" (32-bit) types */
+typedef unsigned long int mg_ullong;
+typedef long int mg_llong;
+
+#define ULL_FS "lu"
+#define LL_FS "ld"
+
+#endif /* __GNUC__ */
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/lovinstem.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/lovinstem.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/lovinstem.cpp	(revision 14757)
@@ -0,0 +1,1172 @@
+/**************************************************************************
+ *
+ * lovinstem.c -- Stemming code
+ * Copyright (C) 1994  Linh Huynh (linh@kbs.citri.edu.au)
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+
+/*****************************************************************************
+ *
+ *   Transformational Rules used in Recoding Stem Terminations
+ *
+ *   Parameter in functions:
+ *       ch : the second last character of the old ending
+ *            (after removing one of double consonants) 
+ *
+ ****************************************************************************/
+
+
+/************ Conditional rules associated with transformations **************/
+
+/*static int aio ();
+static int s ();
+static int pt ();
+static int m ();
+static int n ();*/
+
+static int 
+aio (char ch)			/* Rule number 9     */
+{
+  return ((ch != 'a') && (ch != 'i') && (ch != 'o'));
+}
+
+static int 
+s (char ch)				/* Rule Number 24    */
+{
+  return (ch != 's');
+}
+
+static int 
+pt (char ch)				/* Rule number 28    */
+{
+  return ((ch != 'p') && (ch != 't'));
+}
+
+static int 
+m (char ch)				/* Rule number 30    */
+{
+  return (ch != 'm');
+}
+
+static int 
+n (char ch)				/* Rule number 32    */
+{
+  return (ch != 'n');
+}
+
+
+/**************************************************************************
+ *
+ *  Context-sensitive rules associated with certain endings.
+ *
+ *  The notations of the rules are the same as in Lovins' paper
+ *  except that rule A is replaced by a NULL in the data structure.
+ *
+ *  Function parameters:
+ *      - stem_length: possible stem length
+ *      - end        : pointer points to the end of the possible stem.
+ *
+ *************************************************************************/
+
+
+/********* Context-sensitive rule function declarations ******************/
+
+/*static int B ();
+static int C ();
+static int D ();
+static int E ();
+static int F ();
+static int G ();
+static int H ();
+static int I ();
+static int J ();
+static int K ();
+static int L ();
+static int M ();
+static int N ();
+static int O ();
+static int P ();
+static int Q ();
+static int R ();
+static int S ();
+static int T ();
+static int U ();
+static int V ();
+static int W ();
+static int X ();
+static int Y ();
+static int Z ();
+static int AA ();
+static int BB ();
+static int CC ();
+*/
+static int 
+B (int stem_length, char *end)
+{
+  return (stem_length >= 3);
+}
+
+static int 
+C (int stem_length, char *end)
+{
+  return (stem_length >= 4);
+}
+
+static int 
+D (int stem_length, char *end)
+{
+  return (stem_length >= 5);
+}
+
+static int 
+E (int stem_length, char *end)
+
+     
+{
+  return (*end != 'e');
+}
+
+static int 
+F (int stem_length, char *end)
+     
+     
+{
+  return ((stem_length >= 3) && (*end != 'e'));
+}
+
+static int 
+G (int stem_length, char *end)
+     
+     
+{
+  return ((stem_length >= 3) && (*end == 'f'));
+}
+
+static int 
+H (int stem_length, char *end)
+     
+     
+{
+  char p1, p2;
+  p1 = *end;
+  p2 = *(end - 1);
+  return ((p1 == 't') || ((p1 == 'l') && (p2 == 'l')));
+}
+
+static int 
+I (int stem_length, char *end)
+     
+     
+{
+  char p1;
+  p1 = *end;
+  return ((p1 != 'o') && (p1 != 'e'));
+}
+
+static int 
+J (int stem_length, char *end)
+     
+     
+{
+  char p1;
+  p1 = *end;
+  return ((p1 != 'a') && (p1 != 'e'));
+}
+
+static int 
+K (int stem_length, char *end)
+     
+     
+{
+  char p1;
+  p1 = *end;
+  return ((stem_length >= 3) &&
+	  ((p1 == 'l') || (p1 == 'i') ||
+	   ((p1 == 'e') && (*(end - 2) == 'u'))));
+}
+
+static int 
+L (int stem_length, char *end)
+     
+     
+{
+  char p1, p2;
+  p1 = *end;
+  p2 = *(end - 1);
+  if (p1 == 's')
+    return (p2 == 'o');
+  else
+    return ((p1 != 'u') && (p1 != 'x'));
+}
+
+static int 
+M (int stem_length, char *end)
+     
+     
+{
+  char p1;
+  p1 = *end;
+  return ((p1 != 'a') && (p1 != 'c') &&
+	  (p1 != 'e') && (p1 != 'm'));
+}
+
+static int 
+N (int stem_length, char *end)
+     
+     
+{
+  if (stem_length >= 3)
+    {
+      if (*(end - 2) == 's')
+	return (stem_length >= 4);
+      else
+	return 1;
+    }
+  else
+    return 0;
+}
+
+static int 
+O (int stem_length, char *end)
+     
+     
+{
+  char p1;
+  p1 = *end;
+  return ((p1 == 'l') || (p1 == 'i'));
+}
+
+static int 
+P (int stem_length, char *end)
+     
+     
+{
+  return (*end != 'c');
+}
+
+static int 
+Q (int stem_length, char *end)
+     
+     
+{
+  char p1;
+  p1 = *end;
+
+  return ((stem_length >= 3) && (p1 != 'l') && (p1 != 'n'));
+}
+
+static int 
+R (int stem_length, char *end)
+     
+     
+{
+  char p1;
+  p1 = *end;
+  return ((p1 == 'n') || (p1 == 'r'));
+}
+
+static int 
+S (int stem_length, char *end)
+     
+     
+{
+  char p1, p2;
+  p1 = *end;
+  p2 = *(end - 1);
+
+  if (p1 == 't')
+    return (p2 != 't');
+  else
+    return ((p1 == 'r') && (p2 == 'd'));
+}
+
+static int 
+T (int stem_length, char *end)
+     
+     
+{
+  char p1, p2;
+  p1 = *end;
+  p2 = *(end - 1);
+
+  if (p1 == 't')
+    return (p2 != 'o');
+  else
+    return (p1 == 's');
+}
+
+static int 
+U (int stem_length, char *end)
+     
+     
+{
+  char p1;
+  p1 = *end;
+
+  return ((p1 == 'l') || (p1 == 'm') ||
+	  (p1 == 'n') || (p1 == 'r'));
+}
+
+static int 
+V (int stem_length, char *end)
+     
+     
+{
+  return (*end == 'c');
+}
+
+static int 
+W (int stem_length, char *end)
+     
+     
+{
+  char p1;
+  p1 = *end;
+
+  return ((p1 != 's') && (p1 != 'u'));
+}
+
+static int 
+X (int stem_length, char *end)
+     
+     
+{
+  char p1;
+  p1 = *end;
+
+  if (p1 == 'e')
+    return ((stem_length >= 3) && (*(end - 2) == 'u'));
+  else
+    return ((p1 == 'l') || (p1 == 'i'));
+}
+
+static int 
+Y (int stem_length, char *end)
+     
+     
+{
+  return ((*end == 'n') && (*(end - 1) == 'i'));
+}
+
+static int 
+Z (int stem_length, char *end)
+     
+     
+{
+  return (*end != 'f');
+}
+
+static int 
+AA (int stem_length, char *end)
+     
+     
+{
+  char p1, p2;
+  p1 = *end;
+  p2 = *(end - 1);
+
+  if (p1 == 'h')
+    return ((p2 == 'p') || (p2 == 't'));
+  else if (p1 == 'r')
+    return ((p2 == 'e') || (p2 == 'o'));
+  else if (p1 == 's')
+    return (p2 == 'e');
+  else
+    return ((p1 == 'd') || (p1 == 'f') ||
+	    (p1 == 'l') || (p1 == 't'));
+}
+
+static int 
+BB (int stem_length, char *end)
+     
+     
+{
+  if (stem_length >= 3)
+    {
+      if (stem_length >= 4)
+	return (strncmp (end - 3, "ryst", 4) != 0);
+      else
+	return (strncmp (end - 2, "met", 3) != 0);
+    }
+  else
+    return 0;
+}
+
+static int 
+CC (int stem_length, char *end)
+     
+     
+{
+  return (*end == 'l');
+}
+
+/**************************************************************************/
+
+#define MIN_STEM_LENGTH 2
+#define MAX_ENDING_SIZE 11
+#define PREDEFINED_SIZE (MAX_ENDING_SIZE + MIN_STEM_LENGTH)
+#define EOS     '\0'
+/* [RPAP - Jan 97: Stem Index Change] */
+#define MAX_STEM_LENGTH 255
+
+static char *remove_ending (char *word, int w_len);
+static void recode_stem (char *stem_end);
+
+/* =========================================================================
+ * Function: stem
+ * Description: 
+ *      Implemetation of the Lovins' stemming algorithm described in
+ *      J.B. Lovins, "Development of a Stemming Algorithm",
+ *      Mechanical Translation and Computational Linguistics, Vol 11,1968.
+ * Input: a word string with the length in the first byte
+ * Output: the stemmed word
+ * ========================================================================= */
+
+void
+lovinstem (u_char * word)
+{
+  char *word_start;		/* points to first letter of word */
+  char *stem_end;		/* points to last character of stem portion */
+  int old_length;		/* length of word */
+  int new_length;		/* length after stemming */
+
+  /* [RPAP - Jan 97: Stem Index Change] */
+  u_char copy[MAX_STEM_LENGTH + 2];
+  memcpy (copy, word, *word + 1);
+
+  old_length = *copy; /* [RPAP - Jan 97: Stem Index Change] */
+
+  /* The word must be at least MIN_STEM_LENGTH characters long. */
+  if (old_length <= MIN_STEM_LENGTH)
+    return;
+
+  word_start = (char *) copy + 1;	/* jump over length byte */ /* [RPAP - Jan 97: Stem Index Change] */
+  copy[old_length + 1] = '\0';	/* null terminate string */ /* [RPAP - Jan 97: Stem Index Change] */
+
+  stem_end = remove_ending (word_start, old_length);
+  recode_stem (stem_end);
+
+  /* fix up new length */
+  /* have to use strlen because have no other way of telling length */
+  new_length = strlen (word_start);
+  *copy = new_length;  /* [RPAP - Jan 97: Stem Index Change] */
+
+  /* [RPAP - Jan 97: Stem Index Change] */
+  memcpy (word, copy, *copy + 1);
+
+}				/*stem_complex */
+
+/* =========================================================================
+
+ *   Data structure for recoding and the method for recoding the stem. 
+ *
+ * ========================================================================= */
+
+typedef struct
+{
+  char *old_end;		/* old ending */
+  char *new_end;		/* new ending */
+  char old_offset;		/* length of the old ending - 1 */
+  int (*cond) (char);	        /* condition rule */
+  char end_group;		/* signal the end of the group */
+}
+Recode_Rules;
+
+/*  
+   Stem terminations are divided into groups having the same last
+   character
+ */
+
+static Recode_Rules Rules[] =
+{
+  "uad", "uas", 2, NULL, 0,
+  "vad", "vas", 2, NULL, 0,
+  "cid", "cis", 2, NULL, 0,
+  "lid", "lis", 2, NULL, 0,
+  "erid", "eris", 3, NULL, 0,
+  "pand", "pans", 3, NULL, 0,
+  "end", "ens", 2, s, 0,
+  "end", "ens", 2, m, 0,
+  "ond", "ons", 2, NULL, 0,
+  "lud", "lus", 2, NULL, 0,
+  "rud", "rus", 2, NULL, 1,
+
+  "ul", "l", 1, aio, 1,
+
+  "istr", "ister", 3, NULL, 0,
+  "metr", "meter", 3, NULL, 0,
+  "her", "hes", 2, pt, 1,
+
+  "urs", "ur", 2, NULL, 1,
+
+  "uct", "uc", 2, NULL, 0,
+  "umpt", "um", 3, NULL, 0,
+  "rpt", "rb", 2, NULL, 0,
+  "mit", "mis", 2, NULL, 0,
+  "ert", "ers", 2, NULL, 0,
+  "et", "es", 1, n, 0,
+  "yt", "ys", 1, NULL, 1,
+
+  "iev", "ief", 2, NULL, 0,
+  "olv", "olut", 2, NULL, 1,
+
+  "bex", "bic", 2, NULL, 0,
+  "dex", "dic", 2, NULL, 0,
+  "pex", "pic", 2, NULL, 0,
+  "tex", "tic", 2, NULL, 0,
+  "ax", "ac", 1, NULL, 0,
+  "ex", "ec", 1, NULL, 0,
+  "ix", "ic", 1, NULL, 0,
+  "lux", "luc", 2, NULL, 1,
+
+  "yz", "ys", 1, NULL, 1
+};
+
+typedef struct last
+  {
+    char c;			/* The last character */
+    struct last *left;		/* used in balanced   */
+    struct last *right;		/* binary tree        */
+    Recode_Rules *pt;		/* location of approriate group */
+  }
+Last_Char_Node;
+
+/*------------
+       s
+     /   \
+    l     x
+   / \   / \
+  d   r t   z
+         \
+          v
+---------------*/
+static Last_Char_Node pr[] =
+{
+  'd', NULL, NULL, Rules,
+  'l', pr, pr + 2, Rules + 11,
+  'r', NULL, NULL, Rules + 12,
+  's', pr + 1, pr + 6, Rules + 15,
+  't', NULL, pr + 5, Rules + 16,
+  'v', NULL, NULL, Rules + 23,
+  'x', pr + 4, pr + 7, Rules + 25,
+  'z', NULL, NULL, Rules + 33,
+};
+
+
+/*****************************************************************************
+ *
+ *  Recode the stem according to the transformation rules.
+ *
+ *****************************************************************************/
+
+static void
+recode_stem (char *stem_end)
+{
+  static Last_Char_Node *root = pr + 3;
+  Last_Char_Node *p_last = root;
+  Recode_Rules *rule;		/* points to the transformation list */
+  char *h,			/* points to start of possible ending */
+    ch,				/* last character of the old ending  */
+    ch2;
+
+  h = stem_end - 1;
+  ch = *stem_end;
+  if (*h == ch)			/* Check for double consonant        */
+    {
+      if (strchr ("bdglmnprst", ch) != NULL)
+	{
+	  *stem_end = EOS;
+	  stem_end = h;
+	}
+    }
+
+  do				/* Check for the last character       */
+    {
+      ch2 = p_last->c;
+      if (ch == ch2)
+	break;
+      else if (ch > ch2)
+	p_last = p_last->right;
+      else
+	p_last = p_last->left;
+    }
+  while (p_last != NULL);
+
+  if (p_last != NULL)		/* Check for the rest of suffix list */
+    {
+      rule = p_last->pt;
+      for (;;)
+	{
+	  h = stem_end - rule->old_offset;
+	  if (strcmp (h, rule->old_end) == 0)
+	    {
+	      if (!rule->cond || (*rule->cond) (*(h - 1)))
+		{
+		  (void) strcpy (h, rule->new_end);
+		  break;
+		}
+	    }
+	  if (rule->end_group)
+	    break;
+	  ++rule;
+	}
+    }
+}
+
+/* ======================================================================
+
+ *    List of endings and the method to remove the ending 
+ *
+ * ======================================================================*/
+
+/************ Data structures for list of endings  ********************/
+
+typedef struct
+{
+  char *ending;			/* old ending                */
+  int (*cond) (int length, char *end);		/* conditional rule          */
+  signed char left_offset;	/* used to find the siblings */
+  signed char right_offset;	/* in balanced binary tree   */
+}
+Ending_List;
+
+/*
+   The original list of endings is re-organised into groups having
+   the same length and the same first character.
+ */
+
+static Ending_List List[] =
+{
+  "a", NULL, 0, 0,
+
+  "ae", NULL, 0, 0,
+  "al", BB, -1, 2,
+  "ar", X, 0, 0,
+  "as", B, -1, 0,
+
+  "acy", NULL, 0, 1,
+  "age", B, 0, 0,
+  "aic", NULL, -2, 1,
+  "als", BB, 0, 0,
+  "ant", B, -2, 2,
+  "ars", O, 0, 0,
+  "ary", F, -1, 2,
+  "ata", NULL, 0, 0,
+  "ate", NULL, -1, 0,
+
+  "able", NULL, 0, 1,
+  "ably", NULL, 0, 0,
+  "ages", B, -2, 2,
+  "ally", B, 0, 0,
+  "ance", B, -1, 1,
+  "ancy", B, 0, 0,
+  "ants", B, -4, 4,
+  "aric", NULL, 0, 0,
+  "arly", K, -1, 1,
+  "ated", I, 0, 0,
+  "ates", NULL, -2, 2,
+  "atic", B, 0, 0,
+  "ator", NULL, -1, 0,
+
+  "acies", NULL, 0, 0,
+  "acity", NULL, -1, 1,
+  "aging", B, 0, 0,
+  "aical", NULL, -2, 2,
+  "alist", NULL, 0, 0,
+  "alism", B, -1, 0,
+  "ality", NULL, -3, 3,
+  "alize", NULL, 0, 1,
+  "allic", BB, 0, 0,
+  "anced", B, -2, 2,
+  "ances", B, 0, 0,
+  "antic", C, -1, 0,
+  "arial", NULL, -6, 6,
+  "aries", NULL, 0, 1,
+  "arily", NULL, 0, 0,
+  "arity", B, -2, 2,
+  "arize", NULL, 0, 0,
+  "aroid", NULL, -1, 0,
+  "ately", NULL, -3, 3,
+  "ating", I, 0, 1,
+  "ation", B, 0, 0,
+  "ative", NULL, -2, 2,
+  "ators", NULL, 0, 0,
+  "atory", NULL, -1, 1,
+  "ature", E, 0, 0,
+
+  "aceous", NULL, 0, 1,
+  "acious", B, 0, 0,
+  "action", G, -2, 2,
+  "alness", NULL, 0, 0,
+  "ancial", NULL, -1, 1,
+  "ancies", NULL, 0, 0,
+  "ancing", B, -4, 4,
+  "ariser", NULL, 0, 0,
+  "arized", NULL, -1, 1,
+  "arizer", NULL, 0, 0,
+  "atable", NULL, -2, 2,
+  "ations", B, 0, 0,
+  "atives", NULL, -1, 0,
+
+  "ability", NULL, 0, 1,
+  "aically", NULL, 0, 0,
+  "alistic", B, -2, 2,
+  "alities", NULL, 0, 0,
+  "ariness", E, -1, 0,
+  "aristic", NULL, -3, 3,
+  "arizing", NULL, 0, 1,
+  "ateness", NULL, 0, 0,
+  "atingly", NULL, -2, 2,
+  "ational", B, 0, 0,
+  "atively", NULL, -1, 1,
+  "ativism", NULL, 0, 0,
+
+  "ableness", NULL, 0, 1,
+  "arizable", NULL, 0, 0,
+
+  "allically", C, 0, 0,
+  "antaneous", NULL, -1, 1,
+  "antiality", NULL, 0, 0,
+  "arisation", NULL, -2, 2,
+  "arization", NULL, 0, 0,
+  "ationally", B, -1, 1,
+  "ativeness", NULL, 0, 0,
+
+  "antialness", NULL, 0, 0,
+  "arisations", NULL, -1, 1,
+  "arizations", NULL, 0, 0,
+
+  "alistically", B, 0, 1,
+  "arizability", NULL, 0, 0,
+
+  "e", NULL, 0, 0,
+
+  "ed", E, 0, 0,
+  "en", F, -1, 1,
+  "es", E, 0, 0,
+
+  "eal", Y, 0, 0,
+  "ear", Y, -1, 1,
+  "ely", E, 0, 0,
+  "ene", E, -2, 2,
+  "ent", C, 0, 0,
+  "ery", E, -1, 1,
+  "ese", NULL, 0, 0,
+
+  "ealy", Y, 0, 1,
+  "edly", E, 0, 0,
+  "eful", NULL, -2, 1,
+  "eity", NULL, 0, 0,
+  "ence", NULL, -2, 2,
+  "ency", NULL, 0, 0,
+  "ened", E, -1, 2,
+  "enly", E, 0, 0,
+  "eous", NULL, -1, 0,
+
+  "early", Y, 0, 1,
+  "ehood", NULL, 0, 0,
+  "eless", NULL, -2, 2,
+  "elity", NULL, 0, 0,
+  "ement", NULL, -1, 0,
+  "enced", NULL, -3, 3,
+  "ences", NULL, 0, 1,
+  "eness", E, 0, 0,
+  "ening", E, -2, 2,
+  "ental", NULL, 0, 0,
+  "ented", C, -1, 1,
+  "ently", NULL, 0, 0,
+
+  "eature", Z, 0, 0,
+  "efully", NULL, -1, 1,
+  "encies", NULL, 0, 0,
+  "encing", NULL, -2, 2,
+  "ential", NULL, 0, 0,
+  "enting", C, -1, 1,
+  "entist", NULL, 0, 1,
+  "eously", NULL, 0, 0,
+
+  "elihood", E, 0, 1,
+  "encible", NULL, 0, 0,
+  "entally", NULL, -2, 2,
+  "entials", NULL, 0, 0,
+  "entiate", NULL, -1, 1,
+  "entness", NULL, 0, 0,
+
+  "entation", NULL, 0, 0,
+  "entially", NULL, -1, 1,
+  "eousness", NULL, 0, 0,
+
+  "eableness", E, 0, 1,
+  "entations", NULL, 0, 0,
+  "entiality", NULL, -2, 2,
+  "entialize", NULL, 0, 0,
+  "entiation", NULL, -1, 0,
+
+  "entialness", NULL, 0, 0,
+
+  "ful", NULL, 0, 0,
+
+  "fully", NULL, 0, 0,
+
+  "fulness", NULL, 0, 0,
+
+  "hood", NULL, 0, 0,
+
+  "i", NULL, 0, 0,
+
+  "ia", NULL, 0, 0,
+  "ic", NULL, -1, 1,
+  "is", NULL, 0, 0,
+
+  "ial", NULL, 0, 0,
+  "ian", NULL, -1, 1,
+  "ics", NULL, 0, 1,
+  "ide", L, 0, 0,
+  "ied", NULL, -3, 3,
+  "ier", NULL, 0, 0,
+  "ies", P, -1, 0,
+  "ily", NULL, -1, 1,
+  "ine", M, 0, 0,
+  "ing", N, -5, 5,
+  "ion", Q, 0, 0,
+  "ish", C, -1, 1,
+  "ism", B, 0, 1,
+  "ist", NULL, 0, 0,
+  "ite", AA, -3, 3,
+  "ity", NULL, 0, 0,
+  "ium", NULL, -1, 0,
+  "ive", NULL, -1, 1,
+  "ize", F, 0, 0,
+
+  "ials", NULL, 0, 0,
+  "ians", NULL, -1, 0,
+  "ible", NULL, -1, 1,
+  "ibly", NULL, 0, 0,
+  "ical", NULL, -2, 2,
+  "ides", L, 0, 0,
+  "iers", NULL, -1, 1,
+  "iful", NULL, 0, 0,
+  "ines", M, -4, 4,
+  "ings", N, 0, 0,
+  "ions", B, -1, 1,
+  "ious", NULL, 0, 0,
+  "isms", B, -2, 2,
+  "ists", NULL, 0, 0,
+  "itic", H, -1, 1,
+  "ized", F, 0, 1,
+  "izer", F, 0, 0,
+
+  "ially", NULL, 0, 0,
+  "icant", NULL, -1, 1,
+  "ician", NULL, 0, 0,
+  "icide", NULL, -2, 2,
+  "icism", NULL, 0, 0,
+  "icist", NULL, -1, 0,
+  "icity", NULL, -3, 3,
+  "idine", I, 0, 1,
+  "iedly", NULL, 0, 0,
+  "ihood", NULL, -2, 2,
+  "inate", NULL, 0, 0,
+  "iness", NULL, -1, 0,
+  "ingly", B, -6, 6,
+  "inism", J, 0, 1,
+  "inity", CC, 0, 0,
+  "ional", NULL, -2, 2,
+  "ioned", NULL, 0, 0,
+  "ished", NULL, -1, 0,
+  "istic", NULL, -3, 3,
+  "ities", NULL, 0, 1,
+  "itous", NULL, 0, 0,
+  "ively", NULL, -2, 2,
+  "ivity", NULL, 0, 0,
+  "izers", F, -1, 1,
+  "izing", F, 0, 0,
+
+  "ialist", NULL, 0, 0,
+  "iality", NULL, -1, 1,
+  "ialize", NULL, 0, 0,
+  "ically", NULL, -2, 2,
+  "icance", NULL, 0, 0,
+  "icians", NULL, -1, 1,
+  "icists", NULL, 0, 0,
+  "ifully", NULL, -4, 4,
+  "ionals", NULL, 0, 0,
+  "ionate", D, -1, 1,
+  "ioning", NULL, 0, 0,
+  "ionist", NULL, -2, 2,
+  "iously", NULL, 0, 0,
+  "istics", NULL, -1, 1,
+  "izable", E, 0, 0,
+
+  "ibility", NULL, 0, 0,
+  "icalism", NULL, -1, 1,
+  "icalist", NULL, 0, 1,
+  "icality", NULL, 0, 0,
+  "icalize", NULL, -3, 3,
+  "ication", G, 0, 0,
+  "icianry", NULL, -1, 0,
+  "ination", NULL, -1, 1,
+  "ingness", NULL, 0, 0,
+  "ionally", NULL, -5, 5,
+  "isation", NULL, 0, 0,
+  "ishness", NULL, -1, 1,
+  "istical", NULL, 0, 1,
+  "iteness", NULL, 0, 0,
+  "iveness", NULL, -3, 3,
+  "ivistic", NULL, 0, 0,
+  "ivities", NULL, -1, 0,
+  "ization", F, -1, 1,
+  "izement", NULL, 0, 0,
+
+  "ibleness", NULL, 0, 0,
+  "icalness", NULL, -1, 1,
+  "ionalism", NULL, 0, 0,
+  "ionality", NULL, -2, 2,
+  "ionalize", NULL, 0, 0,
+  "iousness", NULL, -1, 1,
+  "izations", NULL, 0, 0,
+
+  "ionalness", NULL, 0, 1,
+  "istically", NULL, 0, 0,
+  "itousness", NULL, -2, 2,
+  "izability", NULL, 0, 0,
+  "izational", NULL, -1, 0,
+
+  "izationally", B, 0, 0,
+
+  "ly", B, 0, 0,
+
+  "less", NULL, 0, 1,
+  "lily", NULL, 0, 0,
+
+  "lessly", NULL, 0, 0,
+
+  "lessness", NULL, 0, 0,
+
+  "ness", NULL, 0, 0,
+
+  "nesses", NULL, 0, 0,
+
+  "o", NULL, 0, 0,
+
+  "on", S, 0, 1,
+  "or", T, 0, 0,
+
+  "oid", NULL, 0, 0,
+  "one", R, -1, 1,
+  "ous", NULL, 0, 0,
+
+  "ogen", NULL, 0, 0,
+
+  "oidal", NULL, 0, 0,
+  "oides", NULL, -1, 2,
+  "otide", NULL, 0, 0,
+  "ously", NULL, -1, 0,
+
+  "oidism", NULL, 0, 0,
+
+  "oidally", NULL, 0, 1,
+  "ousness", NULL, 0, 0,
+
+  "s", W, 0, 0,
+
+  "s'", NULL, 0, 0,
+
+  "um", U, 0, 1,
+  "us", V, 0, 0,
+
+  "ward", NULL, 0, 1,
+  "wise", NULL, 0, 0,
+
+  "y", B, 0, 0,
+
+  "yl", R, 0, 0,
+
+  "ying", B, 0, 1,
+  "yish", NULL, 0, 0,
+
+  "'s", NULL, 0, 0,
+};
+
+typedef struct node
+  {
+    char c;			/* First character  */
+    struct node *left;		/* used in balanced */
+    struct node *right;		/* binary tree      */
+    Ending_List *ptr[11];	/* the approriate location */
+  }
+First_Char_Node;
+
+static First_Char_Node First[] =
+{
+  '\'', NULL, NULL,
+  {NULL,
+   List + 293, NULL, NULL, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL},
+
+  'a', First, NULL,
+  {List,
+   List + 2, List + 9, List + 20, List + 39, List + 58,
+   List + 70, List + 77, List + 82, List + 87, List + 89},
+
+  'e', First + 1, First + 4,
+  {List + 91,
+   List + 93, List + 98, List + 106, List + 116, List + 126,
+   List + 133, List + 138, List + 142, List + 145, NULL},
+
+  'f', NULL, NULL,
+  {NULL,
+   NULL, List + 146, NULL, List + 147, NULL,
+   List + 148, NULL, NULL, NULL, NULL},
+
+  'h', First + 3, First + 5,
+  {NULL,
+   NULL, NULL, List + 149, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL},
+
+  'i', NULL, NULL,
+  {List + 150,
+   List + 152, List + 163, List + 181, List + 202, List + 222,
+   List + 239, List + 252, List + 258, NULL, List + 261},
+
+  'l', First + 2, First + 10,
+  {NULL,
+   List + 262, NULL, List + 263, NULL, List + 265,
+   NULL, List + 266, NULL, NULL, NULL},
+
+  'n', NULL, NULL,
+  {NULL,
+   NULL, NULL, List + 267, NULL, List + 268,
+   NULL, NULL, NULL, NULL, NULL},
+
+  'o', First + 7, First + 9,
+  {List + 269,
+   List + 270, List + 273, List + 275, List + 277, List + 280,
+   List + 281, NULL, NULL, NULL, NULL},
+
+  's', NULL, NULL,
+  {List + 283,
+   List + 284, NULL, NULL, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL},
+
+  'u', First + 8, First + 12,
+  {NULL,
+   List + 285, NULL, NULL, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL},
+
+  'w', NULL, NULL,
+  {NULL,
+   NULL, NULL, List + 287, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL},
+
+  'y', First + 11, NULL,
+  {List + 289,
+   List + 290, NULL, List + 291, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL},
+};
+
+
+/******************************************************************************
+ *
+ *  Look for a match in the suffix list.
+ *  Return the pointer to the end of the new stem if there is a match.
+ *  Otherwise, return the pointer to the end of the original word.
+ *
+ *  Method:
+ *      * Search for the first character in the suffix list.
+ *      * If there is match, search for the rest of the suffix list.
+ *         
+ *****************************************************************************/
+
+static char *
+remove_ending (char *word, int w_len)
+{
+  static First_Char_Node *root = First + 6;	/* the root of binary tree is 'l' */
+  First_Char_Node *p_first;	/* Points to the first character      */
+  /* of the possible suffix             */
+  Ending_List *p_list;		/* Points to the List of Endings      */
+  char *suffix_start,		/* Points to start of possible suffix */
+   *stem_end,			/* Points to the end of possible stem */
+    ch1, ch2;
+  int s_len,			/* Possible stem length               */
+    e_offset,			/* Offset from the end to the start of */
+  /* possible suffix                    */
+    not_done = 1, cmp;
+
+  stem_end = word + w_len - 1;
+  if (w_len > PREDEFINED_SIZE)	/* find the start of suffix   */
+    suffix_start = word + w_len - MAX_ENDING_SIZE;
+  else
+    suffix_start = word + MIN_STEM_LENGTH;
+
+  ch1 = *suffix_start;
+  do				/* Search for the first character     */
+    {
+      p_first = root;
+      do
+	{
+	  ch2 = p_first->c;
+	  if (ch1 == ch2)
+	    break;
+	  else if (ch1 > ch2)
+	    p_first = p_first->right;
+	  else
+	    p_first = p_first->left;
+	}
+      while (p_first != NULL);
+
+      if (p_first != NULL)	/* Search for the rest */
+	{
+	  e_offset = stem_end - suffix_start;
+	  if ((p_list = p_first->ptr[e_offset]) != NULL)
+	    {
+	      for (;;)		/* no need to compare the first char  */
+		{
+		  cmp = strcmp (suffix_start + 1, p_list->ending + 1);
+		  if (cmp > 0)
+		    if (p_list->right_offset)
+		      p_list += p_list->right_offset;
+		    else
+		      break;
+		  else if (cmp < 0)
+		    if (p_list->left_offset)
+		      p_list += p_list->left_offset;
+		    else
+		      break;
+		  else
+		    {
+		      s_len = suffix_start - word;
+		      if (!p_list->cond ||
+			  (*p_list->cond) (s_len, suffix_start - 1))
+			{
+			  *suffix_start = EOS;
+			  stem_end = suffix_start - 1;
+			  not_done = 0;
+			}
+		      break;
+		    }
+		}
+	    }
+	}
+      ++suffix_start;
+    }
+  while (not_done && ((ch1 = *suffix_start) != EOS));
+  return (stem_end);
+}
Index: /indexers/branches/3.03a/mgpp/lib/lovinstem.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/lovinstem.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/lovinstem.h	(revision 14757)
@@ -0,0 +1,28 @@
+/**************************************************************************
+ *
+ * lovinstem.h -- Lovins' stemmer header
+ * Copyright (C) 1994  Linh Huynh, 
+ *                     (glued into library by tes@kbs.citri.edu.au)
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef LOVINSTEM_H
+#define LOVINSTEM_H
+
+void lovinstem (unsigned char *word);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/memlib.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/memlib.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/memlib.cpp	(revision 14757)
@@ -0,0 +1,41 @@
+/**************************************************************************
+ *
+ * memlib.c -- Malloc wrappers
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "memlib.h"
+
+/* Defined as strdup is not an ANSI function */
+char *
+my_strdup(const char *str)
+{
+  char *ret_str = new char[strlen(str)+1];
+  if (ret_str) return strcpy(ret_str, str);
+  else return (char*) 0;
+}
+
+
+Malloc_func Xmalloc = malloc;
+
+Realloc_func Xrealloc = realloc;
+
+Free_func Xfree = free;
+
+Strdup_func Xstrdup = my_strdup;
Index: /indexers/branches/3.03a/mgpp/lib/memlib.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/memlib.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/memlib.h	(revision 14757)
@@ -0,0 +1,55 @@
+/**************************************************************************
+ *
+ * memlib.h -- Malloc wrappers
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_MEMLIB
+#define H_MEMLIB
+
+/* changed default behaviour - we now assume std memory. - john mcp. */
+/* #ifdef STD_MEM */
+#if !defined(NOT_STD_MEM)
+#include <string.h>
+#define Xmalloc malloc
+#define Xrealloc realloc
+#define Xfree free
+
+#if defined (__WIN32__)
+# define Xstrdup _strdup
+#else
+# define Xstrdup strdup
+#endif
+
+#else
+
+
+#include "sysfuncs.h"
+
+typedef void *(*Malloc_func) (size_t);
+typedef void *(*Realloc_func) (void *, size_t);
+typedef void (*Free_func) (void *);
+typedef char *(*Strdup_func) (const char *);
+
+extern Malloc_func Xmalloc;
+extern Realloc_func Xrealloc;
+extern Free_func Xfree;
+extern Strdup_func Xstrdup;
+#endif
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/messages.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/messages.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/messages.cpp	(revision 14757)
@@ -0,0 +1,75 @@
+/**************************************************************************
+ *
+ * messages.c -- Message and error functions
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include <stdarg.h>
+#include "messages.h"
+
+char *msg_prefix = "";
+
+
+void VOLATILE 
+FatalError (int ExitCode, const char *fmt,...)
+{
+  char buf[1024];
+  char *s, *pfx;
+  va_list args;
+  va_start (args, fmt);
+  vsprintf (buf, fmt, args);
+  s = strrchr (buf, '\n');
+  if (!s || *(s + 1) != '\0')
+    strcat (buf, "\n");
+  pfx = strrchr (msg_prefix, '/');
+  pfx = pfx ? pfx + 1 : msg_prefix;
+  fprintf (stderr, "%s%s%s", pfx, *pfx ? " : " : "", buf);
+  exit (ExitCode);
+}
+
+
+
+/*
+ * This function writes messages to stderr. Due to the fact that I can't 
+ * guarantee that the fprintf call is monatomic I have to implement a 
+ * semaphore system.
+ */
+void 
+Message (const char *fmt,...)
+{
+  char buf[1024];
+  char *s, *pfx;
+  va_list args;
+
+#ifdef SILENT
+  return; /* stop those messages!!!! */
+#endif  
+
+  va_start (args, fmt);
+  vsprintf (buf, fmt, args);
+  s = strrchr (buf, '\n');
+  if (!s || *(s + 1) != '\0')
+    strcat (buf, "\n");
+
+  pfx = strrchr (msg_prefix, '/');
+  pfx = pfx ? pfx + 1 : msg_prefix;
+  fprintf (stderr, "%s%s%s", pfx, *pfx ? " : " : "", buf);
+
+}
Index: /indexers/branches/3.03a/mgpp/lib/messages.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/messages.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/messages.h	(revision 14757)
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * messages.h -- Message and error functions
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_MESSAGES
+#define H_MESSAGES
+
+#ifdef __GNUC__
+#define VOLATILE volatile
+#else
+#define VOLATILE
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+extern char *msg_prefix;
+
+void VOLATILE FatalError (int ExitCode, const char *fmt,...);
+void Message (const char *fmt,...);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
+
+
+
Index: /indexers/branches/3.03a/mgpp/lib/mgheap.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/mgheap.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/mgheap.cpp	(revision 14757)
@@ -0,0 +1,148 @@
+/**************************************************************************
+ *
+ * mgheap.c -- Heap routines
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "mgheap.h"
+
+#define SWAP(s, a, b) 						\
+do {								\
+     register int __i;						\
+     register char *__a = (a), *__b = (b);			\
+     for (__i = (s); __i; --__i)				\
+       {							\
+         register char __t = *__a;				\
+	 *__a++ = *__b; *__b++ = __t;				\
+       }							\
+} while(0)
+
+
+
+#define COPY(s, dst, src) 					\
+do {								\
+     register int __i;						\
+     register char *__dst = (dst), *__src = (src);		\
+     for (__i = (s); __i; --__i)				\
+       *__dst++ = *__src++;					\
+} while(0)
+
+
+
+static void 
+heap_heapify (void *heap, int size, int num, int curr, heap_comp hc)
+{
+  register int child = curr * 2;
+  while (child <= num)
+    {
+      if (child < num && hc ((char *) heap + child * size,
+			     (char *) heap + child * size - size) < 0)
+	++child;
+      if (hc ((char *) heap + (curr - 1) * size, (char *) heap + (child - 1) * size) > 0)
+	{
+	  SWAP (size, (char *) heap + (curr - 1) * size,
+		(char *) heap + (child - 1) * size);
+	  curr = child;
+	  child = child * 2;
+	}
+      else
+	break;
+    }
+}
+
+static void 
+heap_pullup (void *heap, int size, int num, heap_comp hc)
+{
+  register int curr = num;
+  register int parent = curr >> 1;
+  while (parent &&
+	 hc ((char *) heap + (curr - 1) * size, (char *) heap + (parent - 1) * size) < 0)
+    {
+      SWAP (size, (char *) heap + (curr - 1) * size,
+	    (char *) heap + (parent - 1) * size);
+      curr = parent;
+      parent = curr >> 1;
+    }
+}
+
+/************************************************************************
+ *
+ * NOTE: If you choose to change the comparison function the first thing 
+ *       you do after changing the function is call heap_build.
+ *
+ */
+void 
+heap_build (void *heap, int size, int num, heap_comp hc)
+{
+  register int i;
+  for (i = num / 2; i > 0; --i)
+    heap_heapify (heap, size, num, i, hc);
+}
+
+
+
+/****************************************************
+ *
+ * NOTE : The heap must be built before heap_sort is called. 
+ *        This has the effect of reversing the order of the array.
+ *		e.g. if your comparison function is designed to pull the
+ *                   biggest thing off the heap first then the result of
+ *		     sorting with this function will be to put the bigest
+ *                   thing at the end of the array.
+ *
+ */
+void 
+heap_sort (void *heap, int size, int num, heap_comp hc)
+{
+  register int i;
+  for (i = num; i > 1; --i)
+    {
+      SWAP (size, (char *) heap, (char *) heap + (i - 1) * size);
+      heap_heapify (heap, size, i - 1, 1, hc);
+    }
+}
+
+
+void 
+heap_deletehead (void *heap, int size, int *num, heap_comp hc)
+{
+  --(*num);
+  SWAP (size, (char *) heap, (char *) heap + *num * size);
+  heap_heapify (heap, size, *num, 1, hc);
+}
+
+
+void 
+heap_changedhead (void *heap, int size, int num, heap_comp hc)
+{
+  heap_heapify (heap, size, num, 1, hc);
+}
+
+
+/***********************************************************************
+ *
+ * This assumes that the item has been added to the end of the
+ * array that is the heap. But that num has not been changed. 
+ *
+ */
+void 
+heap_additem (void *heap, int size, int *num, heap_comp hc)
+{
+  ++(*num);
+  heap_pullup (heap, size, *num, hc);
+}
Index: /indexers/branches/3.03a/mgpp/lib/mgheap.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/mgheap.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/mgheap.h	(revision 14757)
@@ -0,0 +1,82 @@
+/**************************************************************************
+ *
+ * mgheap.h -- Heap routines
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+/* Care should be taken when using these routines as NO error checking is
+ * done.
+ */
+
+
+
+/* The heap comparison routine should return 
+ * <0 : If a should be before b
+ *  0 : If a and b are equal
+ * >0 : If a should be after b
+ */
+typedef int (*heap_comp) (void *a, void *b);
+
+
+/************************************************************************
+ *
+ * NOTE: If you choose to change the comparison function the first thing 
+ *       you do after changing the function is call heap_build.
+ *
+ */
+void heap_build (void *heap, int size, int num, heap_comp hc);
+
+
+
+/************************************************************************
+ *
+ * NOTE : The heap must be built before heap_sort is called.
+ *        This has the effect of reversing the order of the array.
+ *		e.g. if your comparison function is designed to pull the
+ *                   biggest thing off the heap first then the result of
+ *		     sorting with this function will be to put the bigest
+ *                   thing at the end of the array.
+ *
+ */
+void heap_sort (void *heap, int size, int num, heap_comp hc);
+
+/***********************************************************************
+ *
+ * NOTE: After deleting the head the heap will be one item shorter.
+ *       The deleted item will be placed at the end of the heap.
+ *
+ */
+void heap_deletehead (void *heap, int size, int *num, heap_comp hc);
+
+
+/***********************************************************************
+ *
+ * If you change the "value" of the root node of the heap then you
+ * should call this to re-pritorize the heap.
+ *
+ */
+void heap_changedhead (void *heap, int size, int num, heap_comp hc);
+
+
+/***********************************************************************
+ *
+ * This assumes that the item has been added to the end of the
+ * array that is the heap. But that num has not been changed. 
+ *
+ */
+void heap_additem (void *heap, int size, int *num, heap_comp hc);
Index: /indexers/branches/3.03a/mgpp/lib/netorder.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/netorder.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/netorder.h	(revision 14757)
@@ -0,0 +1,177 @@
+#ifndef NETORDER_H
+#define NETORDER_H
+
+#include "sysfuncs.h"
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+#include "win32in.h"
+#else
+# include <netinet/in.h>
+#endif
+
+#ifndef WORDS_BIGENDIAN
+
+/* double */
+#define HTOND(d)                                                              \
+        do {                                                                  \
+             unsigned long tmph, tmpl;                                        \
+	     memcpy ((void *) &tmph, (const void *) &d, sizeof(double) >> 1); \
+	     memcpy ((void *) &tmpl, (const void *) ((unsigned int) &d + (sizeof(double) >> 1)), sizeof (double) >> 1);   \
+	     tmph = htonl (tmph);                                             \
+	     tmpl = htonl (tmpl);                                             \
+	     memcpy ( (void *) &d, (const void *) &tmpl, sizeof (double) >> 1);                           \
+	     memcpy ((void *) ((unsigned int) &d + (sizeof(double) >> 1)), (const void *) &tmph, sizeof (double) >> 1);   \
+	}while(0)
+#define NTOHD(d)                                                              \
+        do {                                                                  \
+             unsigned long tmph, tmpl;                                        \
+	     memcpy ((void *) &tmph, (const void *) &d, sizeof(double) >> 1); \
+	     memcpy ((void *) &tmpl, (const void *) ((int) &d + (sizeof(double) >> 1)), sizeof (double) >> 1);   \
+	     tmph = ntohl (tmph);                                             \
+	     tmpl = ntohl (tmpl);                                             \
+	     memcpy((void *) &d, (const void *) &tmpl, sizeof (double) >> 1); \
+	     memcpy ((void *) ((int) &d + (sizeof(double) >> 1)), (const void *) &tmph, sizeof (double) >> 1);   \
+        }while(0)
+#define HTOND2(hd, nd)                                                        \
+        do {                                                                  \
+             unsigned long tmph, tmpl;                                        \
+	     memcpy ((void *) &tmph, (const void *) &hd, sizeof(double) >> 1);\
+	     memcpy ((void *) &tmpl, (const void *) ((unsigned int) &hd + (sizeof(double) >> 1)), sizeof (double) >> 1);  \
+	     tmph = htonl (tmph);                                             \
+	     tmpl = htonl (tmpl);                                             \
+	     memcpy((void *) &nd, (const void *) &tmpl, sizeof (double) >> 1);\
+	     memcpy ((void *) ((unsigned int) &nd + (sizeof(double) >> 1)), (void *) &tmph, sizeof (double) >> 1);  \
+	}while(0)
+#define NTOHD2(nd, hd)                                                        \
+        do {                                                                  \
+             unsigned long tmph, tmpl;                                        \
+	     memcpy ((void *) &nd, (void *) &tmph, sizeof(double) >> 1);      \
+	     memcpy ((void *) &tmpl, (const void *) &nd + (sizeof(double) >> 1), sizeof (double) >> 1);  \
+	     tmph = ntohl (tmph);                                             \
+	     tmpl = ntohl (tmpl);                                             \
+	     memcpy((void *) &hd, (const void *) &tmpl, sizeof (double) >> 1);\
+	     memcpy ((void *) &hd + (sizeof(double) >> 1), (const void *) &tmph, sizeof (double) >> 1);  \
+        }while(0)
+
+/* float */
+#define HTONF(f)                                                              \
+        do {                                                                  \
+             unsigned long tmp;                                               \
+             memcpy ((void *) &tmp, (const void *) &(f), sizeof (float));     \
+             HTONUL (tmp);                                                    \
+	     memcpy ((void *) &(f), (const void *) &tmp, sizeof (float));     \
+	}while(0)
+#define NTOHF(f)                                                              \
+        do {                                                                  \
+             unsigned long tmp;                                               \
+             memcpy ((void *) &tmp, (const void *) &(f), sizeof (float));     \
+	     NTOHUL (tmp);                                                    \
+	     memcpy ((void *) &(f), (const void *) &tmp, sizeof (float));     \
+	}while(0)
+#define HTONF2(hf, nf)                                                        \
+        do {                                                                  \
+             unsigned long tmp;                                               \
+             memcpy ((void *) &tmp, (const void *) &(hf), sizeof (float));    \
+             HTONUL (tmp);                                                    \
+	     memcpy ((void *) &(nf), (const void *) &tmp, sizeof (float));    \
+	}while(0)
+#define NTOHF2(nf, hf)                                                        \
+        do {                                                                  \
+             unsigned long tmp;                                               \
+             memcpy ((void *) &tmp, (const void *) &(nf), sizeof (float));    \
+	     NTOHUL (tmp);                                                    \
+	     memcpy ((void *) &(hf), (const void *) &tmp, sizeof (float));    \
+	}while(0)
+
+/* pointers */
+#define HTONP(p)          ((p) = (void *) htonl ((unsigned long) p))
+#define NTOHP(p)          ((p) = (void *) ntohl ((unsigned long) p))
+#define HTONP2(hp, np)    ((np) = (void *) htonl ((unsigned long) hp))
+#define NTOHP2(np, hp)    ((hp) = (void *) ntohl ((unsigned long) np))
+
+/* unsigned long */
+#define HTONUL(l)         ((l) = htonl((l)))
+#define NTOHUL(l)         ((l) = ntohl((l)))
+#define HTONUL2(hl, nl)   ((nl) = htonl ((hl)))
+#define NTOHUL2(nl, hl)   ((hl) = ntohl ((nl)))
+
+/* signed long */
+#define HTONSL(l)         ((l) = (long) htonl ((unsigned long) (l)))
+#define NTOHSL(l)         ((l) = (long) ntohl ((unsigned long) (l)))
+#define HTONSL2(hl, nl)   ((nl) = (long) htonl ((unsigned long) (hl)))
+#define NTOHSL2(nl, hl)   ((hl) = (long) ntohl ((unsigned long) (nl)))
+
+/* unsigned int */
+#define HTONUI(i)         ((i) = (unsigned int) htonl ((unsigned long) (i)))
+#define NTOHUI(i)         ((i) = (unsigned int) ntohl ((unsigned long) (i)))
+#define HTONUI2(hi, ni)   ((ni) = (unsigned int) htonl ((unsigned long) (hi)))
+#define NTOHUI2(ni, hi)   ((hi) = (unsigned int) ntohl ((unsigned long) (ni)))
+
+/* signed int */
+#define HTONSI(i)         ((i) = (int) htonl ((unsigned long) (i)))
+#define NTOHSI(i)         ((i) = (int) ntohl ((unsigned long) (i)))
+#define HTONSI2(hi, ni)   ((ni) = (int) htonl ((unsigned long) (hi)))
+#define NTOHSI2(ni, hi)   ((hi) = (int) ntohl ((unsigned long) (ni)))
+
+/* unsigned short */
+#define HTONUS(s)         ((s) = htons((s)))
+#define NTOHUS(s)         ((s) = ntohs((s)))
+#define HTONUS2(hs, ns)   ((ns) = htons((hs)))
+#define NTOHUS2(ns, hs)   ((hs) = ntohs((ns)))
+
+#else   /* WORDS_BIGENDIAN */
+
+/* double */
+#define HTOND(d)          (d)
+#define NTOHD(d)          (d)
+#define HTOND2(hd, nd)    ((hd) = (nd))
+#define NTOHD2(nd, hd)    ((nd) = (hd))
+
+/* float */
+#define HTONF(f)          (f)
+#define NTOHF(f)          (f)
+#define HTONF2(hf, nf)    ((nf) = (hf))
+#define NTOHF2(nf, hf)    ((hf) = (nf))
+
+/* pointers */
+#define HTONP(p)          (p)
+#define NTOHP(p)          (p)
+#define HTONP2(hp, np)    ((np) = (hp))
+#define NTOHP2(np, hp)    ((hp) = (np))
+
+/* unsigned long */
+#define HTONUL(l)         (l)
+#define NTOHUL(l)         (l)
+#define HTONUL2(hl, nl)   ((nl) = (hl))
+#define NTOHUL2(nl, hl)   ((hl) = (nl))
+
+/* signed long */
+#define HTONSL(l)         (l)
+#define NTOHSL(l)         (l)
+#define HTONSL2(hl, nl)   ((nl) = (hl))
+#define NTOHSL2(nl, hl)   ((hl) = (nl))
+
+/* unsigned int */
+#define HTONUI(i)         (i)
+#define NTOHUI(i)         (i)
+#define HTONUI2(hi, ni)   ((ni) = (hi))
+#define NTOHUI2(ni, hi)   ((hi) = (ni))
+
+/* signed int */
+#define HTONSI(i)         (i)
+#define NTOHSI(i)         (i)
+#define HTONSI2(hi, ni)   ((ni) = (hi))
+#define NTOHSI2(ni, hi)   ((hi) = (ni))
+
+/* unsigned short */
+#define HTONUS(s)         (s)
+#define NTOHUS(s)         (s)
+#define HTONUS2(hs, ns)   ((ns) = (hs))
+#define NTOHUS2(ns, hs)   ((hs) = (ns))
+
+
+
+#endif
+
+#endif /* netorder.h */
Index: /indexers/branches/3.03a/mgpp/lib/non_ansi.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/non_ansi.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/non_ansi.h	(revision 14757)
@@ -0,0 +1,24 @@
+#if !defined(_NON_ANSI_H)
+#define _NON_ANSI_H 1
+
+#include "config.h" 
+# if !defined(__STDC__)
+
+#include <stdlib.h>  /* for FILE def */
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+int fileno(FILE *);
+int ftruncate(int, long);
+int pclose(FILE *);
+FILE *popen(const char *command, const char *type);
+int getpagesize();
+int strcasecmp(const char *, const char *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* !defined STDC, ... */
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/pathmax.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/pathmax.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/pathmax.h	(revision 14757)
@@ -0,0 +1,53 @@
+/* Define PATH_MAX somehow.  Requires sys/types.h.
+   Copyright (C) 1992 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 program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef _PATHMAX_H
+#define _PATHMAX_H
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
+   PATH_MAX but might cause redefinition warnings when sys/param.h is
+   later included (as on MORE/BSD 4.3).  */
+#if defined(_POSIX_VERSION) || (defined(HAVE_LIMITS_H) && !defined(__GNUC__))
+#include <limits.h>
+#endif
+
+#ifndef _POSIX_PATH_MAX
+#define _POSIX_PATH_MAX 255
+#endif
+
+#if !defined(PATH_MAX) && defined(_PC_PATH_MAX)
+#define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
+#endif
+
+/* Don't include sys/param.h if it already has been.  */
+#if defined(HAVE_SYS_PARAM_H) && !defined(PATH_MAX) && !defined(MAXPATHLEN)
+#include <sys/param.h>
+#endif
+
+#if !defined(PATH_MAX) && defined(MAXPATHLEN)
+#define PATH_MAX MAXPATHLEN
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX _POSIX_PATH_MAX
+#endif
+
+#endif /* _PATHMAX_H */
Index: /indexers/branches/3.03a/mgpp/lib/perf_hash.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/perf_hash.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/perf_hash.cpp	(revision 14757)
@@ -0,0 +1,1074 @@
+/**************************************************************************
+ *
+ * perf_hash.c -- Perfect hashing functions
+ * Copyright (C) 1992  Bohdan S. Majewski
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ * 1994 Neil Sharman
+ *      Small modifications were made to the interface so that it fitted in
+ *      with mg.
+ *
+ **************************************************************************/
+
+#define STRUCT
+
+#include <time.h>  /* for call to time () in SEED_RANDOM() */
+#include "sysfuncs.h"
+
+#include "local_strings.h"
+#include "memlib.h"
+#include "messages.h"
+#include "perf_hash.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#define FALSE 0
+#define TRUE  1
+
+#define STATIC 0
+
+/* Random Number stuff */
+
+long irandm (long is[2]);  /* from random.c */
+
+static long seed[] = {0, 0};
+#define RANDOM() irandm(seed)
+#define SEED_RANDOM(the_seed) do{ seed[0] = the_seed; }while(0)
+
+/* Max number of keys - must be a power of 2 minus 1 */
+static int MAX_M;
+
+
+static int MAX_CH;
+
+
+/* the width of the mapping tables  */
+static int MAX_L;
+
+
+
+#define c     1.23
+static int MAX_N;
+
+
+
+
+static u_char *translate;
+
+#define MEMBER 0
+#define ERASED 1
+
+
+
+/* direction constants for the edge oriented 3-graph representation */
+#define A              0
+#define B        (MAX_M)
+#define C          (2*B)
+
+/* NODEa, NODEb, NODEc, FIRST and NEXT are used to represent a 3-graph */
+static int *NODEa, *NODEb, *NODEc;
+static int *FIRST;
+static int *NEXT;
+
+
+#define norm(e) ((e) % MAX_M)
+/* in general should be ((e) % MAX_M) but MAX_M = 2^k - 1 */
+
+
+static char *mk;		/* for marking edges/vertices as removed */
+static int *g;			/* array g defines a minimal perfect hash function */
+
+
+
+/* stack of edges, created during the independency */
+/* test, used in the assignment step               */
+static struct
+  {
+    int sp;
+    int *st;
+  }
+S;
+#define push(s, e) s.st[s.sp++] = (e)
+#define pop(s, e)  e = s.st[--s.sp]
+
+#ifndef STRUCT
+static long **tb0, **tb1, **tb2;
+#else
+struct tb_entry **tb;
+#endif
+
+
+static int 
+unique (int v)
+{				/* checks if vertex v belongs to only one edge */
+  return (FIRST[v] != 0 && NEXT[FIRST[v]] == 0) ? FIRST[v] : 0;
+}				/*unique */
+
+
+
+
+
+
+
+
+static void 
+_delete (int v, int e)
+{				/* deletes edge e from list of v */
+
+  int b;
+
+  b = FIRST[v];
+  assert (norm (b) != 0);
+  if (norm (b) == e)
+    FIRST[v] = NEXT[FIRST[v]];
+  else
+    {
+      while (norm (NEXT[b]) != e)
+	{
+	  b = NEXT[b];
+	  assert (norm (b) != 0);
+	}
+      NEXT[b] = NEXT[NEXT[b]];
+    }
+}				/*delete */
+
+
+
+
+
+
+#if 0
+/* recursively removes the edges of a 3-graph which have at least */
+/* one unique vertex. The removed edges are placed on stack S     */
+static void 
+ph_remove (int e, int v)
+{
+  int b;
+  mk[e] = ERASED;
+  push (S, e);
+
+  if (NODEa[e] != v)
+    _delete (NODEa[e], e);
+  if (NODEb[e] != v)
+    _delete (NODEb[e], e);
+  if (NODEc[e] != v)
+    _delete (NODEc[e], e);
+
+  if (NODEa[e] != v && mk[b = norm (unique (NODEa[e]))] == MEMBER)
+    ph_remove (b, NODEa[e]);
+  if (NODEb[e] != v && mk[b = norm (unique (NODEb[e]))] == MEMBER)
+    ph_remove (b, NODEb[e]);
+  if (NODEc[e] != v && mk[b = norm (unique (NODEc[e]))] == MEMBER)
+    ph_remove (b, NODEc[e]);
+}
+#else
+
+
+static int StackPos, StackMax;
+static struct Stack
+  {
+    int e, v, m;
+  }
+ *Stack = NULL;
+
+#define StackAdd(_e, _v, _m)						\
+  do {									\
+    if (StackPos == StackMax)						\
+      {									\
+        StackMax <<= 1;							\
+	if (!(Stack = (struct Stack *)Xrealloc(Stack, sizeof(*Stack) * StackMax)))	\
+	  return(-1);							\
+      }									\
+    Stack[StackPos].e = (_e);						\
+    Stack[StackPos].v = (_v);						\
+    Stack[StackPos++].m = (_m);						\
+  } while(0)
+
+
+static int 
+ph_remove (int e, int v)
+{
+  if (!Stack)
+    {
+      StackMax = 256;
+      if (!(Stack = (struct Stack *) Xmalloc (sizeof (*Stack) * StackMax)))
+	return (-1);
+      StackPos = 0;
+    }
+  Stack[StackPos].e = e;
+  Stack[StackPos].v = v;
+  Stack[StackPos].m = 0;
+  ++StackPos;
+  while (StackPos)
+    {
+      int m, b;
+      --StackPos;
+      e = Stack[StackPos].e;
+      v = Stack[StackPos].v;
+      m = Stack[StackPos].m;
+
+
+      switch (m)
+	{
+	case 0:
+	  {
+	    mk[e] = ERASED;
+	    push (S, e);
+
+	    if (NODEa[e] != v)
+	      _delete (NODEa[e], e);
+	    if (NODEb[e] != v)
+	      _delete (NODEb[e], e);
+	    if (NODEc[e] != v)
+	      _delete (NODEc[e], e);
+
+	    if (NODEa[e] != v && mk[b = norm (unique (NODEa[e]))] == MEMBER)
+	      {
+		Stack[StackPos++].m = 1;
+		StackAdd (b, NODEa[e], 0);
+		break;
+	      }
+	  }
+	case 1:
+	  {
+	    if (NODEb[e] != v && mk[b = norm (unique (NODEb[e]))] == MEMBER)
+	      {
+		Stack[StackPos++].m = 2;
+		StackAdd (b, NODEb[e], 0);
+		break;
+	      }
+	  }
+	case 2:
+	  if (NODEc[e] != v && mk[b = norm (unique (NODEc[e]))] == MEMBER)
+	    StackAdd (b, NODEc[e], 0);
+	}
+    }
+  return (0);
+}
+#endif
+
+
+
+
+
+/* returns TRUE if and only if set of edges created in the tree_builder */
+/* procedure form a 3-graph with independent edges. Edges of a 3-graph  */
+/* are independent iff repeated deletion of edges containing vertices   */
+/* of degree 1 results in a graph with no edges in it.                  */
+static int 
+acyclic (int m, int n)
+{
+
+  int v, e;
+  /* build list of edges for each node */
+  for (v = 1; v <= n; FIRST[v++] = 0);
+  for (e = 1; e <= m; ++e)
+    {
+      NEXT[A + e] = FIRST[NODEa[e]];
+      FIRST[NODEa[e]] = A + e;
+      NEXT[B + e] = FIRST[NODEb[e]];
+      FIRST[NODEb[e]] = B + e;
+      NEXT[C + e] = FIRST[NODEc[e]];
+      FIRST[NODEc[e]] = C + e;
+
+      /* mark edge e as belonging to the hypergraph */
+      mk[e] = MEMBER;
+    }
+
+
+  S.sp = 0;			/* empty the stack */
+  mk[0] = ERASED;		/* a sentinel for the test below */
+  for (v = 1; v <= n; ++v)
+    {
+      if (mk[e = norm (unique (v))] == MEMBER)
+	ph_remove (e, v);
+    }
+
+  /* check if any edges were left in the graph */
+  return S.sp == m;
+}				/*acyclic */
+
+
+
+
+
+
+
+
+/* repeatedly maps words into edges of a 3-graph until the edges */
+/* are independent.                                              */
+static int 
+tree_builder (int num, u_char ** keys, int *n)
+{
+
+  int e, k = 0;
+  int i, j;
+  u_char *w;
+
+  do
+    {
+      *n = (int) (num * c + 1);
+      /* initialize tables of random integers */
+      for (i = 0; i < MAX_CH; ++i)
+	for (j = 0; j < MAX_L; ++j)
+	  {
+#ifndef STRUCT
+	    tb0[i][j] = RANDOM () % *n;
+	    tb1[i][j] = RANDOM () % *n;
+	    tb2[i][j] = RANDOM () % *n;
+#else
+	    struct tb_entry *tbp = &tb[i][j];
+	    tbp->tb0 = RANDOM () % *n;
+	    tbp->tb1 = RANDOM () % *n;
+	    tbp->tb2 = RANDOM () % *n;
+#endif
+	  }
+
+      /* compute an edge (NODEa[e], NODEb[e], NODEc[e]) for each word */
+      for (e = 1; e <= num; ++e)
+	{
+	  /*generate an edge corresponding to the ith word */
+	  int x = 0, y = 0, z = 0, l;
+	  w = keys[e - 1];
+
+	  l = *w++;
+	  j = (l - 1) % MAX_L;
+
+	  do
+	    {
+#ifndef STRUCT
+	      x += tb0[translate[*w]][j];
+	      y += tb1[translate[*w]][j];
+	      z += tb2[translate[*w]][j];
+#else
+	      struct tb_entry *tbp = &tb[translate[*w]][j];
+	      x += tbp->tb0;
+	      y += tbp->tb1;
+	      z += tbp->tb2;
+#endif
+	      if (++j >= MAX_L)
+		j = 0;
+	      ++w;
+	    }
+	  while (--l);
+	  x = (x % *n) + 1;
+	  y = (y % *n) + 1;
+	  z = (z % *n) + 1;
+	  if (y == x && ++y > *n)
+	    y = 1;
+	  if (z == x && ++z > *n)
+	    z = 1;
+	  if (z == y)
+	    {
+	      if (++z > *n)
+		z = 1;
+	      if (z == x && ++z > *n)
+		z = 1;
+	    }
+
+	  NODEa[e] = x;
+	  NODEb[e] = y;
+	  NODEc[e] = z;
+	}
+      if (++k > 50)		/* make sure we will not wait for ever */
+	FatalError (1, "Unable to generate the perfect hash function. "
+		    "This is probably because there aren't enough words");
+    }
+  while (!acyclic (num, *n));
+  return k;
+}				/*tree_builder */
+
+
+
+
+
+
+
+
+
+/* calculates values of the g function/array so that i-th word is */
+/* placed at the (i-1)st position of a hash table.                */
+static void 
+assign (int n)
+{
+
+  int v, w = 0, e;
+
+  /* mark all the vertices of the 3-graph as unassigned */
+  for (v = 1; v <= n; mk[v++] = FALSE);
+
+  while (S.sp > 0)
+    {
+      int _xor = 0;
+      pop (S, e);
+      v = NODEa[e];
+      if (mk[v])
+	_xor ^= g[v];
+      else
+	{
+	  g[w = v] = 0;
+	  mk[v] = TRUE;
+	}
+      v = NODEb[e];
+      if (mk[v])
+	_xor ^= g[v];
+      else
+	{
+	  g[w = v] = 0;
+	  mk[v] = TRUE;
+	}
+      v = NODEc[e];
+      if (mk[v])
+	_xor ^= g[v];
+      else
+	{
+	  g[w = v] = 0;
+	  mk[v] = TRUE;
+	}
+      g[w] = (e - 1) ^ _xor;
+    }
+}				/*assign */
+
+
+
+
+
+
+
+
+
+/*check returns 0 if no error in mphf is detected, else returns error code */
+static int 
+check (int m)
+{
+
+  int e, err_code = 0;
+
+  /*for each word compute its place in hash table and check if correct */
+  for (e = 1; e <= m; ++e)
+    {
+      if ((e - 1) != (g[NODEa[e]] ^ g[NODEb[e]] ^ g[NODEc[e]]))
+	{
+	  (void) fprintf (stderr, "Error for %dth word detected.\n", e);
+	  err_code = e;
+	}
+    }
+  return err_code;
+}				/*check */
+
+
+
+
+
+
+
+#if 0
+void 
+outputh (int m, int n)
+{
+
+  int i, j, w = (int) ceil (log10 ((double) n + 1.0)) + 1;
+
+#if 0
+  char *PRG =
+  "int h(char *s)\n"
+  "{\n"
+  "  int u, v, w, i;\n"
+  "i = (strlen(s) - 1) % _HXL;\n"
+  "  u = v = w = 0;\n"
+  "  while(*s)\n"
+  "    {\n"
+  "      u += mt1[(*s) - _HFC][i];\n"
+  "      v += mt2[(*s) - _HFC][i];\n"
+  "      w += mt3[(*s++) - _HFC][i];\n"
+  "      if(++i >= _HXL) i = 0;\n"
+  "    }\n"
+  "  u %= _HFN; v %= _HFN; w %= _HFN;\n"
+  "  if(u == v && ++v >= _HFN) v = 0;\n"
+  "  if(w == u && ++w >= _HFN) w = 0;\n"
+  "  if(w == v && ++w >= _HFN) w = 0;\n"
+  "  if(w == u && ++w >= _HFN) w = 0;\n"
+  "  return (g[u] ^ g[v] ^ g[w]) % _HFM;\n"
+  "};\n\n";
+#endif
+
+  char *PRG =
+  "int h(char *s)\n"
+  "{\n"
+  "  int u, v, w, i;\n"
+  "  i = (strlen(s) - 1) % _HXL;\n"
+  "  u = v = w = 0;\n"
+  "  while(*s)\n"
+  "    {\n"
+  "      if((u += mt1[(*s) - _HFC][i]) >= _HFN) u -= _HFN;\n"
+  "      if((v += mt2[(*s) - _HFC][i]) >= _HFN) v -= _HFN;\n"
+  "      if((w += mt3[(*s++) - _HFC][i]) >= _HFN) w -= _HFN;\n"
+  "      if(++i >= _HXL) i = 0;\n"
+  "    }\n"
+  "  if(u == v && ++v >= _HFN) v = 0;\n"
+  "  if(w == v) \n"
+  "    {\n"
+  "      if(++w >= _HFN) w = 0;\n"
+  "      if(w == u && ++w >= _HFN) w = 0;\n"
+  "    }\n"
+  "  else\n"
+  "    if(w == u)\n"
+  "      {\n"
+  "	     if(++w >= _HFN) w = 0;\n"
+  "	     if(w == v && ++w >= _HFN) w = 0;\n"
+  "      }\n"
+  "  return ((g[u] ^ g[v] ^ g[w]) > _HFM)? 0 : (g[u] ^ g[v] ^ g[w]);\n"
+  "}\n\n";
+
+  printf ("#define _HFN %d\n#define _HFC %d\n", n, fc);
+  printf ("#define _HFM %d\n#define _HXL %d\n", m, MAX_L);
+  printf ("#define _HFA %d\n\nstatic int g[_HFN] = {\n", lc - fc + 1);
+  for (i = 1; i < n; ++i)
+    {
+      if (i % 8 == 0)
+	putchar ('\n');
+      printf ("%5d, ", g[i]);
+    }
+  printf ("%5d};\n\n", g[n]);
+
+  printf ("static int mt1[_HFA][_HXL] = {\n");
+  for (j = fc; j < lc; ++j)
+    {
+      printf ("{");
+      for (i = 0; i < MAX_L - 1; ++i)
+	printf ("%*d,", w, tb0[j][i]);
+      printf ("%*d},\n", w, tb0[j][MAX_L - 1]);
+    }
+  printf ("{");
+  for (i = 0; i < MAX_L - 1; ++i)
+    printf ("%*d,", w, tb0[lc][i]);
+  printf ("%*d}\n", w, tb0[lc][MAX_L - 1]);
+  printf ("};\n\n");
+
+  printf ("static int mt2[_HFA][_HXL] = {\n");
+  for (j = fc; j < lc; ++j)
+    {
+      printf ("{");
+      for (i = 0; i < MAX_L - 1; ++i)
+	printf ("%*d,", w, tb1[j][i]);
+      printf ("%*d},\n", w, tb1[j][MAX_L - 1]);
+    }
+  printf ("{");
+  for (i = 0; i < MAX_L - 1; ++i)
+    printf ("%*d,", w, tb1[lc][i]);
+  printf ("%*d}\n", w, tb1[lc][MAX_L - 1]);
+  printf ("};\n\n");
+
+  printf ("static int mt3[_HFA][_HXL] = {\n");
+  for (j = fc; j < lc; ++j)
+    {
+      printf ("{");
+      for (i = 0; i < MAX_L - 1; ++i)
+	printf ("%*d,", w, tb2[j][i]);
+      printf ("%*d},\n", w, tb2[j][MAX_L - 1]);
+    }
+  printf ("{");
+  for (i = 0; i < MAX_L - 1; ++i)
+    printf ("%*d,", w, tb2[lc][i]);
+  printf ("%*d}\n", w, tb2[lc][MAX_L - 1]);
+  printf ("};\n\n");
+
+  printf ("%s", PRG);
+}				/*outputh */
+#endif
+
+
+
+
+
+
+
+static void 
+make_trans_func (int num, u_char ** keys)
+{
+  int i, j;
+
+  memset (translate, '\0', sizeof (translate));
+
+  MAX_L = 1;
+  for (i = 0; i < num; ++i)
+    {
+      unsigned len = keys[i][0];
+      u_char *s = keys[i] + 1;
+      for (; len; --len, ++s)
+	translate[*s] = 1;
+      if (i)
+	{
+	  int l;
+	  l = prefixlen (keys[i - 1], keys[i]);
+	  if (l + 1 > MAX_L)
+	    MAX_L = l + 1;
+	}
+    }
+  j = 0;
+  for (i = 0; i < 256; ++i)
+    if (translate[i])
+      translate[i] = j++;
+  MAX_CH = j;
+}
+
+
+static void 
+temp_free (void)
+{
+  if (NODEa)
+    Xfree (NODEa);
+  if (NODEb)
+    Xfree (NODEb);
+  if (NODEc)
+    Xfree (NODEc);
+  if (FIRST)
+    Xfree (FIRST);
+  if (NEXT)
+    Xfree (NEXT);
+  if (S.st)
+    Xfree (S.st);
+  if (mk)
+    Xfree (mk);
+}
+
+static void 
+all_free (void)
+{
+  int i;
+  temp_free ();
+  if (translate)
+    Xfree (translate);
+  if (g)
+    Xfree (g);
+#ifndef STRUCT
+  for (i = 0; i < MAX_CH; ++i)
+    {
+      if (tb0 && tb0[i])
+	Xfree (tb0[i]);
+      if (tb1 && tb1[i])
+	Xfree (tb1[i]);
+      if (tb2 && tb2[i])
+	Xfree (tb2[i]);
+    }
+  if (tb0)
+    Xfree (tb0);
+  if (tb1)
+    Xfree (tb1);
+  if (tb2)
+    Xfree (tb2);
+#else
+  for (i = 0; i < MAX_CH; ++i)
+    if (tb && tb[i])
+      Xfree (tb[i]);
+  if (tb)
+    Xfree (tb);
+#endif
+}
+
+static int 
+allocate_memory (void)
+{
+  int i, ok = 1;
+  NODEa = (int *) Xmalloc (sizeof (int) * (MAX_M + 1));
+  NODEb = (int *)Xmalloc (sizeof (int) * (MAX_M + 1));
+  NODEc = (int *)Xmalloc (sizeof (int) * (MAX_M + 1));
+  FIRST = (int *)Xmalloc (sizeof (int) * (MAX_N + 1));
+  NEXT = (int *)Xmalloc (sizeof (int) * (MAX_M + 1) * 3);
+  S.st = (int *)Xmalloc (sizeof (int) * MAX_M);
+  mk = (char *)Xmalloc (sizeof (char) * (MAX_N + 1));
+  g = (int *)Xmalloc (sizeof (int) * (MAX_N + 1));
+#ifndef STRUCT
+  tb0 = Xmalloc (sizeof (int *) * MAX_CH);
+  tb1 = Xmalloc (sizeof (int *) * MAX_CH);
+  tb2 = Xmalloc (sizeof (int *) * MAX_CH);
+  for (i = 0; i < MAX_CH; ++i)
+    {
+      if (tb0)
+	if (!(tb0[i] = Xmalloc (sizeof (long) * MAX_L)))
+	    ok = 0;
+      if (tb1)
+	if (!(tb1[i] = Xmalloc (sizeof (long) * MAX_L)))
+	    ok = 0;
+      if (tb2)
+	if (!(tb2[i] = Xmalloc (sizeof (long) * MAX_L)))
+	    ok = 0;
+    }
+
+  if (!(NODEa && NODEb && NODEc && FIRST && NEXT && S.st && mk && g &&
+	tb0 && tb1 && tb2 && ok))
+    {
+      all_free ();
+      return (-1);
+    }
+#else
+  tb = (tb_entry **)Xmalloc (sizeof (struct tb_entry *) * MAX_CH);
+  for (i = 0; i < MAX_CH; ++i)
+    if (tb)
+      if (!(tb[i] = (tb_entry *)Xmalloc (sizeof (struct tb_entry) * MAX_L)))
+	  ok = 0;
+
+  if (!(NODEa && NODEb && NODEc && FIRST && NEXT && S.st && mk && g &&
+	tb && ok))
+    {
+      all_free ();
+      return (-1);
+    }
+#endif
+  return (0);
+}
+
+
+perf_hash_data *
+gen_hash_func (int num, u_char ** keys, int r)
+{
+  int n;
+  perf_hash_data *phd;
+  translate = (u_char *)Xmalloc (sizeof (u_char) * 256);
+  memset(translate, '\0', sizeof (u_char) * 256);  /* [RPAP - Feb 97: WIN32 Port] */
+  make_trans_func (num, keys);
+
+  if (r <= 0)
+    SEED_RANDOM ((long) time ((time_t *) NULL));
+  else
+    SEED_RANDOM (r);
+
+  MAX_M = num + 1;
+
+  MAX_N = MAX_M + MAX_M / 4;
+
+  if (allocate_memory () == -1)
+    return (NULL);
+
+  /* construct an "acyclic" hypergraph */
+  tree_builder (num, keys, &n);
+  /* compute function g */
+  assign (n);
+
+  if (check (num) != 0)
+    FatalError (1, "An error has been detected in the mphf.");
+  temp_free ();
+
+  if (!(phd = (perf_hash_data *)Xmalloc (sizeof (perf_hash_data))))
+    return (NULL);
+
+  memcpy ((void *) g, (const void *) &g[1], n * sizeof (int));
+
+  phd->MAX_L = MAX_L;
+  phd->MAX_N = n;
+  phd->MAX_M = num;
+  phd->MAX_CH = MAX_CH;
+  phd->translate = translate;
+  phd->g = g;
+#ifndef STRUCT
+  phd->tb0 = tb0;
+  phd->tb1 = tb1;
+  phd->tb2 = tb2;
+#else
+  phd->tb = tb;
+#endif
+  return (phd);
+}
+
+int 
+write_perf_hash_data (FILE * f, perf_hash_data * phd)
+{
+  int tot, i;
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONSI(phd->MAX_L);
+  HTONSI(phd->MAX_N);
+  HTONSI(phd->MAX_M);
+  HTONSI(phd->MAX_CH);
+
+  tot = fwrite ((char *) &phd->MAX_L, sizeof (int), 1, f) * sizeof (int);
+  tot += fwrite ((char *) &phd->MAX_N, sizeof (int), 1, f) * sizeof (int);
+  tot += fwrite ((char *) &phd->MAX_M, sizeof (int), 1, f) * sizeof (int);
+  tot += fwrite ((char *) &phd->MAX_CH, sizeof (int), 1, f) * sizeof (int);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHSI(phd->MAX_L);
+  NTOHSI(phd->MAX_N);
+  NTOHSI(phd->MAX_M);
+  NTOHSI(phd->MAX_CH);
+
+  tot += fwrite ((char *) phd->translate, sizeof (u_char), 256, f);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = 0; i < phd->MAX_N + 1; ++i)
+    HTONSI(phd->g[i]);
+
+  tot += fwrite ((char *) phd->g, sizeof (int), phd->MAX_N + 1, f) * sizeof (int);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = 0; i < phd->MAX_N + 1; ++i)
+    NTOHSI(phd->g[i]);
+
+#ifndef STRUCT
+  for (i = 0; i < phd->MAX_CH; ++i)
+    {
+      /* [RPAP - Jan 97: Endian Ordering] */
+      int j;
+      for (j = 0; j < phd->MAX_L; ++j)
+	{
+	  HTONSI(phd->tb0[i][j]);
+	  HTONSI(phd->tb1[i][j]);
+	  HTONSI(phd->tb2[i][j]);
+	}
+
+      tot += fwrite ((char *) phd->tb0[i], sizeof (int), phd->MAX_L, f) *
+        sizeof (int);
+      tot += fwrite ((char *) phd->tb1[i], sizeof (int), phd->MAX_L, f) *
+        sizeof (int);
+      tot += fwrite ((char *) phd->tb2[i], sizeof (int), phd->MAX_L, f) *
+        sizeof (int);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (j = 0; j < phd->MAX_L; ++j)
+	{
+	  NTOHSI(phd->tb0[i][j]);
+	  NTOHSI(phd->tb1[i][j]);
+	  NTOHSI(phd->tb2[i][j]);
+	}
+    }
+#else
+  for (i = 0; i < phd->MAX_CH; ++i)
+    {
+      /* [RPAP - Jan 97: Endian Ordering] */
+      int j;
+      for (j = 0; j < phd->MAX_L; ++j)
+	{
+	  HTONSL(phd->tb[i][j].tb0);
+	  HTONSL(phd->tb[i][j].tb1);
+	  HTONSL(phd->tb[i][j].tb2);
+	}
+
+      tot += fwrite ((char *) phd->tb[i], sizeof (struct tb_entry), phd->MAX_L, f) *
+	sizeof (struct tb_entry);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (j = 0; j < phd->MAX_L; ++j)
+	{
+	  NTOHSL(phd->tb[i][j].tb0);
+	  NTOHSL(phd->tb[i][j].tb1);
+	  NTOHSL(phd->tb[i][j].tb2);
+	}
+    }
+#endif
+  return (tot);
+}
+
+
+perf_hash_data *
+read_perf_hash_data (FILE * f)
+{
+  perf_hash_data *phd;
+  int i, tot, ok = 1;
+  if (!(phd = (perf_hash_data *)Xmalloc (sizeof (perf_hash_data))))
+    return (NULL);
+  tot = fread ((char *) &phd->MAX_L, sizeof (int), 1, f) * sizeof (int);
+  tot += fread ((char *) &phd->MAX_N, sizeof (int), 1, f) * sizeof (int);
+  tot += fread ((char *) &phd->MAX_M, sizeof (int), 1, f) * sizeof (int);
+  tot += fread ((char *) &phd->MAX_CH, sizeof (int), 1, f) * sizeof (int);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHSI(phd->MAX_L);
+  NTOHSI(phd->MAX_N);
+  NTOHSI(phd->MAX_M);
+  NTOHSI(phd->MAX_CH);
+
+  if (tot != 4 * sizeof (int))
+      return (NULL);
+  phd->translate = (u_char *)Xmalloc (sizeof (u_char) * 256);
+  phd->g = (int *)Xmalloc (sizeof (int) * (phd->MAX_N + 1));
+#ifndef STRUCT
+  phd->tb0 = Xmalloc (sizeof (int *) * phd->MAX_CH);
+  phd->tb1 = Xmalloc (sizeof (int *) * phd->MAX_CH);
+  phd->tb2 = Xmalloc (sizeof (int *) * phd->MAX_CH);
+  for (i = 0; i < phd->MAX_CH; ++i)
+    {
+      if (phd->tb0)
+	if (!(phd->tb0[i] = Xmalloc (sizeof (long) * phd->MAX_L)))
+	    ok = 0;
+      if (phd->tb1)
+	if (!(phd->tb1[i] = Xmalloc (sizeof (long) * phd->MAX_L)))
+	    ok = 0;
+      if (phd->tb2)
+	if (!(phd->tb2[i] = Xmalloc (sizeof (long) * phd->MAX_L)))
+	    ok = 0;
+    }
+  if (!(phd->translate && phd->g && phd->tb0 && phd->tb1 && phd->tb2 && ok))
+    {
+      if (phd->translate)
+	Xfree (phd->translate);
+      if (phd->g)
+	Xfree (phd->g);
+      for (i = 0; i < MAX_CH; ++i)
+	{
+	  if (phd->tb0 && phd->tb0[i])
+	    Xfree (phd->tb0[i]);
+	  if (phd->tb1 && phd->tb1[i])
+	    Xfree (phd->tb1[i]);
+	  if (phd->tb2 && phd->tb2[i])
+	    Xfree (phd->tb2[i]);
+	}
+      if (phd->tb0)
+	Xfree (phd->tb0);
+      if (phd->tb1)
+	Xfree (phd->tb1);
+      if (phd->tb2)
+	Xfree (phd->tb2);
+      Xfree (phd);
+      return (NULL);
+    }
+  tot += fread ((char *) phd->translate, sizeof (u_char), 256, f);
+  tot += fread ((char *) phd->g, sizeof (int), phd->MAX_N + 1, f) * sizeof (int);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = 0; i < phd->MAX_N + 1; ++i)
+    NTOHSI(phd->g[i]);
+
+  for (i = 0; i < phd->MAX_CH; ++i)
+    {
+      int j;
+
+      tot += fread ((char *) phd->tb0[i], sizeof (long), phd->MAX_L, f) *
+        sizeof (int);
+      tot += fread ((char *) phd->tb1[i], sizeof (long), phd->MAX_L, f) *
+        sizeof (int);
+      tot += fread ((char *) phd->tb2[i], sizeof (long), phd->MAX_L, f) *
+        sizeof (int);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (j = 0; j < phd->MAX_L; ++j)
+	{
+	  NTOHSI(phd->tb0[i][j]);
+	  NTOHSI(phd->tb1[i][j]);
+	  NTOHSI(phd->tb2[i][j]);
+	}
+    }
+#else
+  phd->tb = (struct tb_entry **)Xmalloc (sizeof (struct tb_entry *) * phd->MAX_CH);
+  for (i = 0; i < phd->MAX_CH; ++i)
+    if (phd->tb)
+      if (!(phd->tb[i] = (struct tb_entry *)Xmalloc (sizeof (struct tb_entry) * phd->MAX_L)))
+	  ok = 0;
+  if (!(phd->translate && phd->g && phd->tb && ok))
+    {
+      if (phd->translate)
+	Xfree (phd->translate);
+      if (phd->g)
+	Xfree (phd->g);
+      for (i = 0; i < MAX_CH; ++i)
+	if (phd->tb && phd->tb[i])
+	  Xfree (phd->tb[i]);
+      if (phd->tb)
+	Xfree (phd->tb);
+      Xfree (phd);
+      return (NULL);
+    }
+  tot += fread ((char *) phd->translate, sizeof (u_char), 256, f);
+  tot += fread ((char *) phd->g, sizeof (int), phd->MAX_N + 1, f) * sizeof (int);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = 0; i < phd->MAX_N + 1; ++i)
+    NTOHSI(phd->g[i]);
+
+  for (i = 0; i < phd->MAX_CH; ++i)
+    {
+      int j;
+
+      tot += fread ((char *) phd->tb[i], sizeof (struct tb_entry), phd->MAX_L, f) *
+	sizeof (struct tb_entry);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      for (j = 0; j < phd->MAX_L; ++j)
+	{
+	  NTOHSL(phd->tb[i][j].tb0);
+	  NTOHSL(phd->tb[i][j].tb1);
+	  NTOHSL(phd->tb[i][j].tb2);
+	}
+    }
+#endif
+  return (phd);
+}
+
+void 
+free_perf_hash (perf_hash_data * phd)
+{
+  int i;
+  if (phd->translate)
+    Xfree (phd->translate);
+  if (phd->g)
+    Xfree (phd->g);
+  for (i = 0; i < phd->MAX_CH; ++i)
+    if (phd->tb && phd->tb[i])
+      Xfree (phd->tb[i]);
+  if (phd->tb)
+    Xfree (phd->tb);
+  Xfree (phd);
+}
+
+
+int 
+perf_hash (perf_hash_data * phd, u_char * s)
+{
+  int u, v, w, i, l;
+  l = *s++;
+  i = (l - 1) % phd->MAX_L;
+  u = v = w = 0;
+  while (l)
+    {
+#ifndef STRUCT
+      if ((u += phd->tb0[phd->translate[*s]][i]) >= phd->MAX_N)
+	u -= phd->MAX_N;
+      if ((v += phd->tb1[phd->translate[*s]][i]) >= phd->MAX_N)
+	v -= phd->MAX_N;
+      if ((w += phd->tb2[phd->translate[*s]][i]) >= phd->MAX_N)
+	w -= phd->MAX_N;
+#else
+      struct tb_entry *tbp = &phd->tb[phd->translate[*s]][i];
+      if ((u += tbp->tb0) >= phd->MAX_N)
+	u -= phd->MAX_N;
+      if ((v += tbp->tb1) >= phd->MAX_N)
+	v -= phd->MAX_N;
+      if ((w += tbp->tb2) >= phd->MAX_N)
+	w -= phd->MAX_N;
+#endif
+      if (++i >= phd->MAX_L)
+	i = 0;
+      --l;
+      ++s;
+    }
+  if (u == v && ++v >= phd->MAX_N)
+    v = 0;
+  if (w == v)
+    {
+      if (++w >= phd->MAX_N)
+	w = 0;
+      if (w == u && ++w >= phd->MAX_N)
+	w = 0;
+    }
+  else if (w == u)
+    {
+      if (++w >= phd->MAX_N)
+	w = 0;
+      if (w == v && ++w >= phd->MAX_N)
+	w = 0;
+    }
+  return ((phd->g[u] ^ phd->g[v] ^ phd->g[w]) > phd->MAX_M) ? 0 :
+    (phd->g[u] ^ phd->g[v] ^ phd->g[w]);
+}
Index: /indexers/branches/3.03a/mgpp/lib/perf_hash.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/perf_hash.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/perf_hash.h	(revision 14757)
@@ -0,0 +1,52 @@
+/**************************************************************************
+ *
+ * perf_hash.h -- Perfect hashing functions
+ * Copyright (C) 1994  Bohdan S. Majewski and Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_PERF_HASH
+#define H_PERF_HASH
+
+struct tb_entry
+  {
+    long tb0, tb1, tb2;
+  };
+
+typedef struct
+  {
+    int MAX_L;
+    int MAX_N;
+    int MAX_M;
+    int MAX_CH;
+    u_char *translate;
+    int *g;
+    struct tb_entry **tb;
+  }
+perf_hash_data;
+
+perf_hash_data *gen_hash_func (int num, u_char ** keys, int r);
+
+int perf_hash (perf_hash_data * phd, u_char * s);
+
+int write_perf_hash_data (FILE * f, perf_hash_data * phd);
+
+void free_perf_hash (perf_hash_data * phd);
+
+perf_hash_data *read_perf_hash_data (FILE * f);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/random.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/random.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/random.cpp	(revision 14757)
@@ -0,0 +1,211 @@
+/**************************************************************************
+ *
+ * random.c -- pseudo random number generator
+ * Copyright (C) 1994  Chris Wallace (csw@bruce.cs.monash.edu.au)
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+/*
+ *	A random number generator called as a function by
+ *	random (iseed)	or	irandm (iseed)
+ *	The parameter should be a pointer to a 2-element long vector.
+ *	The first function returns a double uniform in 0 .. 1.
+ *	The second returns a long integer uniform in 0 .. 2**31-1
+ *	Both update iseed[] in exactly the same way.
+ *	iseed[] must be a 2-element integer vector.
+ *	The initial value of the second element may be anything.
+ *
+ *	The period of the random sequence is 2**32 * (2**32-1)
+ *	The table mt[0:127] is defined by mt[i] = 69069 ** (128-i)
+ */
+
+#define MASK ((long) 593970775)
+/*	or in hex, 23674657	*/
+
+#define SCALE ((double) 1.0 / (1024.0 * 1024.0 * 1024.0 * 2.0))
+/*	i.e. 2 to power -31	*/
+
+static long mt [128] =   {
+      902906369,
+     2030498053,
+     -473499623,
+     1640834941,
+      723406961,
+     1993558325,
+     -257162999,
+    -1627724755,
+      913952737,
+      278845029,
+     1327502073,
+    -1261253155,
+      981676113,
+    -1785280363,
+     1700077033,
+      366908557,
+    -1514479167,
+     -682799163,
+      141955545,
+     -830150595,
+      317871153,
+     1542036469,
+     -946413879,
+    -1950779155,
+      985397153,
+      626515237,
+      530871481,
+      783087261,
+    -1512358895,
+     1031357269,
+    -2007710807,
+    -1652747955,
+    -1867214463,
+      928251525,
+     1243003801,
+    -2132510467,
+     1874683889,
+     -717013323,
+      218254473,
+    -1628774995,
+    -2064896159,
+       69678053,
+      281568889,
+    -2104168611,
+     -165128239,
+     1536495125,
+      -39650967,
+      546594317,
+     -725987007,
+     1392966981,
+     1044706649,
+      687331773,
+    -2051306575,
+     1544302965,
+     -758494647,
+    -1243934099,
+      -75073759,
+      293132965,
+    -1935153095,
+      118929437,
+      807830417,
+    -1416222507,
+    -1550074071,
+      -84903219,
+     1355292929,
+     -380482555,
+    -1818444007,
+     -204797315,
+      170442609,
+    -1636797387,
+      868931593,
+     -623503571,
+     1711722209,
+      381210981,
+     -161547783,
+     -272740131,
+    -1450066095,
+     2116588437,
+     1100682473,
+      358442893,
+    -1529216831,
+     2116152005,
+     -776333095,
+     1265240893,
+     -482278607,
+     1067190005,
+      333444553,
+       86502381,
+      753481377,
+       39000101,
+     1779014585,
+      219658653,
+     -920253679,
+     2029538901,
+     1207761577,
+    -1515772851,
+     -236195711,
+      442620293,
+      423166617,
+    -1763648515,
+     -398436623,
+    -1749358155,
+     -538598519,
+     -652439379,
+      430550625,
+    -1481396507,
+     2093206905,
+    -1934691747,
+     -962631983,
+     1454463253,
+    -1877118871,
+     -291917555,
+    -1711673279,
+      201201733,
+     -474645415,
+      -96764739,
+    -1587365199,
+     1945705589,
+     1303896393,
+     1744831853,
+      381957665,
+     2135332261,
+      -55996615,
+    -1190135011,
+     1790562961,
+    -1493191723,
+      475559465,
+          69069
+		};
+
+double 
+random (long is [2])
+{
+	long it, leh, nit;
+
+	it = is [0];
+	leh = is [1];
+	if (it <= 0)	
+		it = (it + it) ^ MASK;
+	else
+		it = it + it;
+	nit = it - 1;
+/*	to ensure all-ones pattern omitted    */
+	leh = leh * mt[nit & 127] + nit;
+	is [0] = it;    is [1] = leh;
+	if (leh < 0) leh = ~leh;
+	return (SCALE * ((long) (leh | 1)));
+}
+
+
+
+long 
+irandm (long is [2])
+{
+	long it, leh, nit;
+
+	it = is [0];
+	leh = is [1];
+	if (it <= 0)	
+		it = (it + it) ^ MASK;
+	else
+		it = it + it;
+	nit = it - 1;
+/*	to ensure all-ones pattern omitted    */
+	leh = leh * mt[nit & 127] + nit;
+	is [0] = it;    is [1] = leh;
+	if (leh < 0) leh = ~leh;
+	return (leh);
+}
Index: /indexers/branches/3.03a/mgpp/lib/random.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/random.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/random.h	(revision 14757)
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * random.h -- pseudo random number generator
+ * Copyright (C) 1994  Chris Wallace (csw@bruce.cs.monash.edu.au)
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef RANDOM_H
+#define RANDOM_H
+
+/*
+ *	A random number generator called as a function by
+ *	random (iseed)	or	irandm (iseed)
+ *	The parameter should be a pointer to a 2-element long vector.
+ *	The first function returns a double uniform in 0 .. 1.
+ *	The second returns a long integer uniform in 0 .. 2**31-1
+ *	Both update iseed[] in exactly the same way.
+ *	iseed[] must be a 2-element integer vector.
+ *	The initial value of the second element may be anything.
+ *
+ *	The period of the random sequence is 2**32 * (2**32-1)
+ *	The table mt[0:127] is defined by mt[i] = 69069 ** (128-i)
+ */
+
+double random (long is [2]);
+long irandm (long is [2]);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/simplefrenchstem.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/simplefrenchstem.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/simplefrenchstem.cpp	(revision 14757)
@@ -0,0 +1,70 @@
+/**************************************************************************
+ *
+ * simplefrenchstem.c -- a simple french stemmer
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "simplefrenchstem.h"
+#include "unitool.h"
+
+
+/* =========================================================================
+ * Function: simplefrenchstem
+ * Description: a simple french stemmer
+ * Input: a word string with the length in the first byte
+ * Output: the stemmed word
+ * ========================================================================= */
+
+void simplefrenchstem (unsigned char *word) {      
+  unsigned short out[256]; /* temp space */
+  unsigned short *wordstart; /* points to first letter of word */
+  int last;                  /* last points to the last character */
+
+  /* decode */
+  utf8_word_to_unicode (word, out, 255);
+  wordstart = out + 1;
+  last = out[0]-1;
+  
+
+  if (last > 4) {
+    if (wordstart[last]=='x') {
+      if (wordstart[last-1]=='u' && wordstart[last-2]=='a') {
+	wordstart[last-1]='l';
+      }
+      --last;
+
+    } else {
+      if (last>=0 && wordstart[last]=='s') --last;
+      if (last>=0 && wordstart[last]=='r') --last;
+      if (last>=0 && wordstart[last]=='e') --last;
+
+      /* letter with accent e + ' -- there are two possible encodings  */
+      if (last>=0 && wordstart[last]==0xe9) { 
+	--last;
+      } else if (last>=1 && wordstart[last-1]=='e' && wordstart[last]==0x301) {
+	last -= 2; 
+      }
+
+      if (last >= 1 && wordstart[last]==wordstart[last-1]) --last;
+    }  /* end else */
+
+    out[0] = (unsigned char)(last+1);
+  } /* end if (len > 4) */
+
+  /* re-code, make sure the result is not longer than the input */
+  unicode_to_utf8_word (out, word, word[0]+1);
+}
Index: /indexers/branches/3.03a/mgpp/lib/simplefrenchstem.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/simplefrenchstem.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/simplefrenchstem.h	(revision 14757)
@@ -0,0 +1,26 @@
+/**************************************************************************
+ *
+ * simplefrenchstem.h -- a simple french stemmer
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef SIMPLEFRENCHSTEM_H
+#define SIMPLEFRENCHSTEM_H
+
+void simplefrenchstem (unsigned char *word);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/strcasecmp.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/strcasecmp.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/strcasecmp.cpp	(revision 14757)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of California at Berkeley. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific written prior permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcasecmp.c	5.5 (Berkeley) 11/24/87";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static unsigned char charmap[] = {
+	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+	'\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
+	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+int
+strcasecmp(char *s1, char *s2)
+{
+    register unsigned char u1, u2;
+
+    for (;;) {
+	u1 = (unsigned char) *s1++;
+	u2 = (unsigned char) *s2++;
+	if (charmap[u1] != charmap[u2]) {
+	    return charmap[u1] - charmap[u2];
+	}
+	if (u1 == '\0') {
+	    return 0;
+	}
+    }
+}
+
Index: /indexers/branches/3.03a/mgpp/lib/strstr.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/strstr.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/strstr.cpp	(revision 14757)
@@ -0,0 +1,42 @@
+/* strstr.c -- return the offset of one string within another
+   Copyright (C) 1989, 1990 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 program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Written by Mike Rendell <michael@cs.mun.ca>.  */
+
+/* Return the starting address of string S2 in S1;
+   return 0 if it is not found. */
+
+char *
+strstr (char *s1, char *s2)
+{
+  int i;
+  char *p1;
+  char *p2;
+  char *s = s1;
+
+  for (p2 = s2, i = 0; *s; p2 = s2, ++i, ++s)
+    {
+      for (p1 = s; *p1 && *p2 && *p1 == *p2; ++p1, ++p2)
+	;
+      if (!*p2)
+	break;
+    }
+  if (!*p2)
+    return s1 + i;
+
+  return 0;
+}
Index: /indexers/branches/3.03a/mgpp/lib/sysfuncs.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/sysfuncs.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/sysfuncs.cpp	(revision 14757)
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+void *bcopy(void *s, void *d, int n)
+{ return memcpy(d, s, n);
+}
+
Index: /indexers/branches/3.03a/mgpp/lib/sysfuncs.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/sysfuncs.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/sysfuncs.h	(revision 14757)
@@ -0,0 +1,388 @@
+/* System dependent definitions for GNU tar.
+   Copyright (C) 1994 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 program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * [TS:Aug/95]
+ * Based on code from system.h file in GNU's tar package 
+ *
+ */
+
+#ifndef SYSFUNCS_H
+#define SYSFUNCS_H
+
+#include <sys/stat.h>
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef HAVE_CONFIG_H
+# ifdef __WIN32__
+#  include <WIN32cfg.h>
+# else
+#  include <config.h>
+# endif
+#endif
+
+/* Declare alloca.  AIX requires this to be the first thing in the file.  */
+
+#ifdef __GNUC__
+#ifndef alloca
+#define alloca __builtin_alloca
+#endif
+#else
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#else
+#ifdef _AIX
+#pragma alloca
+#else
+#ifndef alloca
+char *alloca ();
+#endif
+#endif
+#endif
+#endif
+
+#include <sys/types.h>
+
+/* ------------------------------------------------- */
+/* [TS:Aug/95]
+ * Some extra include files that mg needs
+ */
+#include <stdlib.h>
+#include <math.h>
+
+#ifndef log2
+# ifndef M_LN2
+#  define M_LN2 0.69314718055994530942
+# endif
+# define log2(x) (log(x)/M_LN2)
+#endif
+
+
+#ifndef HAVE_SETBUFFER
+#ifdef __CYGWIN__ 
+/* Cygwin has setbuffer in stdio.h, but can't link against it!! */
+#include <stdio.h>
+#endif
+# define setbuffer(f, b, s)  setvbuf(f, b, _IOFBF, s)
+#endif
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#if defined(__MSDOS__)  && !defined(__WIN32__)
+# define SHORT_SUFFIX 1
+#endif
+
+
+
+#include <assert.h>
+
+/* ------------------------------------------------- */
+
+/* Declare a generic pointer type.  */
+#if __STDC__ || defined(__TURBOC__)
+#define voidstar void *
+#else
+#define voidstar char *
+#endif
+
+/* Declare ISASCII.  */
+
+#include <ctype.h>
+
+#if STDC_HEADERS
+#define ISASCII(Char) 1
+#else
+#ifdef isascii
+#define ISASCII(Char) isascii (Char)
+#else
+#if HAVE_ISASCII
+#define ISASCII(Char) isascii (Char)
+#else
+#define ISASCII(Char) 1
+#endif
+#endif
+#endif
+
+
+/* ------------------------------------------------- */
+/* [TS:Aug/95] 
+ * The following is copied from GNU Autoconf.Info (1.1)   
+ * It sets up the approriate string and memory functions.
+ */
+
+#if STDC_HEADERS || HAVE_STRING_H
+#include <string.h>
+   /* An ANSI string.h and pre-ANSI memory.h might conflict */
+#if !STDC_HEADERS && HAVE_MEMORY_H
+#include <memory.h>
+#endif /* not STDC_HEADERS and HAVE_MEMORY_H */
+#ifndef index
+/*#define index strchr 
+ *
+ * this is stuffing up our code so its commented out */
+#endif
+#ifndef rindex
+#define rindex strrchr
+#endif
+
+#ifdef __cplusplus /* compiling for C++ */
+#include <stdlib.h>
+#ifndef __bcopy
+inline void *bcopy(void *s, void *d, int n)
+{ return memcpy(d, s, n);
+}
+#define __bcopy 1
+#endif
+#ifndef __bcmp
+inline int bcmp(void *s1, void *s2, int n)
+{ return memcmp(s1, s2, n);
+}
+#define __bcmp 1
+#endif
+#ifndef __bzero
+inline void bzero(void *m, int n)
+{ memset(m, 0, n);
+}
+#define __bzero 1
+#endif
+#else              /* compiling for C */
+#ifndef bcopy
+#define bcopy(s, d, n) memcpy((d), (s), (n))
+#endif
+#ifndef bcmp
+#define bcmp(s1, s2, n) memcmp((s1), (s2), (n))
+#endif
+#ifndef bzero
+#define bzero(s, n) memset((s), 0, (n))
+#endif
+#endif
+
+#else /* not STDC_HEADERS and not HAVE_STRING_H */
+#include <strings.h>
+   /* memory.h and strings.h conflict on some systems */
+#endif
+/* ------------------------------------------------- */
+
+
+/* Declare errno.  */
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+/* Declare open parameters.  */
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#include <sys/file.h>
+#endif
+
+#ifndef	O_BINARY
+#define O_BINARY 0
+#endif
+#ifndef O_CREAT
+#define O_CREAT 0
+#endif
+#ifndef	O_NDELAY
+#define O_NDELAY 0
+#endif
+#ifndef	O_RDONLY
+#define O_RDONLY 0
+#endif
+#ifndef O_RDWR
+#define O_RDWR 2
+#endif
+
+/* Declare file status routines and bits.  */
+
+#ifdef STAT_MACROS_BROKEN
+#undef S_ISBLK
+#undef S_ISCHR
+#undef S_ISDIR
+#undef S_ISFIFO
+#undef S_ISLNK
+#undef S_ISMPB
+#undef S_ISMPC
+#undef S_ISNWK
+#undef S_ISREG
+#undef S_ISSOCK
+#endif
+
+/* On MSDOS, there are missing things from <sys/stat.h>.  */
+#ifdef __MSDOS__
+#define S_ISUID 0
+#define S_ISGID 0
+#define S_ISVTX 0
+#endif
+
+#ifndef S_ISREG			/* POSIX.1 stat stuff missing */
+#define mode_t unsigned short
+#endif
+#if !defined(S_ISBLK) && defined(S_IFBLK)
+#define S_ISBLK(Mode) (((Mode) & S_IFMT) == S_IFBLK)
+#endif
+#if !defined(S_ISCHR) && defined(S_IFCHR)
+#define S_ISCHR(Mode) (((Mode) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISDIR) && defined(S_IFDIR)
+#define S_ISDIR(Mode) (((Mode) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG) && defined(S_IFREG)
+#define S_ISREG(Mode) (((Mode) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISFIFO) && defined(S_IFIFO)
+#define S_ISFIFO(Mode) (((Mode) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+#define S_ISLNK(Mode) (((Mode) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK) && defined(S_IFSOCK)
+#define S_ISSOCK(Mode) (((Mode) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISMPB) && defined(S_IFMPB)	/* V7 */
+#define S_ISMPB(Mode) (((Mode) & S_IFMT) == S_IFMPB)
+#define S_ISMPC(Mode) (((Mode) & S_IFMT) == S_IFMPC)
+#endif
+#if !defined(S_ISNWK) && defined(S_IFNWK)	/* HP/UX */
+#define S_ISNWK(Mode) (((Mode) & S_IFMT) == S_IFNWK)
+#endif
+
+#if !defined(S_ISCTG) && defined(S_IFCTG)	/* contiguous file */
+#define S_ISCTG(Mode) (((Mode) & S_IFMT) == S_IFCTG)
+#endif
+#if !defined(S_ISVTX)
+#define S_ISVTX 0001000
+#endif
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#if !defined(_POSIX_SOURCE) && !defined(__WIN32__)
+#include <sys/param.h>
+#endif
+
+/* Include <unistd.h> before any preprocessor test of _POSIX_VERSION.  */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+
+/* Declare standard functions.  */
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+voidstar malloc ();
+voidstar realloc ();
+char *getenv ();
+#endif
+
+#include <stdio.h>
+
+#ifndef _POSIX_VERSION
+#ifdef __MSDOS__
+#include <io.h>
+#else
+off_t lseek ();
+#endif
+#endif
+
+#ifndef __WIN32__
+#include <pathmax.h>
+#endif
+
+/* Until getoptold function is declared in getopt.h, we need this here for
+   struct option.  */
+/*#include <getopt.h>*/
+
+#ifdef WITH_DMALLOC
+#undef HAVE_VALLOC
+#define DMALLOC_FUNC_CHECK
+#include <dmalloc.h>
+#endif
+
+/* Prototypes for external functions.  */
+
+#ifndef __P
+#if PROTOTYPES
+#define __P(Args) Args
+#else
+#define __P(Args) ()
+#endif
+#endif
+
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+/*** setlocale is ansi and posix...(jrm21)
+#if !HAVE_SETLOCALE
+#define setlocale(Category, Locale)
+#endif
+***/
+
+#if ENABLE_NLS
+#include <libintl.h>
+#define _(Text) gettext (Text)
+#else
+#define textdomain(Domain)
+#define _(Text) Text
+#endif
+
+/* Library modules.  */
+
+#ifdef HAVE_VPRINTF
+void error __P ((int, int, const char *,...));
+#else
+void error ();
+#endif
+
+#ifndef HAVE_STRSTR
+char *strstr __P ((const char *, const char *));
+#endif
+
+/* [RB/TS:Oct/95] commented out. Used by lib/gmalloc.c - but it defines it anyway ???
+ *#ifndef HAVE_VALLOC
+ *#define valloc(Size) malloc (Size)
+ *#endif
+ */
+
+voidstar xmalloc __P ((size_t));
+voidstar xrealloc __P ((voidstar, size_t));
+char *xstrdup __P ((const char *));
+
+/* [TS:Aug/95] 
+ * These were required by files which referred 
+ * to these as function pointers. 
+ * e.g. huffman.c - fread,  mgfelics.c - fgetc
+ */
+#ifndef HAVE_FREAD_DECL
+extern size_t   fread __P ((void *, size_t, size_t, FILE *));
+#endif
+#ifndef HAVE_FGETC_DECL
+extern int      fgetc __P ((FILE *));
+#endif
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifndef u_long
+# define u_long unsigned long
+#endif
+#ifndef u_char
+# define u_char unsigned char
+#endif
+
+
+#endif /* SYSFUNCS_H */
Index: /indexers/branches/3.03a/mgpp/lib/unitool.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/unitool.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/unitool.cpp	(revision 14757)
@@ -0,0 +1,1758 @@
+#include "unitool.h"
+#include "sysfuncs.h"
+
+
+/* unicode_cat_data is a combination of the letter, digit, and
+ * space information in a form that is quick to look up.
+ * The information about each byte is stored in two bits
+ *
+ * 00 - neither letter, digit or space
+ * 01 - letter
+ * 10 - space
+ * 11 - digit
+ *
+ * You can test for letter | space by looking at the right
+ * column
+ */
+static unsigned long *unicode_cat_data=NULL;
+
+
+typedef struct unidecompose {
+  unsigned short ch;
+  unsigned short str[3];
+} unidecompose;
+
+typedef struct unirelate {
+  unsigned short ch1;
+  unsigned short ch2;
+} unirelate;
+
+typedef struct unirange {
+  unsigned short first;
+  unsigned short last;
+} unirange;
+
+
+
+/* This decomposition data only includes canonical decompositional
+ * characters.  Any unused bytes are set to 0x0. */
+
+#define NUM_DECOMPOSE_INFO 1269
+static const unidecompose decompose_info[NUM_DECOMPOSE_INFO] = {
+  {0xC0,0x41,0x300,0x0}, {0xC1,0x41,0x301,0x0}, {0xC2,0x41,0x302,0x0}, 
+  {0xC3,0x41,0x303,0x0}, {0xC4,0x41,0x308,0x0}, {0xC5,0x41,0x30A,0x0}, 
+  {0xC7,0x43,0x327,0x0}, {0xC8,0x45,0x300,0x0}, {0xC9,0x45,0x301,0x0}, 
+  {0xCA,0x45,0x302,0x0}, {0xCB,0x45,0x308,0x0}, {0xCC,0x49,0x300,0x0}, 
+  {0xCD,0x49,0x301,0x0}, {0xCE,0x49,0x302,0x0}, {0xCF,0x49,0x308,0x0}, 
+  {0xD1,0x4E,0x303,0x0}, {0xD2,0x4F,0x300,0x0}, {0xD3,0x4F,0x301,0x0}, 
+  {0xD4,0x4F,0x302,0x0}, {0xD5,0x4F,0x303,0x0}, {0xD6,0x4F,0x308,0x0}, 
+  {0xD9,0x55,0x300,0x0}, {0xDA,0x55,0x301,0x0}, {0xDB,0x55,0x302,0x0}, 
+  {0xDC,0x55,0x308,0x0}, {0xDD,0x59,0x301,0x0}, {0xE0,0x61,0x300,0x0}, 
+  {0xE1,0x61,0x301,0x0}, {0xE2,0x61,0x302,0x0}, {0xE3,0x61,0x303,0x0}, 
+  {0xE4,0x61,0x308,0x0}, {0xE5,0x61,0x30A,0x0}, {0xE7,0x63,0x327,0x0}, 
+  {0xE8,0x65,0x300,0x0}, {0xE9,0x65,0x301,0x0}, {0xEA,0x65,0x302,0x0}, 
+  {0xEB,0x65,0x308,0x0}, {0xEC,0x69,0x300,0x0}, {0xED,0x69,0x301,0x0}, 
+  {0xEE,0x69,0x302,0x0}, {0xEF,0x69,0x308,0x0}, {0xF1,0x6E,0x303,0x0}, 
+  {0xF2,0x6F,0x300,0x0}, {0xF3,0x6F,0x301,0x0}, {0xF4,0x6F,0x302,0x0}, 
+  {0xF5,0x6F,0x303,0x0}, {0xF6,0x6F,0x308,0x0}, {0xF9,0x75,0x300,0x0}, 
+  {0xFA,0x75,0x301,0x0}, {0xFB,0x75,0x302,0x0}, {0xFC,0x75,0x308,0x0}, 
+  {0xFD,0x79,0x301,0x0}, {0xFF,0x79,0x308,0x0}, {0x100,0x41,0x304,0x0}, 
+  {0x101,0x61,0x304,0x0}, {0x102,0x41,0x306,0x0}, {0x103,0x61,0x306,0x0}, 
+  {0x104,0x41,0x328,0x0}, {0x105,0x61,0x328,0x0}, {0x106,0x43,0x301,0x0}, 
+  {0x107,0x63,0x301,0x0}, {0x108,0x43,0x302,0x0}, {0x109,0x63,0x302,0x0}, 
+  {0x10A,0x43,0x307,0x0}, {0x10B,0x63,0x307,0x0}, {0x10C,0x43,0x30C,0x0}, 
+  {0x10D,0x63,0x30C,0x0}, {0x10E,0x44,0x30C,0x0}, {0x10F,0x64,0x30C,0x0}, 
+  {0x112,0x45,0x304,0x0}, {0x113,0x65,0x304,0x0}, {0x114,0x45,0x306,0x0}, 
+  {0x115,0x65,0x306,0x0}, {0x116,0x45,0x307,0x0}, {0x117,0x65,0x307,0x0}, 
+  {0x118,0x45,0x328,0x0}, {0x119,0x65,0x328,0x0}, {0x11A,0x45,0x30C,0x0}, 
+  {0x11B,0x65,0x30C,0x0}, {0x11C,0x47,0x302,0x0}, {0x11D,0x67,0x302,0x0}, 
+  {0x11E,0x47,0x306,0x0}, {0x11F,0x67,0x306,0x0}, {0x120,0x47,0x307,0x0}, 
+  {0x121,0x67,0x307,0x0}, {0x122,0x47,0x327,0x0}, {0x123,0x67,0x327,0x0}, 
+  {0x124,0x48,0x302,0x0}, {0x125,0x68,0x302,0x0}, {0x128,0x49,0x303,0x0}, 
+  {0x129,0x69,0x303,0x0}, {0x12A,0x49,0x304,0x0}, {0x12B,0x69,0x304,0x0}, 
+  {0x12C,0x49,0x306,0x0}, {0x12D,0x69,0x306,0x0}, {0x12E,0x49,0x328,0x0}, 
+  {0x12F,0x69,0x328,0x0}, {0x130,0x49,0x307,0x0}, {0x134,0x4A,0x302,0x0}, 
+  {0x135,0x6A,0x302,0x0}, {0x136,0x4B,0x327,0x0}, {0x137,0x6B,0x327,0x0}, 
+  {0x139,0x4C,0x301,0x0}, {0x13A,0x6C,0x301,0x0}, {0x13B,0x4C,0x327,0x0}, 
+  {0x13C,0x6C,0x327,0x0}, {0x13D,0x4C,0x30C,0x0}, {0x13E,0x6C,0x30C,0x0}, 
+  {0x143,0x4E,0x301,0x0}, {0x144,0x6E,0x301,0x0}, {0x145,0x4E,0x327,0x0}, 
+  {0x146,0x6E,0x327,0x0}, {0x147,0x4E,0x30C,0x0}, {0x148,0x6E,0x30C,0x0}, 
+  {0x14C,0x4F,0x304,0x0}, {0x14D,0x6F,0x304,0x0}, {0x14E,0x4F,0x306,0x0}, 
+  {0x14F,0x6F,0x306,0x0}, {0x150,0x4F,0x30B,0x0}, {0x151,0x6F,0x30B,0x0}, 
+  {0x154,0x52,0x301,0x0}, {0x155,0x72,0x301,0x0}, {0x156,0x52,0x327,0x0}, 
+  {0x157,0x72,0x327,0x0}, {0x158,0x52,0x30C,0x0}, {0x159,0x72,0x30C,0x0}, 
+  {0x15A,0x53,0x301,0x0}, {0x15B,0x73,0x301,0x0}, {0x15C,0x53,0x302,0x0}, 
+  {0x15D,0x73,0x302,0x0}, {0x15E,0x53,0x327,0x0}, {0x15F,0x73,0x327,0x0}, 
+  {0x160,0x53,0x30C,0x0}, {0x161,0x73,0x30C,0x0}, {0x162,0x54,0x327,0x0}, 
+  {0x163,0x74,0x327,0x0}, {0x164,0x54,0x30C,0x0}, {0x165,0x74,0x30C,0x0}, 
+  {0x168,0x55,0x303,0x0}, {0x169,0x75,0x303,0x0}, {0x16A,0x55,0x304,0x0}, 
+  {0x16B,0x75,0x304,0x0}, {0x16C,0x55,0x306,0x0}, {0x16D,0x75,0x306,0x0}, 
+  {0x16E,0x55,0x30A,0x0}, {0x16F,0x75,0x30A,0x0}, {0x170,0x55,0x30B,0x0}, 
+  {0x171,0x75,0x30B,0x0}, {0x172,0x55,0x328,0x0}, {0x173,0x75,0x328,0x0}, 
+  {0x174,0x57,0x302,0x0}, {0x175,0x77,0x302,0x0}, {0x176,0x59,0x302,0x0}, 
+  {0x177,0x79,0x302,0x0}, {0x178,0x59,0x308,0x0}, {0x179,0x5A,0x301,0x0}, 
+  {0x17A,0x7A,0x301,0x0}, {0x17B,0x5A,0x307,0x0}, {0x17C,0x7A,0x307,0x0}, 
+  {0x17D,0x5A,0x30C,0x0}, {0x17E,0x7A,0x30C,0x0}, {0x1A0,0x4F,0x31B,0x0}, 
+  {0x1A1,0x6F,0x31B,0x0}, {0x1AF,0x55,0x31B,0x0}, {0x1B0,0x75,0x31B,0x0}, 
+  {0x1CD,0x41,0x30C,0x0}, {0x1CE,0x61,0x30C,0x0}, {0x1CF,0x49,0x30C,0x0}, 
+  {0x1D0,0x69,0x30C,0x0}, {0x1D1,0x4F,0x30C,0x0}, {0x1D2,0x6F,0x30C,0x0}, 
+  {0x1D3,0x55,0x30C,0x0}, {0x1D4,0x75,0x30C,0x0}, {0x1D5,0xDC,0x304,0x0}, 
+  {0x1D6,0xFC,0x304,0x0}, {0x1D7,0xDC,0x301,0x0}, {0x1D8,0xFC,0x301,0x0}, 
+  {0x1D9,0xDC,0x30C,0x0}, {0x1DA,0xFC,0x30C,0x0}, {0x1DB,0xDC,0x300,0x0}, 
+  {0x1DC,0xFC,0x300,0x0}, {0x1DE,0xC4,0x304,0x0}, {0x1DF,0xE4,0x304,0x0}, 
+  {0x1E0,0x41,0x307,0x304}, {0x1E1,0x61,0x307,0x304}, {0x1E2,0xC6,0x304,0x0}, 
+  {0x1E3,0xE6,0x304,0x0}, {0x1E6,0x47,0x30C,0x0}, {0x1E7,0x67,0x30C,0x0}, 
+  {0x1E8,0x4B,0x30C,0x0}, {0x1E9,0x6B,0x30C,0x0}, {0x1EA,0x4F,0x328,0x0}, 
+  {0x1EB,0x6F,0x328,0x0}, {0x1EC,0x1EA,0x304,0x0}, {0x1ED,0x1EB,0x304,0x0}, 
+  {0x1EE,0x1B7,0x30C,0x0}, {0x1EF,0x292,0x30C,0x0}, {0x1F0,0x6A,0x30C,0x0}, 
+  {0x1F4,0x47,0x301,0x0}, {0x1F5,0x67,0x301,0x0}, {0x1FA,0xC5,0x301,0x0}, 
+  {0x1FB,0xE5,0x301,0x0}, {0x1FC,0xC6,0x301,0x0}, {0x1FD,0xE6,0x301,0x0}, 
+  {0x1FE,0xD8,0x301,0x0}, {0x1FF,0xF8,0x301,0x0}, {0x200,0x41,0x30F,0x0}, 
+  {0x201,0x61,0x30F,0x0}, {0x202,0x41,0x311,0x0}, {0x203,0x61,0x311,0x0}, 
+  {0x204,0x45,0x30F,0x0}, {0x205,0x65,0x30F,0x0}, {0x206,0x45,0x311,0x0}, 
+  {0x207,0x65,0x311,0x0}, {0x208,0x49,0x30F,0x0}, {0x209,0x69,0x30F,0x0}, 
+  {0x20A,0x49,0x311,0x0}, {0x20B,0x69,0x311,0x0}, {0x20C,0x4F,0x30F,0x0}, 
+  {0x20D,0x6F,0x30F,0x0}, {0x20E,0x4F,0x311,0x0}, {0x20F,0x6F,0x311,0x0}, 
+  {0x210,0x52,0x30F,0x0}, {0x211,0x72,0x30F,0x0}, {0x212,0x52,0x311,0x0}, 
+  {0x213,0x72,0x311,0x0}, {0x214,0x55,0x30F,0x0}, {0x215,0x75,0x30F,0x0}, 
+  {0x216,0x55,0x311,0x0}, {0x217,0x75,0x311,0x0}, {0x310,0x306,0x307,0x0}, 
+  {0x340,0x300,0x0,0x0}, {0x341,0x301,0x0,0x0}, {0x343,0x313,0x0,0x0}, 
+  {0x344,0x308,0x30D,0x0}, {0x374,0x2B9,0x0,0x0}, {0x37E,0x3B,0x0,0x0}, 
+  {0x385,0xA8,0x30D,0x0}, {0x386,0x391,0x30D,0x0}, {0x387,0xB7,0x0,0x0}, 
+  {0x388,0x395,0x30D,0x0}, {0x389,0x397,0x30D,0x0}, {0x38A,0x399,0x30D,0x0}, 
+  {0x38C,0x39F,0x30D,0x0}, {0x38E,0x3A5,0x30D,0x0}, {0x38F,0x3A9,0x30D,0x0}, 
+  {0x390,0x3B9,0x344,0x0}, {0x3AA,0x399,0x308,0x0}, {0x3AB,0x3A5,0x308,0x0}, 
+  {0x3AC,0x3B1,0x30D,0x0}, {0x3AD,0x3B5,0x30D,0x0}, {0x3AE,0x3B7,0x30D,0x0}, 
+  {0x3AF,0x3B9,0x30D,0x0}, {0x3B0,0x3C5,0x344,0x0}, {0x3CA,0x3B9,0x308,0x0}, 
+  {0x3CB,0x3C5,0x308,0x0}, {0x3CC,0x3BF,0x30D,0x0}, {0x3CD,0x3C5,0x30D,0x0}, 
+  {0x3CE,0x3C9,0x30D,0x0}, {0x3D3,0x3D2,0x30D,0x0}, {0x3D4,0x3D2,0x308,0x0}, 
+  {0x401,0x415,0x308,0x0}, {0x403,0x413,0x301,0x0}, {0x407,0x406,0x308,0x0}, 
+  {0x40C,0x41A,0x301,0x0}, {0x40E,0x423,0x306,0x0}, {0x419,0x418,0x306,0x0}, 
+  {0x439,0x438,0x306,0x0}, {0x451,0x435,0x308,0x0}, {0x453,0x433,0x301,0x0}, 
+  {0x457,0x456,0x308,0x0}, {0x45C,0x43A,0x301,0x0}, {0x45E,0x443,0x306,0x0}, 
+  {0x476,0x474,0x30F,0x0}, {0x477,0x475,0x30F,0x0}, {0x4C1,0x416,0x306,0x0}, 
+  {0x4C2,0x436,0x306,0x0}, {0x4D0,0x410,0x306,0x0}, {0x4D1,0x430,0x306,0x0}, 
+  {0x4D2,0x410,0x308,0x0}, {0x4D3,0x430,0x308,0x0}, {0x4D6,0x415,0x306,0x0}, 
+  {0x4D7,0x435,0x306,0x0}, {0x4DA,0x4D8,0x308,0x0}, {0x4DB,0x4D9,0x308,0x0}, 
+  {0x4DC,0x416,0x308,0x0}, {0x4DD,0x436,0x308,0x0}, {0x4DE,0x417,0x308,0x0}, 
+  {0x4DF,0x437,0x308,0x0}, {0x4E2,0x418,0x304,0x0}, {0x4E3,0x438,0x304,0x0}, 
+  {0x4E4,0x418,0x308,0x0}, {0x4E5,0x438,0x308,0x0}, {0x4E6,0x41E,0x308,0x0}, 
+  {0x4E7,0x43E,0x308,0x0}, {0x4EA,0x4E8,0x308,0x0}, {0x4EB,0x4E9,0x308,0x0}, 
+  {0x4EE,0x423,0x304,0x0}, {0x4EF,0x443,0x304,0x0}, {0x4F0,0x423,0x308,0x0}, 
+  {0x4F1,0x443,0x308,0x0}, {0x4F2,0x423,0x30B,0x0}, {0x4F3,0x443,0x30B,0x0}, 
+  {0x4F4,0x427,0x308,0x0}, {0x4F5,0x447,0x308,0x0}, {0x4F8,0x42B,0x308,0x0}, 
+  {0x4F9,0x44B,0x308,0x0}, {0x929,0x928,0x93C,0x0}, {0x931,0x930,0x93C,0x0}, 
+  {0x934,0x933,0x93C,0x0}, {0x958,0x915,0x93C,0x0}, {0x959,0x916,0x93C,0x0}, 
+  {0x95A,0x917,0x93C,0x0}, {0x95B,0x91C,0x93C,0x0}, {0x95C,0x921,0x93C,0x0}, 
+  {0x95D,0x922,0x93C,0x0}, {0x95E,0x92B,0x93C,0x0}, {0x95F,0x92F,0x93C,0x0}, 
+  {0x9B0,0x9AC,0x9BC,0x0}, {0x9CB,0x9C7,0x9BE,0x0}, {0x9CC,0x9C7,0x9D7,0x0}, 
+  {0x9DC,0x9A1,0x9BC,0x0}, {0x9DD,0x9A2,0x9BC,0x0}, {0x9DF,0x9AF,0x9BC,0x0}, 
+  {0xA59,0xA16,0xA3C,0x0}, {0xA5A,0xA17,0xA3C,0x0}, {0xA5B,0xA1C,0xA3C,0x0}, 
+  {0xA5C,0xA21,0xA3C,0x0}, {0xA5E,0xA2B,0xA3C,0x0}, {0xB48,0xB47,0xB56,0x0}, 
+  {0xB4B,0xB47,0xB3E,0x0}, {0xB4C,0xB47,0xB57,0x0}, {0xB5C,0xB21,0xB3C,0x0}, 
+  {0xB5D,0xB22,0xB3C,0x0}, {0xB5F,0xB2F,0xB3C,0x0}, {0xB94,0xB92,0xBD7,0x0}, 
+  {0xBCA,0xBC6,0xBBE,0x0}, {0xBCB,0xBC7,0xBBE,0x0}, {0xBCC,0xBC6,0xBD7,0x0}, 
+  {0xC48,0xC46,0xC56,0x0}, {0xCC0,0xCBF,0xCD5,0x0}, {0xCC7,0xCC6,0xCD5,0x0}, 
+  {0xCC8,0xCC6,0xCD6,0x0}, {0xCCA,0xCC6,0xCC2,0x0}, {0xCCB,0xCC6,0xCC2,0xCD5}, 
+  {0xD4A,0xD46,0xD3E,0x0}, {0xD4B,0xD47,0xD3E,0x0}, {0xD4C,0xD46,0xD57,0x0}, 
+  {0xE33,0xE4D,0xE32,0x0}, {0xEB3,0xECD,0xEB2,0x0}, {0xF43,0xF42,0xFB7,0x0}, 
+  {0xF4D,0xF4C,0xFB7,0x0}, {0xF52,0xF51,0xFB7,0x0}, {0xF57,0xF56,0xFB7,0x0}, 
+  {0xF5C,0xF5B,0xFB7,0x0}, {0xF69,0xF40,0xFB5,0x0}, {0xF73,0xF72,0xF71,0x0}, 
+  {0xF75,0xF71,0xF74,0x0}, {0xF76,0xFB2,0xF80,0x0}, {0xF77,0xF76,0xF71,0x0}, 
+  {0xF78,0xFB3,0xF80,0x0}, {0xF79,0xF78,0xF71,0x0}, {0xF81,0xF80,0xF71,0x0}, 
+  {0xF93,0xF92,0xFB7,0x0}, {0xF9D,0xF9C,0xFB7,0x0}, {0xFA2,0xFA1,0xFB7,0x0}, 
+  {0xFA7,0xFA6,0xFB7,0x0}, {0xFAC,0xFAB,0xFB7,0x0}, {0xFB9,0xF90,0xFB5,0x0}, 
+  {0x1E00,0x41,0x325,0x0}, {0x1E01,0x61,0x325,0x0}, {0x1E02,0x42,0x307,0x0}, 
+  {0x1E03,0x62,0x307,0x0}, {0x1E04,0x42,0x323,0x0}, {0x1E05,0x62,0x323,0x0}, 
+  {0x1E06,0x42,0x331,0x0}, {0x1E07,0x62,0x331,0x0}, {0x1E08,0xC7,0x301,0x0}, 
+  {0x1E09,0xE7,0x301,0x0}, {0x1E0A,0x44,0x307,0x0}, {0x1E0B,0x64,0x307,0x0}, 
+  {0x1E0C,0x44,0x323,0x0}, {0x1E0D,0x64,0x323,0x0}, {0x1E0E,0x44,0x331,0x0}, 
+  {0x1E0F,0x64,0x331,0x0}, {0x1E10,0x44,0x327,0x0}, {0x1E11,0x64,0x327,0x0}, 
+  {0x1E12,0x44,0x32D,0x0}, {0x1E13,0x64,0x32D,0x0}, {0x1E14,0x112,0x300,0x0}, 
+  {0x1E15,0x113,0x300,0x0}, {0x1E16,0x112,0x301,0x0}, {0x1E17,0x113,0x301,0x0}, 
+  {0x1E18,0x45,0x32D,0x0}, {0x1E19,0x65,0x32D,0x0}, {0x1E1A,0x45,0x330,0x0}, 
+  {0x1E1B,0x65,0x330,0x0}, {0x1E1C,0x114,0x327,0x0}, {0x1E1D,0x115,0x327,0x0}, 
+  {0x1E1E,0x46,0x307,0x0}, {0x1E1F,0x66,0x307,0x0}, {0x1E20,0x47,0x304,0x0}, 
+  {0x1E21,0x67,0x304,0x0}, {0x1E22,0x48,0x307,0x0}, {0x1E23,0x68,0x307,0x0}, 
+  {0x1E24,0x48,0x323,0x0}, {0x1E25,0x68,0x323,0x0}, {0x1E26,0x48,0x308,0x0}, 
+  {0x1E27,0x68,0x308,0x0}, {0x1E28,0x48,0x327,0x0}, {0x1E29,0x68,0x327,0x0}, 
+  {0x1E2A,0x48,0x32E,0x0}, {0x1E2B,0x68,0x32E,0x0}, {0x1E2C,0x49,0x330,0x0}, 
+  {0x1E2D,0x69,0x330,0x0}, {0x1E2E,0xCF,0x301,0x0}, {0x1E2F,0xEF,0x301,0x0}, 
+  {0x1E30,0x4B,0x301,0x0}, {0x1E31,0x6B,0x301,0x0}, {0x1E32,0x4B,0x323,0x0}, 
+  {0x1E33,0x6B,0x323,0x0}, {0x1E34,0x4B,0x331,0x0}, {0x1E35,0x6B,0x331,0x0}, 
+  {0x1E36,0x4C,0x323,0x0}, {0x1E37,0x6C,0x323,0x0}, {0x1E38,0x1E36,0x304,0x0}, 
+  {0x1E39,0x1E37,0x304,0x0}, {0x1E3A,0x4C,0x331,0x0}, {0x1E3B,0x6C,0x331,0x0}, 
+  {0x1E3C,0x4C,0x32D,0x0}, {0x1E3D,0x6C,0x32D,0x0}, {0x1E3E,0x4D,0x301,0x0}, 
+  {0x1E3F,0x6D,0x301,0x0}, {0x1E40,0x4D,0x307,0x0}, {0x1E41,0x6D,0x307,0x0}, 
+  {0x1E42,0x4D,0x323,0x0}, {0x1E43,0x6D,0x323,0x0}, {0x1E44,0x4E,0x307,0x0}, 
+  {0x1E45,0x6E,0x307,0x0}, {0x1E46,0x4E,0x323,0x0}, {0x1E47,0x6E,0x323,0x0}, 
+  {0x1E48,0x4E,0x331,0x0}, {0x1E49,0x6E,0x331,0x0}, {0x1E4A,0x4E,0x32D,0x0}, 
+  {0x1E4B,0x6E,0x32D,0x0}, {0x1E4C,0xD5,0x301,0x0}, {0x1E4D,0xF5,0x301,0x0}, 
+  {0x1E4E,0xD5,0x308,0x0}, {0x1E4F,0xF5,0x308,0x0}, {0x1E50,0x14C,0x300,0x0}, 
+  {0x1E51,0x14D,0x300,0x0}, {0x1E52,0x14C,0x301,0x0}, {0x1E53,0x14D,0x301,0x0}, 
+  {0x1E54,0x50,0x301,0x0}, {0x1E55,0x70,0x301,0x0}, {0x1E56,0x50,0x307,0x0}, 
+  {0x1E57,0x70,0x307,0x0}, {0x1E58,0x52,0x307,0x0}, {0x1E59,0x72,0x307,0x0}, 
+  {0x1E5A,0x52,0x323,0x0}, {0x1E5B,0x72,0x323,0x0}, {0x1E5C,0x1E5A,0x304,0x0}, 
+  {0x1E5D,0x1E5B,0x304,0x0}, {0x1E5E,0x52,0x331,0x0}, {0x1E5F,0x72,0x331,0x0}, 
+  {0x1E60,0x53,0x307,0x0}, {0x1E61,0x73,0x307,0x0}, {0x1E62,0x53,0x323,0x0}, 
+  {0x1E63,0x73,0x323,0x0}, {0x1E64,0x15A,0x307,0x0}, {0x1E65,0x15B,0x307,0x0}, 
+  {0x1E66,0x160,0x307,0x0}, {0x1E67,0x161,0x307,0x0}, {0x1E68,0x1E62,0x307,0x0}, 
+  {0x1E69,0x1E63,0x307,0x0}, {0x1E6A,0x54,0x307,0x0}, {0x1E6B,0x74,0x307,0x0}, 
+  {0x1E6C,0x54,0x323,0x0}, {0x1E6D,0x74,0x323,0x0}, {0x1E6E,0x54,0x331,0x0}, 
+  {0x1E6F,0x74,0x331,0x0}, {0x1E70,0x54,0x32D,0x0}, {0x1E71,0x74,0x32D,0x0}, 
+  {0x1E72,0x55,0x324,0x0}, {0x1E73,0x75,0x324,0x0}, {0x1E74,0x55,0x330,0x0}, 
+  {0x1E75,0x75,0x330,0x0}, {0x1E76,0x55,0x32D,0x0}, {0x1E77,0x75,0x32D,0x0}, 
+  {0x1E78,0x168,0x301,0x0}, {0x1E79,0x169,0x301,0x0}, {0x1E7A,0x16A,0x308,0x0}, 
+  {0x1E7B,0x16B,0x308,0x0}, {0x1E7C,0x56,0x303,0x0}, {0x1E7D,0x76,0x303,0x0}, 
+  {0x1E7E,0x56,0x323,0x0}, {0x1E7F,0x76,0x323,0x0}, {0x1E80,0x57,0x300,0x0}, 
+  {0x1E81,0x77,0x300,0x0}, {0x1E82,0x57,0x301,0x0}, {0x1E83,0x77,0x301,0x0}, 
+  {0x1E84,0x57,0x308,0x0}, {0x1E85,0x77,0x308,0x0}, {0x1E86,0x57,0x307,0x0}, 
+  {0x1E87,0x77,0x307,0x0}, {0x1E88,0x57,0x323,0x0}, {0x1E89,0x77,0x323,0x0}, 
+  {0x1E8A,0x58,0x307,0x0}, {0x1E8B,0x78,0x307,0x0}, {0x1E8C,0x58,0x308,0x0}, 
+  {0x1E8D,0x78,0x308,0x0}, {0x1E8E,0x59,0x307,0x0}, {0x1E8F,0x79,0x307,0x0}, 
+  {0x1E90,0x5A,0x302,0x0}, {0x1E91,0x7A,0x302,0x0}, {0x1E92,0x5A,0x323,0x0}, 
+  {0x1E93,0x7A,0x323,0x0}, {0x1E94,0x5A,0x331,0x0}, {0x1E95,0x7A,0x331,0x0}, 
+  {0x1E96,0x68,0x331,0x0}, {0x1E97,0x74,0x308,0x0}, {0x1E98,0x77,0x30A,0x0}, 
+  {0x1E99,0x79,0x30A,0x0}, {0x1E9B,0x17F,0x307,0x0}, {0x1EA0,0x41,0x323,0x0}, 
+  {0x1EA1,0x61,0x323,0x0}, {0x1EA2,0x41,0x309,0x0}, {0x1EA3,0x61,0x309,0x0}, 
+  {0x1EA4,0xC2,0x301,0x0}, {0x1EA5,0xE2,0x301,0x0}, {0x1EA6,0xC2,0x300,0x0}, 
+  {0x1EA7,0xE2,0x300,0x0}, {0x1EA8,0xC2,0x309,0x0}, {0x1EA9,0xE2,0x309,0x0}, 
+  {0x1EAA,0xC2,0x303,0x0}, {0x1EAB,0xE2,0x303,0x0}, {0x1EAC,0xC2,0x323,0x0}, 
+  {0x1EAD,0xE2,0x323,0x0}, {0x1EAE,0x102,0x301,0x0}, {0x1EAF,0x103,0x301,0x0}, 
+  {0x1EB0,0x102,0x300,0x0}, {0x1EB1,0x103,0x300,0x0}, {0x1EB2,0x102,0x309,0x0}, 
+  {0x1EB3,0x103,0x309,0x0}, {0x1EB4,0x102,0x303,0x0}, {0x1EB5,0x103,0x303,0x0}, 
+  {0x1EB6,0x102,0x323,0x0}, {0x1EB7,0x103,0x323,0x0}, {0x1EB8,0x45,0x323,0x0}, 
+  {0x1EB9,0x65,0x323,0x0}, {0x1EBA,0x45,0x309,0x0}, {0x1EBB,0x65,0x309,0x0}, 
+  {0x1EBC,0x45,0x303,0x0}, {0x1EBD,0x65,0x303,0x0}, {0x1EBE,0xCA,0x301,0x0}, 
+  {0x1EBF,0xEA,0x301,0x0}, {0x1EC0,0xCA,0x300,0x0}, {0x1EC1,0xEA,0x300,0x0}, 
+  {0x1EC2,0xCA,0x309,0x0}, {0x1EC3,0xEA,0x309,0x0}, {0x1EC4,0xCA,0x303,0x0}, 
+  {0x1EC5,0xEA,0x303,0x0}, {0x1EC6,0xCA,0x323,0x0}, {0x1EC7,0xEA,0x323,0x0}, 
+  {0x1EC8,0x49,0x309,0x0}, {0x1EC9,0x69,0x309,0x0}, {0x1ECA,0x49,0x323,0x0}, 
+  {0x1ECB,0x69,0x323,0x0}, {0x1ECC,0x4F,0x323,0x0}, {0x1ECD,0x6F,0x323,0x0}, 
+  {0x1ECE,0x4F,0x309,0x0}, {0x1ECF,0x6F,0x309,0x0}, {0x1ED0,0xD4,0x301,0x0}, 
+  {0x1ED1,0xF4,0x301,0x0}, {0x1ED2,0xD4,0x300,0x0}, {0x1ED3,0xF4,0x300,0x0}, 
+  {0x1ED4,0xD4,0x309,0x0}, {0x1ED5,0xF4,0x309,0x0}, {0x1ED6,0xD4,0x303,0x0}, 
+  {0x1ED7,0xF4,0x303,0x0}, {0x1ED8,0xD4,0x323,0x0}, {0x1ED9,0xF4,0x323,0x0}, 
+  {0x1EDA,0x1A0,0x301,0x0}, {0x1EDB,0x1A1,0x301,0x0}, {0x1EDC,0x1A0,0x300,0x0}, 
+  {0x1EDD,0x1A1,0x300,0x0}, {0x1EDE,0x1A0,0x309,0x0}, {0x1EDF,0x1A1,0x309,0x0}, 
+  {0x1EE0,0x1A0,0x303,0x0}, {0x1EE1,0x1A1,0x303,0x0}, {0x1EE2,0x1A0,0x323,0x0}, 
+  {0x1EE3,0x1A1,0x323,0x0}, {0x1EE4,0x55,0x323,0x0}, {0x1EE5,0x75,0x323,0x0}, 
+  {0x1EE6,0x55,0x309,0x0}, {0x1EE7,0x75,0x309,0x0}, {0x1EE8,0x1AF,0x301,0x0}, 
+  {0x1EE9,0x1B0,0x301,0x0}, {0x1EEA,0x1AF,0x300,0x0}, {0x1EEB,0x1B0,0x300,0x0}, 
+  {0x1EEC,0x1AF,0x309,0x0}, {0x1EED,0x1B0,0x309,0x0}, {0x1EEE,0x1AF,0x303,0x0}, 
+  {0x1EEF,0x1B0,0x303,0x0}, {0x1EF0,0x1AF,0x323,0x0}, {0x1EF1,0x1B0,0x323,0x0}, 
+  {0x1EF2,0x59,0x300,0x0}, {0x1EF3,0x79,0x300,0x0}, {0x1EF4,0x59,0x323,0x0}, 
+  {0x1EF5,0x79,0x323,0x0}, {0x1EF6,0x59,0x309,0x0}, {0x1EF7,0x79,0x309,0x0}, 
+  {0x1EF8,0x59,0x303,0x0}, {0x1EF9,0x79,0x303,0x0}, {0x1F00,0x3B1,0x313,0x0}, 
+  {0x1F01,0x3B1,0x314,0x0}, {0x1F02,0x1F00,0x300,0x0}, {0x1F03,0x1F01,0x300,0x0}, 
+  {0x1F04,0x1F00,0x301,0x0}, {0x1F05,0x1F01,0x301,0x0}, {0x1F06,0x1F00,0x342,0x0}, 
+  {0x1F07,0x1F01,0x342,0x0}, {0x1F08,0x391,0x313,0x0}, {0x1F09,0x391,0x314,0x0}, 
+  {0x1F0A,0x1F08,0x300,0x0}, {0x1F0B,0x1F09,0x300,0x0}, {0x1F0C,0x1F08,0x301,0x0}, 
+  {0x1F0D,0x1F09,0x301,0x0}, {0x1F0E,0x1F08,0x342,0x0}, {0x1F0F,0x1F09,0x342,0x0}, 
+  {0x1F10,0x3B5,0x313,0x0}, {0x1F11,0x3B5,0x314,0x0}, {0x1F12,0x1F10,0x300,0x0}, 
+  {0x1F13,0x1F11,0x300,0x0}, {0x1F14,0x1F10,0x301,0x0}, {0x1F15,0x1F11,0x301,0x0}, 
+  {0x1F18,0x395,0x313,0x0}, {0x1F19,0x395,0x314,0x0}, {0x1F1A,0x1F18,0x300,0x0}, 
+  {0x1F1B,0x1F19,0x300,0x0}, {0x1F1C,0x1F18,0x301,0x0}, {0x1F1D,0x1F19,0x301,0x0}, 
+  {0x1F20,0x3B7,0x313,0x0}, {0x1F21,0x3B7,0x314,0x0}, {0x1F22,0x1F20,0x300,0x0}, 
+  {0x1F23,0x1F21,0x300,0x0}, {0x1F24,0x1F20,0x301,0x0}, {0x1F25,0x1F21,0x301,0x0}, 
+  {0x1F26,0x1F20,0x342,0x0}, {0x1F27,0x1F21,0x342,0x0}, {0x1F28,0x397,0x313,0x0}, 
+  {0x1F29,0x397,0x314,0x0}, {0x1F2A,0x1F28,0x300,0x0}, {0x1F2B,0x1F29,0x300,0x0}, 
+  {0x1F2C,0x1F28,0x301,0x0}, {0x1F2D,0x1F29,0x301,0x0}, {0x1F2E,0x1F28,0x342,0x0}, 
+  {0x1F2F,0x1F29,0x342,0x0}, {0x1F30,0x3B9,0x313,0x0}, {0x1F31,0x3B9,0x314,0x0}, 
+  {0x1F32,0x1F30,0x300,0x0}, {0x1F33,0x1F31,0x300,0x0}, {0x1F34,0x1F30,0x301,0x0}, 
+  {0x1F35,0x1F31,0x301,0x0}, {0x1F36,0x1F30,0x342,0x0}, {0x1F37,0x1F31,0x342,0x0}, 
+  {0x1F38,0x399,0x313,0x0}, {0x1F39,0x399,0x314,0x0}, {0x1F3A,0x1F38,0x300,0x0}, 
+  {0x1F3B,0x1F39,0x300,0x0}, {0x1F3C,0x1F38,0x301,0x0}, {0x1F3D,0x1F39,0x301,0x0}, 
+  {0x1F3E,0x1F38,0x342,0x0}, {0x1F3F,0x1F39,0x342,0x0}, {0x1F40,0x3BF,0x313,0x0}, 
+  {0x1F41,0x3BF,0x314,0x0}, {0x1F42,0x1F40,0x300,0x0}, {0x1F43,0x1F41,0x300,0x0}, 
+  {0x1F44,0x1F40,0x301,0x0}, {0x1F45,0x1F41,0x301,0x0}, {0x1F48,0x39F,0x313,0x0}, 
+  {0x1F49,0x39F,0x314,0x0}, {0x1F4A,0x1F48,0x300,0x0}, {0x1F4B,0x1F49,0x300,0x0}, 
+  {0x1F4C,0x1F48,0x301,0x0}, {0x1F4D,0x1F49,0x301,0x0}, {0x1F50,0x3C5,0x313,0x0}, 
+  {0x1F51,0x3C5,0x314,0x0}, {0x1F52,0x1F50,0x300,0x0}, {0x1F53,0x1F51,0x300,0x0}, 
+  {0x1F54,0x1F50,0x301,0x0}, {0x1F55,0x1F51,0x301,0x0}, {0x1F56,0x1F50,0x342,0x0}, 
+  {0x1F57,0x1F51,0x342,0x0}, {0x1F59,0x3A5,0x314,0x0}, {0x1F5B,0x1F59,0x300,0x0}, 
+  {0x1F5D,0x1F59,0x301,0x0}, {0x1F5F,0x1F59,0x342,0x0}, {0x1F60,0x3C9,0x313,0x0}, 
+  {0x1F61,0x3C9,0x314,0x0}, {0x1F62,0x1F60,0x300,0x0}, {0x1F63,0x1F61,0x300,0x0}, 
+  {0x1F64,0x1F60,0x301,0x0}, {0x1F65,0x1F61,0x301,0x0}, {0x1F66,0x1F60,0x342,0x0}, 
+  {0x1F67,0x1F61,0x342,0x0}, {0x1F68,0x3A9,0x313,0x0}, {0x1F69,0x3A9,0x314,0x0}, 
+  {0x1F6A,0x1F68,0x300,0x0}, {0x1F6B,0x1F69,0x300,0x0}, {0x1F6C,0x1F68,0x301,0x0}, 
+  {0x1F6D,0x1F69,0x301,0x0}, {0x1F6E,0x1F68,0x342,0x0}, {0x1F6F,0x1F69,0x342,0x0}, 
+  {0x1F70,0x3B1,0x300,0x0}, {0x1F71,0x3B1,0x301,0x0}, {0x1F72,0x3B5,0x300,0x0}, 
+  {0x1F73,0x3B5,0x301,0x0}, {0x1F74,0x3B7,0x300,0x0}, {0x1F75,0x3B7,0x301,0x0}, 
+  {0x1F76,0x3B9,0x300,0x0}, {0x1F77,0x3B9,0x301,0x0}, {0x1F78,0x3BF,0x300,0x0}, 
+  {0x1F79,0x3BF,0x301,0x0}, {0x1F7A,0x3C5,0x300,0x0}, {0x1F7B,0x3C5,0x301,0x0}, 
+  {0x1F7C,0x3C9,0x300,0x0}, {0x1F7D,0x3C9,0x301,0x0}, {0x1F80,0x1F00,0x345,0x0}, 
+  {0x1F81,0x1F01,0x345,0x0}, {0x1F82,0x1F02,0x345,0x0}, {0x1F83,0x1F03,0x345,0x0}, 
+  {0x1F84,0x1F04,0x345,0x0}, {0x1F85,0x1F05,0x345,0x0}, {0x1F86,0x1F06,0x345,0x0}, 
+  {0x1F87,0x1F07,0x345,0x0}, {0x1F88,0x1F08,0x345,0x0}, {0x1F89,0x1F09,0x345,0x0}, 
+  {0x1F8A,0x1F0A,0x345,0x0}, {0x1F8B,0x1F0B,0x345,0x0}, {0x1F8C,0x1F0C,0x345,0x0}, 
+  {0x1F8D,0x1F0D,0x345,0x0}, {0x1F8E,0x1F0E,0x345,0x0}, {0x1F8F,0x1F0F,0x345,0x0}, 
+  {0x1F90,0x1F20,0x345,0x0}, {0x1F91,0x1F21,0x345,0x0}, {0x1F92,0x1F22,0x345,0x0}, 
+  {0x1F93,0x1F23,0x345,0x0}, {0x1F94,0x1F24,0x345,0x0}, {0x1F95,0x1F25,0x345,0x0}, 
+  {0x1F96,0x1F26,0x345,0x0}, {0x1F97,0x1F27,0x345,0x0}, {0x1F98,0x1F28,0x345,0x0}, 
+  {0x1F99,0x1F29,0x345,0x0}, {0x1F9A,0x1F2A,0x345,0x0}, {0x1F9B,0x1F2B,0x345,0x0}, 
+  {0x1F9C,0x1F2C,0x345,0x0}, {0x1F9D,0x1F2D,0x345,0x0}, {0x1F9E,0x1F2E,0x345,0x0}, 
+  {0x1F9F,0x1F2F,0x345,0x0}, {0x1FA0,0x1F60,0x345,0x0}, {0x1FA1,0x1F61,0x345,0x0}, 
+  {0x1FA2,0x1F62,0x345,0x0}, {0x1FA3,0x1F63,0x345,0x0}, {0x1FA4,0x1F64,0x345,0x0}, 
+  {0x1FA5,0x1F65,0x345,0x0}, {0x1FA6,0x1F66,0x345,0x0}, {0x1FA7,0x1F67,0x345,0x0}, 
+  {0x1FA8,0x1F68,0x345,0x0}, {0x1FA9,0x1F69,0x345,0x0}, {0x1FAA,0x1F6A,0x345,0x0}, 
+  {0x1FAB,0x1F6B,0x345,0x0}, {0x1FAC,0x1F6C,0x345,0x0}, {0x1FAD,0x1F6D,0x345,0x0}, 
+  {0x1FAE,0x1F6E,0x345,0x0}, {0x1FAF,0x1F6F,0x345,0x0}, {0x1FB0,0x3B1,0x306,0x0}, 
+  {0x1FB1,0x3B1,0x304,0x0}, {0x1FB2,0x1F70,0x345,0x0}, {0x1FB3,0x3B1,0x345,0x0}, 
+  {0x1FB4,0x1F71,0x345,0x0}, {0x1FB6,0x3B1,0x342,0x0}, {0x1FB7,0x1FB6,0x345,0x0}, 
+  {0x1FB8,0x391,0x306,0x0}, {0x1FB9,0x391,0x304,0x0}, {0x1FBA,0x391,0x300,0x0}, 
+  {0x1FBB,0x391,0x301,0x0}, {0x1FBC,0x391,0x345,0x0}, {0x1FBE,0x3B9,0x0,0x0}, 
+  {0x1FC1,0xA8,0x342,0x0}, {0x1FC2,0x1F74,0x345,0x0}, {0x1FC3,0x3B7,0x345,0x0}, 
+  {0x1FC4,0x1F75,0x345,0x0}, {0x1FC6,0x3B7,0x342,0x0}, {0x1FC7,0x1FC6,0x345,0x0}, 
+  {0x1FC8,0x395,0x300,0x0}, {0x1FC9,0x395,0x301,0x0}, {0x1FCA,0x397,0x300,0x0}, 
+  {0x1FCB,0x397,0x301,0x0}, {0x1FCC,0x397,0x345,0x0}, {0x1FCD,0x1FBF,0x300,0x0}, 
+  {0x1FCE,0x1FBF,0x301,0x0}, {0x1FCF,0x1FBF,0x342,0x0}, {0x1FD0,0x3B9,0x306,0x0}, 
+  {0x1FD1,0x3B9,0x304,0x0}, {0x1FD2,0x3CA,0x300,0x0}, {0x1FD3,0x3CA,0x301,0x0}, 
+  {0x1FD6,0x3B9,0x342,0x0}, {0x1FD7,0x3CA,0x342,0x0}, {0x1FD8,0x399,0x306,0x0}, 
+  {0x1FD9,0x399,0x304,0x0}, {0x1FDA,0x399,0x300,0x0}, {0x1FDB,0x399,0x301,0x0}, 
+  {0x1FDD,0x1FFE,0x300,0x0}, {0x1FDE,0x1FFE,0x301,0x0}, {0x1FDF,0x1FFE,0x342,0x0}, 
+  {0x1FE0,0x3C5,0x306,0x0}, {0x1FE1,0x3C5,0x304,0x0}, {0x1FE2,0x3CB,0x300,0x0}, 
+  {0x1FE3,0x3CB,0x301,0x0}, {0x1FE4,0x3C1,0x313,0x0}, {0x1FE5,0x3C1,0x314,0x0}, 
+  {0x1FE6,0x3C5,0x342,0x0}, {0x1FE7,0x3CB,0x342,0x0}, {0x1FE8,0x3A5,0x306,0x0}, 
+  {0x1FE9,0x3A5,0x304,0x0}, {0x1FEA,0x3A5,0x300,0x0}, {0x1FEB,0x3A5,0x301,0x0}, 
+  {0x1FEC,0x3A1,0x314,0x0}, {0x1FED,0xA8,0x300,0x0}, {0x1FEE,0xA8,0x301,0x0}, 
+  {0x1FEF,0x60,0x0,0x0}, {0x1FF2,0x1F7C,0x345,0x0}, {0x1FF3,0x3C9,0x345,0x0}, 
+  {0x1FF4,0x1F79,0x345,0x0}, {0x1FF6,0x3C9,0x342,0x0}, {0x1FF7,0x1FF6,0x345,0x0}, 
+  {0x1FF8,0x39F,0x300,0x0}, {0x1FF9,0x39F,0x301,0x0}, {0x1FFA,0x3A9,0x300,0x0}, 
+  {0x1FFB,0x3A9,0x301,0x0}, {0x1FFC,0x3A9,0x345,0x0}, {0x1FFD,0xB4,0x0,0x0}, 
+  {0x2000,0x2002,0x0,0x0}, {0x2001,0x2003,0x0,0x0}, {0x2126,0x3A9,0x0,0x0}, 
+  {0x212A,0x4B,0x0,0x0}, {0x212B,0xC5,0x0,0x0}, {0x2204,0x2203,0x338,0x0}, 
+  {0x2209,0x2208,0x338,0x0}, {0x220C,0x220B,0x338,0x0}, {0x2224,0x2223,0x338,0x0}, 
+  {0x2226,0x2225,0x338,0x0}, {0x2241,0x7E,0x338,0x0}, {0x2244,0x2243,0x338,0x0}, 
+  {0x2247,0x2245,0x338,0x0}, {0x2249,0x2248,0x338,0x0}, {0x2260,0x3D,0x338,0x0}, 
+  {0x2262,0x2261,0x338,0x0}, {0x226D,0x224D,0x338,0x0}, {0x226E,0x3C,0x338,0x0}, 
+  {0x226F,0x3E,0x338,0x0}, {0x2270,0x2264,0x338,0x0}, {0x2271,0x2265,0x338,0x0}, 
+  {0x2274,0x2272,0x338,0x0}, {0x2275,0x2273,0x338,0x0}, {0x2278,0x2276,0x338,0x0}, 
+  {0x2279,0x2277,0x338,0x0}, {0x2280,0x227A,0x338,0x0}, {0x2281,0x227B,0x338,0x0}, 
+  {0x2284,0x2282,0x338,0x0}, {0x2285,0x2283,0x338,0x0}, {0x2288,0x2286,0x338,0x0}, 
+  {0x2289,0x2287,0x338,0x0}, {0x22AC,0x22A2,0x338,0x0}, {0x22AD,0x22A8,0x338,0x0}, 
+  {0x22AE,0x22A9,0x338,0x0}, {0x22AF,0x22AB,0x338,0x0}, {0x22E0,0x227C,0x338,0x0}, 
+  {0x22E1,0x227D,0x338,0x0}, {0x22E2,0x2291,0x338,0x0}, {0x22E3,0x2292,0x338,0x0}, 
+  {0x22EA,0x22B2,0x338,0x0}, {0x22EB,0x22B3,0x338,0x0}, {0x22EC,0x22B4,0x338,0x0}, 
+  {0x22ED,0x22B5,0x338,0x0}, {0x2329,0x3008,0x0,0x0}, {0x232A,0x3009,0x0,0x0}, 
+  {0x304C,0x304B,0x3099,0x0}, {0x304E,0x304D,0x3099,0x0}, {0x3050,0x304F,0x3099,0x0}, 
+  {0x3052,0x3051,0x3099,0x0}, {0x3054,0x3053,0x3099,0x0}, {0x3056,0x3055,0x3099,0x0}, 
+  {0x3058,0x3057,0x3099,0x0}, {0x305A,0x3059,0x3099,0x0}, {0x305C,0x305B,0x3099,0x0}, 
+  {0x305E,0x305D,0x3099,0x0}, {0x3060,0x305F,0x3099,0x0}, {0x3062,0x3061,0x3099,0x0}, 
+  {0x3065,0x3064,0x3099,0x0}, {0x3067,0x3066,0x3099,0x0}, {0x3069,0x3068,0x3099,0x0}, 
+  {0x3070,0x306F,0x3099,0x0}, {0x3071,0x306F,0x309A,0x0}, {0x3073,0x3072,0x3099,0x0}, 
+  {0x3074,0x3072,0x309A,0x0}, {0x3076,0x3075,0x3099,0x0}, {0x3077,0x3075,0x309A,0x0}, 
+  {0x3079,0x3078,0x3099,0x0}, {0x307A,0x3078,0x309A,0x0}, {0x307C,0x307B,0x3099,0x0}, 
+  {0x307D,0x307B,0x309A,0x0}, {0x3094,0x3046,0x3099,0x0}, {0x309E,0x309D,0x3099,0x0}, 
+  {0x30AC,0x30AB,0x3099,0x0}, {0x30AE,0x30AD,0x3099,0x0}, {0x30B0,0x30AF,0x3099,0x0}, 
+  {0x30B2,0x30B1,0x3099,0x0}, {0x30B4,0x30B3,0x3099,0x0}, {0x30B6,0x30B5,0x3099,0x0}, 
+  {0x30B8,0x30B7,0x3099,0x0}, {0x30BA,0x30B9,0x3099,0x0}, {0x30BC,0x30BB,0x3099,0x0}, 
+  {0x30BE,0x30BD,0x3099,0x0}, {0x30C0,0x30BF,0x3099,0x0}, {0x30C2,0x30C1,0x3099,0x0}, 
+  {0x30C5,0x30C4,0x3099,0x0}, {0x30C7,0x30C6,0x3099,0x0}, {0x30C9,0x30C8,0x3099,0x0}, 
+  {0x30D0,0x30CF,0x3099,0x0}, {0x30D1,0x30CF,0x309A,0x0}, {0x30D3,0x30D2,0x3099,0x0}, 
+  {0x30D4,0x30D2,0x309A,0x0}, {0x30D6,0x30D5,0x3099,0x0}, {0x30D7,0x30D5,0x309A,0x0}, 
+  {0x30D9,0x30D8,0x3099,0x0}, {0x30DA,0x30D8,0x309A,0x0}, {0x30DC,0x30DB,0x3099,0x0}, 
+  {0x30DD,0x30DB,0x309A,0x0}, {0x30F4,0x30A6,0x3099,0x0}, {0x30F7,0x30EF,0x3099,0x0}, 
+  {0x30F8,0x30F0,0x3099,0x0}, {0x30F9,0x30F1,0x3099,0x0}, {0x30FA,0x30F2,0x3099,0x0}, 
+  {0x30FE,0x30FD,0x3099,0x0}, {0xF900,0x8C48,0x0,0x0}, {0xF901,0x66F4,0x0,0x0}, 
+  {0xF902,0x8ECA,0x0,0x0}, {0xF903,0x8CC8,0x0,0x0}, {0xF904,0x6ED1,0x0,0x0}, 
+  {0xF905,0x4E32,0x0,0x0}, {0xF906,0x53E5,0x0,0x0}, {0xF907,0x9F9C,0x0,0x0}, 
+  {0xF908,0x9F9C,0x0,0x0}, {0xF909,0x5951,0x0,0x0}, {0xF90A,0x91D1,0x0,0x0}, 
+  {0xF90B,0x5587,0x0,0x0}, {0xF90C,0x5948,0x0,0x0}, {0xF90D,0x61F6,0x0,0x0}, 
+  {0xF90E,0x7669,0x0,0x0}, {0xF90F,0x7F85,0x0,0x0}, {0xF910,0x863F,0x0,0x0}, 
+  {0xF911,0x87BA,0x0,0x0}, {0xF912,0x88F8,0x0,0x0}, {0xF913,0x908F,0x0,0x0}, 
+  {0xF914,0x6A02,0x0,0x0}, {0xF915,0x6D1B,0x0,0x0}, {0xF916,0x70D9,0x0,0x0}, 
+  {0xF917,0x73DE,0x0,0x0}, {0xF918,0x843D,0x0,0x0}, {0xF919,0x916A,0x0,0x0}, 
+  {0xF91A,0x99F1,0x0,0x0}, {0xF91B,0x4E82,0x0,0x0}, {0xF91C,0x5375,0x0,0x0}, 
+  {0xF91D,0x6B04,0x0,0x0}, {0xF91E,0x721B,0x0,0x0}, {0xF91F,0x862D,0x0,0x0}, 
+  {0xF920,0x9E1E,0x0,0x0}, {0xF921,0x5D50,0x0,0x0}, {0xF922,0x6FEB,0x0,0x0}, 
+  {0xF923,0x85CD,0x0,0x0}, {0xF924,0x8964,0x0,0x0}, {0xF925,0x62C9,0x0,0x0}, 
+  {0xF926,0x81D8,0x0,0x0}, {0xF927,0x881F,0x0,0x0}, {0xF928,0x5ECA,0x0,0x0}, 
+  {0xF929,0x6717,0x0,0x0}, {0xF92A,0x6D6A,0x0,0x0}, {0xF92B,0x72FC,0x0,0x0}, 
+  {0xF92C,0x90CE,0x0,0x0}, {0xF92D,0x4F86,0x0,0x0}, {0xF92E,0x51B7,0x0,0x0}, 
+  {0xF92F,0x52DE,0x0,0x0}, {0xF930,0x64C4,0x0,0x0}, {0xF931,0x6AD3,0x0,0x0}, 
+  {0xF932,0x7210,0x0,0x0}, {0xF933,0x76E7,0x0,0x0}, {0xF934,0x8001,0x0,0x0}, 
+  {0xF935,0x8606,0x0,0x0}, {0xF936,0x865C,0x0,0x0}, {0xF937,0x8DEF,0x0,0x0}, 
+  {0xF938,0x9732,0x0,0x0}, {0xF939,0x9B6F,0x0,0x0}, {0xF93A,0x9DFA,0x0,0x0}, 
+  {0xF93B,0x788C,0x0,0x0}, {0xF93C,0x797F,0x0,0x0}, {0xF93D,0x7DA0,0x0,0x0}, 
+  {0xF93E,0x83C9,0x0,0x0}, {0xF93F,0x9304,0x0,0x0}, {0xF940,0x9E7F,0x0,0x0}, 
+  {0xF941,0x8AD6,0x0,0x0}, {0xF942,0x58DF,0x0,0x0}, {0xF943,0x5F04,0x0,0x0}, 
+  {0xF944,0x7C60,0x0,0x0}, {0xF945,0x807E,0x0,0x0}, {0xF946,0x7262,0x0,0x0}, 
+  {0xF947,0x78CA,0x0,0x0}, {0xF948,0x8CC2,0x0,0x0}, {0xF949,0x96F7,0x0,0x0}, 
+  {0xF94A,0x58D8,0x0,0x0}, {0xF94B,0x5C62,0x0,0x0}, {0xF94C,0x6A13,0x0,0x0}, 
+  {0xF94D,0x6DDA,0x0,0x0}, {0xF94E,0x6F0F,0x0,0x0}, {0xF94F,0x7D2F,0x0,0x0}, 
+  {0xF950,0x7E37,0x0,0x0}, {0xF951,0x96FB,0x0,0x0}, {0xF952,0x52D2,0x0,0x0}, 
+  {0xF953,0x808B,0x0,0x0}, {0xF954,0x51DC,0x0,0x0}, {0xF955,0x51CC,0x0,0x0}, 
+  {0xF956,0x7A1C,0x0,0x0}, {0xF957,0x7DBE,0x0,0x0}, {0xF958,0x83F1,0x0,0x0}, 
+  {0xF959,0x9675,0x0,0x0}, {0xF95A,0x8B80,0x0,0x0}, {0xF95B,0x62CF,0x0,0x0}, 
+  {0xF95C,0x6A02,0x0,0x0}, {0xF95D,0x8AFE,0x0,0x0}, {0xF95E,0x4E39,0x0,0x0}, 
+  {0xF95F,0x5BE7,0x0,0x0}, {0xF960,0x6012,0x0,0x0}, {0xF961,0x7387,0x0,0x0}, 
+  {0xF962,0x7570,0x0,0x0}, {0xF963,0x5317,0x0,0x0}, {0xF964,0x78FB,0x0,0x0}, 
+  {0xF965,0x4FBF,0x0,0x0}, {0xF966,0x5FA9,0x0,0x0}, {0xF967,0x4E0D,0x0,0x0}, 
+  {0xF968,0x6CCC,0x0,0x0}, {0xF969,0x6578,0x0,0x0}, {0xF96A,0x7D22,0x0,0x0}, 
+  {0xF96B,0x53C3,0x0,0x0}, {0xF96C,0x585E,0x0,0x0}, {0xF96D,0x7701,0x0,0x0}, 
+  {0xF96E,0x8449,0x0,0x0}, {0xF96F,0x8AAA,0x0,0x0}, {0xF970,0x6BBA,0x0,0x0}, 
+  {0xF971,0x8FB0,0x0,0x0}, {0xF972,0x6C88,0x0,0x0}, {0xF973,0x62FE,0x0,0x0}, 
+  {0xF974,0x82E5,0x0,0x0}, {0xF975,0x63A0,0x0,0x0}, {0xF976,0x7565,0x0,0x0}, 
+  {0xF977,0x4EAE,0x0,0x0}, {0xF978,0x5169,0x0,0x0}, {0xF979,0x51C9,0x0,0x0}, 
+  {0xF97A,0x6881,0x0,0x0}, {0xF97B,0x7CE7,0x0,0x0}, {0xF97C,0x826F,0x0,0x0}, 
+  {0xF97D,0x8AD2,0x0,0x0}, {0xF97E,0x91CF,0x0,0x0}, {0xF97F,0x52F5,0x0,0x0}, 
+  {0xF980,0x5442,0x0,0x0}, {0xF981,0x5973,0x0,0x0}, {0xF982,0x5EEC,0x0,0x0}, 
+  {0xF983,0x65C5,0x0,0x0}, {0xF984,0x6FFE,0x0,0x0}, {0xF985,0x792A,0x0,0x0}, 
+  {0xF986,0x95AD,0x0,0x0}, {0xF987,0x9A6A,0x0,0x0}, {0xF988,0x9E97,0x0,0x0}, 
+  {0xF989,0x9ECE,0x0,0x0}, {0xF98A,0x529B,0x0,0x0}, {0xF98B,0x66C6,0x0,0x0}, 
+  {0xF98C,0x6B77,0x0,0x0}, {0xF98D,0x8F62,0x0,0x0}, {0xF98E,0x5E74,0x0,0x0}, 
+  {0xF98F,0x6190,0x0,0x0}, {0xF990,0x6200,0x0,0x0}, {0xF991,0x649A,0x0,0x0}, 
+  {0xF992,0x6F23,0x0,0x0}, {0xF993,0x7149,0x0,0x0}, {0xF994,0x7489,0x0,0x0}, 
+  {0xF995,0x79CA,0x0,0x0}, {0xF996,0x7DF4,0x0,0x0}, {0xF997,0x806F,0x0,0x0}, 
+  {0xF998,0x8F26,0x0,0x0}, {0xF999,0x84EE,0x0,0x0}, {0xF99A,0x9023,0x0,0x0}, 
+  {0xF99B,0x934A,0x0,0x0}, {0xF99C,0x5217,0x0,0x0}, {0xF99D,0x52A3,0x0,0x0}, 
+  {0xF99E,0x54BD,0x0,0x0}, {0xF99F,0x70C8,0x0,0x0}, {0xF9A0,0x88C2,0x0,0x0}, 
+  {0xF9A1,0x8AAA,0x0,0x0}, {0xF9A2,0x5EC9,0x0,0x0}, {0xF9A3,0x5FF5,0x0,0x0}, 
+  {0xF9A4,0x637B,0x0,0x0}, {0xF9A5,0x6BAE,0x0,0x0}, {0xF9A6,0x7C3E,0x0,0x0}, 
+  {0xF9A7,0x7375,0x0,0x0}, {0xF9A8,0x4EE4,0x0,0x0}, {0xF9A9,0x56F9,0x0,0x0}, 
+  {0xF9AA,0x5BE7,0x0,0x0}, {0xF9AB,0x5DBA,0x0,0x0}, {0xF9AC,0x601C,0x0,0x0}, 
+  {0xF9AD,0x73B2,0x0,0x0}, {0xF9AE,0x7469,0x0,0x0}, {0xF9AF,0x7F9A,0x0,0x0}, 
+  {0xF9B0,0x8046,0x0,0x0}, {0xF9B1,0x9234,0x0,0x0}, {0xF9B2,0x96F6,0x0,0x0}, 
+  {0xF9B3,0x9748,0x0,0x0}, {0xF9B4,0x9818,0x0,0x0}, {0xF9B5,0x4F8B,0x0,0x0}, 
+  {0xF9B6,0x79AE,0x0,0x0}, {0xF9B7,0x91B4,0x0,0x0}, {0xF9B8,0x96B8,0x0,0x0}, 
+  {0xF9B9,0x60E1,0x0,0x0}, {0xF9BA,0x4E86,0x0,0x0}, {0xF9BB,0x50DA,0x0,0x0}, 
+  {0xF9BC,0x5BEE,0x0,0x0}, {0xF9BD,0x5C3F,0x0,0x0}, {0xF9BE,0x6599,0x0,0x0}, 
+  {0xF9BF,0x6A02,0x0,0x0}, {0xF9C0,0x71CE,0x0,0x0}, {0xF9C1,0x7642,0x0,0x0}, 
+  {0xF9C2,0x84FC,0x0,0x0}, {0xF9C3,0x907C,0x0,0x0}, {0xF9C4,0x9F8D,0x0,0x0}, 
+  {0xF9C5,0x6688,0x0,0x0}, {0xF9C6,0x962E,0x0,0x0}, {0xF9C7,0x5289,0x0,0x0}, 
+  {0xF9C8,0x677B,0x0,0x0}, {0xF9C9,0x67F3,0x0,0x0}, {0xF9CA,0x6D41,0x0,0x0}, 
+  {0xF9CB,0x6E9C,0x0,0x0}, {0xF9CC,0x7409,0x0,0x0}, {0xF9CD,0x7559,0x0,0x0}, 
+  {0xF9CE,0x786B,0x0,0x0}, {0xF9CF,0x7D10,0x0,0x0}, {0xF9D0,0x985E,0x0,0x0}, 
+  {0xF9D1,0x516D,0x0,0x0}, {0xF9D2,0x622E,0x0,0x0}, {0xF9D3,0x9678,0x0,0x0}, 
+  {0xF9D4,0x502B,0x0,0x0}, {0xF9D5,0x5D19,0x0,0x0}, {0xF9D6,0x6DEA,0x0,0x0}, 
+  {0xF9D7,0x8F2A,0x0,0x0}, {0xF9D8,0x5F8B,0x0,0x0}, {0xF9D9,0x6144,0x0,0x0}, 
+  {0xF9DA,0x6817,0x0,0x0}, {0xF9DB,0x7387,0x0,0x0}, {0xF9DC,0x9686,0x0,0x0}, 
+  {0xF9DD,0x5229,0x0,0x0}, {0xF9DE,0x540F,0x0,0x0}, {0xF9DF,0x5C65,0x0,0x0}, 
+  {0xF9E0,0x6613,0x0,0x0}, {0xF9E1,0x674E,0x0,0x0}, {0xF9E2,0x68A8,0x0,0x0}, 
+  {0xF9E3,0x6CE5,0x0,0x0}, {0xF9E4,0x7406,0x0,0x0}, {0xF9E5,0x75E2,0x0,0x0}, 
+  {0xF9E6,0x7F79,0x0,0x0}, {0xF9E7,0x88CF,0x0,0x0}, {0xF9E8,0x88E1,0x0,0x0}, 
+  {0xF9E9,0x91CC,0x0,0x0}, {0xF9EA,0x96E2,0x0,0x0}, {0xF9EB,0x533F,0x0,0x0}, 
+  {0xF9EC,0x6EBA,0x0,0x0}, {0xF9ED,0x541D,0x0,0x0}, {0xF9EE,0x71D0,0x0,0x0}, 
+  {0xF9EF,0x7498,0x0,0x0}, {0xF9F0,0x85FA,0x0,0x0}, {0xF9F1,0x96A3,0x0,0x0}, 
+  {0xF9F2,0x9C57,0x0,0x0}, {0xF9F3,0x9E9F,0x0,0x0}, {0xF9F4,0x6797,0x0,0x0}, 
+  {0xF9F5,0x6DCB,0x0,0x0}, {0xF9F6,0x81E8,0x0,0x0}, {0xF9F7,0x7ACB,0x0,0x0}, 
+  {0xF9F8,0x7B20,0x0,0x0}, {0xF9F9,0x7C92,0x0,0x0}, {0xF9FA,0x72C0,0x0,0x0}, 
+  {0xF9FB,0x7099,0x0,0x0}, {0xF9FC,0x8B58,0x0,0x0}, {0xF9FD,0x4EC0,0x0,0x0}, 
+  {0xF9FE,0x8336,0x0,0x0}, {0xF9FF,0x523A,0x0,0x0}, {0xFA00,0x5207,0x0,0x0}, 
+  {0xFA01,0x5EA6,0x0,0x0}, {0xFA02,0x62D3,0x0,0x0}, {0xFA03,0x7CD6,0x0,0x0}, 
+  {0xFA04,0x5B85,0x0,0x0}, {0xFA05,0x6D1E,0x0,0x0}, {0xFA06,0x66B4,0x0,0x0}, 
+  {0xFA07,0x8F3B,0x0,0x0}, {0xFA08,0x884C,0x0,0x0}, {0xFA09,0x964D,0x0,0x0}, 
+  {0xFA0A,0x898B,0x0,0x0}, {0xFA0B,0x5ED3,0x0,0x0}, {0xFA0C,0x5140,0x0,0x0}, 
+  {0xFA0D,0x55C0,0x0,0x0}, {0xFA10,0x585A,0x0,0x0}, {0xFA12,0x6674,0x0,0x0}, 
+  {0xFA15,0x51DE,0x0,0x0}, {0xFA16,0x732A,0x0,0x0}, {0xFA17,0x76CA,0x0,0x0}, 
+  {0xFA18,0x793C,0x0,0x0}, {0xFA19,0x795E,0x0,0x0}, {0xFA1A,0x7965,0x0,0x0}, 
+  {0xFA1B,0x798F,0x0,0x0}, {0xFA1C,0x9756,0x0,0x0}, {0xFA1D,0x7CBE,0x0,0x0}, 
+  {0xFA1E,0x7FBD,0x0,0x0}, {0xFA20,0x8612,0x0,0x0}, {0xFA22,0x8AF8,0x0,0x0}, 
+  {0xFA25,0x9038,0x0,0x0}, {0xFA26,0x90FD,0x0,0x0}, {0xFA2A,0x98EF,0x0,0x0}, 
+  {0xFA2B,0x98FC,0x0,0x0}, {0xFA2C,0x9928,0x0,0x0}, {0xFA2D,0x9DB4,0x0,0x0}, 
+  {0xFB1F,0x5F2,0x5B7,0x0}, {0xFB2A,0x5E9,0x5C1,0x0}, {0xFB2B,0x5E9,0x5C2,0x0}, 
+  {0xFB2C,0x5E9,0x5BC,0x5C1}, {0xFB2D,0x5E9,0x5BC,0x5C2}, {0xFB2E,0x5D0,0x5B7,0x0}, 
+  {0xFB2F,0x5D0,0x5B8,0x0}, {0xFB30,0x5D0,0x5BC,0x0}, {0xFB31,0x5D1,0x5BC,0x0}, 
+  {0xFB32,0x5D2,0x5BC,0x0}, {0xFB33,0x5D3,0x5BC,0x0}, {0xFB34,0x5D4,0x5BC,0x0}, 
+  {0xFB35,0x5D5,0x5BC,0x0}, {0xFB36,0x5D6,0x5BC,0x0}, {0xFB38,0x5D8,0x5BC,0x0}, 
+  {0xFB39,0x5D9,0x5BC,0x0}, {0xFB3A,0x5DA,0x5BC,0x0}, {0xFB3B,0x5DB,0x5BC,0x0}, 
+  {0xFB3C,0x5DC,0x5BC,0x0}, {0xFB3E,0x5DE,0x5BC,0x0}, {0xFB40,0x5E0,0x5BC,0x0}, 
+  {0xFB41,0x5E1,0x5BC,0x0}, {0xFB43,0x5E3,0x5BC,0x0}, {0xFB44,0x5E4,0x5BC,0x0}, 
+  {0xFB46,0x5E6,0x5BC,0x0}, {0xFB47,0x5E7,0x5BC,0x0}, {0xFB48,0x5E8,0x5BC,0x0}, 
+  {0xFB49,0x5E9,0x5BC,0x0}, {0xFB4A,0x5EA,0x5BC,0x0}, {0xFB4B,0x5D5,0x5B9,0x0}, 
+  {0xFB4C,0x5D1,0x5BF,0x0}, {0xFB4D,0x5DB,0x5BF,0x0}, {0xFB4E,0x5E4,0x5BF,0x0} 
+};
+
+
+/* All upper-case translations are included here */
+
+#define NUM_TOUPPER_INFO 677
+static const unirelate toupper_info[NUM_TOUPPER_INFO] = {
+  {0x61,0x41}, {0x62,0x42}, {0x63,0x43}, {0x64,0x44}, {0x65,0x45}, 
+  {0x66,0x46}, {0x67,0x47}, {0x68,0x48}, {0x69,0x49}, {0x6A,0x4A}, 
+  {0x6B,0x4B}, {0x6C,0x4C}, {0x6D,0x4D}, {0x6E,0x4E}, {0x6F,0x4F}, 
+  {0x70,0x50}, {0x71,0x51}, {0x72,0x52}, {0x73,0x53}, {0x74,0x54}, 
+  {0x75,0x55}, {0x76,0x56}, {0x77,0x57}, {0x78,0x58}, {0x79,0x59}, 
+  {0x7A,0x5A}, {0xE0,0xC0}, {0xE1,0xC1}, {0xE2,0xC2}, {0xE3,0xC3}, 
+  {0xE4,0xC4}, {0xE5,0xC5}, {0xE6,0xC6}, {0xE7,0xC7}, {0xE8,0xC8}, 
+  {0xE9,0xC9}, {0xEA,0xCA}, {0xEB,0xCB}, {0xEC,0xCC}, {0xED,0xCD}, 
+  {0xEE,0xCE}, {0xEF,0xCF}, {0xF0,0xD0}, {0xF1,0xD1}, {0xF2,0xD2}, 
+  {0xF3,0xD3}, {0xF4,0xD4}, {0xF5,0xD5}, {0xF6,0xD6}, {0xF8,0xD8}, 
+  {0xF9,0xD9}, {0xFA,0xDA}, {0xFB,0xDB}, {0xFC,0xDC}, {0xFD,0xDD}, 
+  {0xFE,0xDE}, {0xFF,0x178}, {0x101,0x100}, {0x103,0x102}, {0x105,0x104}, 
+  {0x107,0x106}, {0x109,0x108}, {0x10B,0x10A}, {0x10D,0x10C}, {0x10F,0x10E}, 
+  {0x111,0x110}, {0x113,0x112}, {0x115,0x114}, {0x117,0x116}, {0x119,0x118}, 
+  {0x11B,0x11A}, {0x11D,0x11C}, {0x11F,0x11E}, {0x121,0x120}, {0x123,0x122}, 
+  {0x125,0x124}, {0x127,0x126}, {0x129,0x128}, {0x12B,0x12A}, {0x12D,0x12C}, 
+  {0x12F,0x12E}, {0x131,0x49}, {0x133,0x132}, {0x135,0x134}, {0x137,0x136}, 
+  {0x13A,0x139}, {0x13C,0x13B}, {0x13E,0x13D}, {0x140,0x13F}, {0x142,0x141}, 
+  {0x144,0x143}, {0x146,0x145}, {0x148,0x147}, {0x14B,0x14A}, {0x14D,0x14C}, 
+  {0x14F,0x14E}, {0x151,0x150}, {0x153,0x152}, {0x155,0x154}, {0x157,0x156}, 
+  {0x159,0x158}, {0x15B,0x15A}, {0x15D,0x15C}, {0x15F,0x15E}, {0x161,0x160}, 
+  {0x163,0x162}, {0x165,0x164}, {0x167,0x166}, {0x169,0x168}, {0x16B,0x16A}, 
+  {0x16D,0x16C}, {0x16F,0x16E}, {0x171,0x170}, {0x173,0x172}, {0x175,0x174}, 
+  {0x177,0x176}, {0x17A,0x179}, {0x17C,0x17B}, {0x17E,0x17D}, {0x17F,0x53}, 
+  {0x183,0x182}, {0x185,0x184}, {0x188,0x187}, {0x18C,0x18B}, {0x192,0x191}, 
+  {0x199,0x198}, {0x1A1,0x1A0}, {0x1A3,0x1A2}, {0x1A5,0x1A4}, {0x1A8,0x1A7}, 
+  {0x1AD,0x1AC}, {0x1B0,0x1AF}, {0x1B4,0x1B3}, {0x1B6,0x1B5}, {0x1B9,0x1B8}, 
+  {0x1BD,0x1BC}, {0x1C5,0x1C4}, {0x1C6,0x1C4}, {0x1C8,0x1C7}, {0x1C9,0x1C7}, 
+  {0x1CB,0x1CA}, {0x1CC,0x1CA}, {0x1CE,0x1CD}, {0x1D0,0x1CF}, {0x1D2,0x1D1}, 
+  {0x1D4,0x1D3}, {0x1D6,0x1D5}, {0x1D8,0x1D7}, {0x1DA,0x1D9}, {0x1DC,0x1DB}, 
+  {0x1DD,0x18E}, {0x1DF,0x1DE}, {0x1E1,0x1E0}, {0x1E3,0x1E2}, {0x1E5,0x1E4}, 
+  {0x1E7,0x1E6}, {0x1E9,0x1E8}, {0x1EB,0x1EA}, {0x1ED,0x1EC}, {0x1EF,0x1EE}, 
+  {0x1F2,0x1F1}, {0x1F3,0x1F1}, {0x1F5,0x1F4}, {0x1FB,0x1FA}, {0x1FD,0x1FC}, 
+  {0x1FF,0x1FE}, {0x201,0x200}, {0x203,0x202}, {0x205,0x204}, {0x207,0x206}, 
+  {0x209,0x208}, {0x20B,0x20A}, {0x20D,0x20C}, {0x20F,0x20E}, {0x211,0x210}, 
+  {0x213,0x212}, {0x215,0x214}, {0x217,0x216}, {0x253,0x181}, {0x254,0x186}, 
+  {0x256,0x189}, {0x257,0x18A}, {0x259,0x18F}, {0x25B,0x190}, {0x260,0x193}, 
+  {0x263,0x194}, {0x268,0x197}, {0x269,0x196}, {0x26F,0x19C}, {0x272,0x19D}, 
+  {0x275,0x19F}, {0x283,0x1A9}, {0x288,0x1AE}, {0x28A,0x1B1}, {0x28B,0x1B2}, 
+  {0x292,0x1B7}, {0x3AC,0x386}, {0x3AD,0x388}, {0x3AE,0x389}, {0x3AF,0x38A}, 
+  {0x3B1,0x391}, {0x3B2,0x392}, {0x3B3,0x393}, {0x3B4,0x394}, {0x3B5,0x395}, 
+  {0x3B6,0x396}, {0x3B7,0x397}, {0x3B8,0x398}, {0x3B9,0x399}, {0x3BA,0x39A}, 
+  {0x3BB,0x39B}, {0x3BC,0x39C}, {0x3BD,0x39D}, {0x3BE,0x39E}, {0x3BF,0x39F}, 
+  {0x3C0,0x3A0}, {0x3C1,0x3A1}, {0x3C2,0x3A3}, {0x3C3,0x3A3}, {0x3C4,0x3A4}, 
+  {0x3C5,0x3A5}, {0x3C6,0x3A6}, {0x3C7,0x3A7}, {0x3C8,0x3A8}, {0x3C9,0x3A9}, 
+  {0x3CA,0x3AA}, {0x3CB,0x3AB}, {0x3CC,0x38C}, {0x3CD,0x38E}, {0x3CE,0x38F}, 
+  {0x3D0,0x392}, {0x3D1,0x398}, {0x3D5,0x3A6}, {0x3D6,0x3A0}, {0x3E3,0x3E2}, 
+  {0x3E5,0x3E4}, {0x3E7,0x3E6}, {0x3E9,0x3E8}, {0x3EB,0x3EA}, {0x3ED,0x3EC}, 
+  {0x3EF,0x3EE}, {0x3F0,0x39A}, {0x3F1,0x3A1}, {0x3F2,0x3A3}, {0x430,0x410}, 
+  {0x431,0x411}, {0x432,0x412}, {0x433,0x413}, {0x434,0x414}, {0x435,0x415}, 
+  {0x436,0x416}, {0x437,0x417}, {0x438,0x418}, {0x439,0x419}, {0x43A,0x41A}, 
+  {0x43B,0x41B}, {0x43C,0x41C}, {0x43D,0x41D}, {0x43E,0x41E}, {0x43F,0x41F}, 
+  {0x440,0x420}, {0x441,0x421}, {0x442,0x422}, {0x443,0x423}, {0x444,0x424}, 
+  {0x445,0x425}, {0x446,0x426}, {0x447,0x427}, {0x448,0x428}, {0x449,0x429}, 
+  {0x44A,0x42A}, {0x44B,0x42B}, {0x44C,0x42C}, {0x44D,0x42D}, {0x44E,0x42E}, 
+  {0x44F,0x42F}, {0x451,0x401}, {0x452,0x402}, {0x453,0x403}, {0x454,0x404}, 
+  {0x455,0x405}, {0x456,0x406}, {0x457,0x407}, {0x458,0x408}, {0x459,0x409}, 
+  {0x45A,0x40A}, {0x45B,0x40B}, {0x45C,0x40C}, {0x45E,0x40E}, {0x45F,0x40F}, 
+  {0x461,0x460}, {0x463,0x462}, {0x465,0x464}, {0x467,0x466}, {0x469,0x468}, 
+  {0x46B,0x46A}, {0x46D,0x46C}, {0x46F,0x46E}, {0x471,0x470}, {0x473,0x472}, 
+  {0x475,0x474}, {0x477,0x476}, {0x479,0x478}, {0x47B,0x47A}, {0x47D,0x47C}, 
+  {0x47F,0x47E}, {0x481,0x480}, {0x491,0x490}, {0x493,0x492}, {0x495,0x494}, 
+  {0x497,0x496}, {0x499,0x498}, {0x49B,0x49A}, {0x49D,0x49C}, {0x49F,0x49E}, 
+  {0x4A1,0x4A0}, {0x4A3,0x4A2}, {0x4A5,0x4A4}, {0x4A7,0x4A6}, {0x4A9,0x4A8}, 
+  {0x4AB,0x4AA}, {0x4AD,0x4AC}, {0x4AF,0x4AE}, {0x4B1,0x4B0}, {0x4B3,0x4B2}, 
+  {0x4B5,0x4B4}, {0x4B7,0x4B6}, {0x4B9,0x4B8}, {0x4BB,0x4BA}, {0x4BD,0x4BC}, 
+  {0x4BF,0x4BE}, {0x4C2,0x4C1}, {0x4C4,0x4C3}, {0x4C8,0x4C7}, {0x4CC,0x4CB}, 
+  {0x4D1,0x4D0}, {0x4D3,0x4D2}, {0x4D5,0x4D4}, {0x4D7,0x4D6}, {0x4D9,0x4D8}, 
+  {0x4DB,0x4DA}, {0x4DD,0x4DC}, {0x4DF,0x4DE}, {0x4E1,0x4E0}, {0x4E3,0x4E2}, 
+  {0x4E5,0x4E4}, {0x4E7,0x4E6}, {0x4E9,0x4E8}, {0x4EB,0x4EA}, {0x4EF,0x4EE}, 
+  {0x4F1,0x4F0}, {0x4F3,0x4F2}, {0x4F5,0x4F4}, {0x4F9,0x4F8}, {0x561,0x531}, 
+  {0x562,0x532}, {0x563,0x533}, {0x564,0x534}, {0x565,0x535}, {0x566,0x536}, 
+  {0x567,0x537}, {0x568,0x538}, {0x569,0x539}, {0x56A,0x53A}, {0x56B,0x53B}, 
+  {0x56C,0x53C}, {0x56D,0x53D}, {0x56E,0x53E}, {0x56F,0x53F}, {0x570,0x540}, 
+  {0x571,0x541}, {0x572,0x542}, {0x573,0x543}, {0x574,0x544}, {0x575,0x545}, 
+  {0x576,0x546}, {0x577,0x547}, {0x578,0x548}, {0x579,0x549}, {0x57A,0x54A}, 
+  {0x57B,0x54B}, {0x57C,0x54C}, {0x57D,0x54D}, {0x57E,0x54E}, {0x57F,0x54F}, 
+  {0x580,0x550}, {0x581,0x551}, {0x582,0x552}, {0x583,0x553}, {0x584,0x554}, 
+  {0x585,0x555}, {0x586,0x556}, {0x1E01,0x1E00}, {0x1E03,0x1E02}, {0x1E05,0x1E04}, 
+  {0x1E07,0x1E06}, {0x1E09,0x1E08}, {0x1E0B,0x1E0A}, {0x1E0D,0x1E0C}, {0x1E0F,0x1E0E}, 
+  {0x1E11,0x1E10}, {0x1E13,0x1E12}, {0x1E15,0x1E14}, {0x1E17,0x1E16}, {0x1E19,0x1E18}, 
+  {0x1E1B,0x1E1A}, {0x1E1D,0x1E1C}, {0x1E1F,0x1E1E}, {0x1E21,0x1E20}, {0x1E23,0x1E22}, 
+  {0x1E25,0x1E24}, {0x1E27,0x1E26}, {0x1E29,0x1E28}, {0x1E2B,0x1E2A}, {0x1E2D,0x1E2C}, 
+  {0x1E2F,0x1E2E}, {0x1E31,0x1E30}, {0x1E33,0x1E32}, {0x1E35,0x1E34}, {0x1E37,0x1E36}, 
+  {0x1E39,0x1E38}, {0x1E3B,0x1E3A}, {0x1E3D,0x1E3C}, {0x1E3F,0x1E3E}, {0x1E41,0x1E40}, 
+  {0x1E43,0x1E42}, {0x1E45,0x1E44}, {0x1E47,0x1E46}, {0x1E49,0x1E48}, {0x1E4B,0x1E4A}, 
+  {0x1E4D,0x1E4C}, {0x1E4F,0x1E4E}, {0x1E51,0x1E50}, {0x1E53,0x1E52}, {0x1E55,0x1E54}, 
+  {0x1E57,0x1E56}, {0x1E59,0x1E58}, {0x1E5B,0x1E5A}, {0x1E5D,0x1E5C}, {0x1E5F,0x1E5E}, 
+  {0x1E61,0x1E60}, {0x1E63,0x1E62}, {0x1E65,0x1E64}, {0x1E67,0x1E66}, {0x1E69,0x1E68}, 
+  {0x1E6B,0x1E6A}, {0x1E6D,0x1E6C}, {0x1E6F,0x1E6E}, {0x1E71,0x1E70}, {0x1E73,0x1E72}, 
+  {0x1E75,0x1E74}, {0x1E77,0x1E76}, {0x1E79,0x1E78}, {0x1E7B,0x1E7A}, {0x1E7D,0x1E7C}, 
+  {0x1E7F,0x1E7E}, {0x1E81,0x1E80}, {0x1E83,0x1E82}, {0x1E85,0x1E84}, {0x1E87,0x1E86}, 
+  {0x1E89,0x1E88}, {0x1E8B,0x1E8A}, {0x1E8D,0x1E8C}, {0x1E8F,0x1E8E}, {0x1E91,0x1E90}, 
+  {0x1E93,0x1E92}, {0x1E95,0x1E94}, {0x1E9B,0x1E60}, {0x1EA1,0x1EA0}, {0x1EA3,0x1EA2}, 
+  {0x1EA5,0x1EA4}, {0x1EA7,0x1EA6}, {0x1EA9,0x1EA8}, {0x1EAB,0x1EAA}, {0x1EAD,0x1EAC}, 
+  {0x1EAF,0x1EAE}, {0x1EB1,0x1EB0}, {0x1EB3,0x1EB2}, {0x1EB5,0x1EB4}, {0x1EB7,0x1EB6}, 
+  {0x1EB9,0x1EB8}, {0x1EBB,0x1EBA}, {0x1EBD,0x1EBC}, {0x1EBF,0x1EBE}, {0x1EC1,0x1EC0}, 
+  {0x1EC3,0x1EC2}, {0x1EC5,0x1EC4}, {0x1EC7,0x1EC6}, {0x1EC9,0x1EC8}, {0x1ECB,0x1ECA}, 
+  {0x1ECD,0x1ECC}, {0x1ECF,0x1ECE}, {0x1ED1,0x1ED0}, {0x1ED3,0x1ED2}, {0x1ED5,0x1ED4}, 
+  {0x1ED7,0x1ED6}, {0x1ED9,0x1ED8}, {0x1EDB,0x1EDA}, {0x1EDD,0x1EDC}, {0x1EDF,0x1EDE}, 
+  {0x1EE1,0x1EE0}, {0x1EE3,0x1EE2}, {0x1EE5,0x1EE4}, {0x1EE7,0x1EE6}, {0x1EE9,0x1EE8}, 
+  {0x1EEB,0x1EEA}, {0x1EED,0x1EEC}, {0x1EEF,0x1EEE}, {0x1EF1,0x1EF0}, {0x1EF3,0x1EF2}, 
+  {0x1EF5,0x1EF4}, {0x1EF7,0x1EF6}, {0x1EF9,0x1EF8}, {0x1F00,0x1F08}, {0x1F01,0x1F09}, 
+  {0x1F02,0x1F0A}, {0x1F03,0x1F0B}, {0x1F04,0x1F0C}, {0x1F05,0x1F0D}, {0x1F06,0x1F0E}, 
+  {0x1F07,0x1F0F}, {0x1F10,0x1F18}, {0x1F11,0x1F19}, {0x1F12,0x1F1A}, {0x1F13,0x1F1B}, 
+  {0x1F14,0x1F1C}, {0x1F15,0x1F1D}, {0x1F20,0x1F28}, {0x1F21,0x1F29}, {0x1F22,0x1F2A}, 
+  {0x1F23,0x1F2B}, {0x1F24,0x1F2C}, {0x1F25,0x1F2D}, {0x1F26,0x1F2E}, {0x1F27,0x1F2F}, 
+  {0x1F30,0x1F38}, {0x1F31,0x1F39}, {0x1F32,0x1F3A}, {0x1F33,0x1F3B}, {0x1F34,0x1F3C}, 
+  {0x1F35,0x1F3D}, {0x1F36,0x1F3E}, {0x1F37,0x1F3F}, {0x1F40,0x1F48}, {0x1F41,0x1F49}, 
+  {0x1F42,0x1F4A}, {0x1F43,0x1F4B}, {0x1F44,0x1F4C}, {0x1F45,0x1F4D}, {0x1F51,0x1F59}, 
+  {0x1F53,0x1F5B}, {0x1F55,0x1F5D}, {0x1F57,0x1F5F}, {0x1F60,0x1F68}, {0x1F61,0x1F69}, 
+  {0x1F62,0x1F6A}, {0x1F63,0x1F6B}, {0x1F64,0x1F6C}, {0x1F65,0x1F6D}, {0x1F66,0x1F6E}, 
+  {0x1F67,0x1F6F}, {0x1F70,0x1FBA}, {0x1F71,0x1FBB}, {0x1F72,0x1FC8}, {0x1F73,0x1FC9}, 
+  {0x1F74,0x1FCA}, {0x1F75,0x1FCB}, {0x1F76,0x1FDA}, {0x1F77,0x1FDB}, {0x1F78,0x1FF8}, 
+  {0x1F79,0x1FF9}, {0x1F7A,0x1FEA}, {0x1F7B,0x1FEB}, {0x1F7C,0x1FFA}, {0x1F7D,0x1FFB}, 
+  {0x1F80,0x1F88}, {0x1F81,0x1F89}, {0x1F82,0x1F8A}, {0x1F83,0x1F8B}, {0x1F84,0x1F8C}, 
+  {0x1F85,0x1F8D}, {0x1F86,0x1F8E}, {0x1F87,0x1F8F}, {0x1F90,0x1F98}, {0x1F91,0x1F99}, 
+  {0x1F92,0x1F9A}, {0x1F93,0x1F9B}, {0x1F94,0x1F9C}, {0x1F95,0x1F9D}, {0x1F96,0x1F9E}, 
+  {0x1F97,0x1F9F}, {0x1FA0,0x1FA8}, {0x1FA1,0x1FA9}, {0x1FA2,0x1FAA}, {0x1FA3,0x1FAB}, 
+  {0x1FA4,0x1FAC}, {0x1FA5,0x1FAD}, {0x1FA6,0x1FAE}, {0x1FA7,0x1FAF}, {0x1FB0,0x1FB8}, 
+  {0x1FB1,0x1FB9}, {0x1FB3,0x1FBC}, {0x1FC3,0x1FCC}, {0x1FD0,0x1FD8}, {0x1FD1,0x1FD9}, 
+  {0x1FE0,0x1FE8}, {0x1FE1,0x1FE9}, {0x1FE5,0x1FEC}, {0x1FF3,0x1FFC}, {0x2170,0x2160}, 
+  {0x2171,0x2161}, {0x2172,0x2162}, {0x2173,0x2163}, {0x2174,0x2164}, {0x2175,0x2165}, 
+  {0x2176,0x2166}, {0x2177,0x2167}, {0x2178,0x2168}, {0x2179,0x2169}, {0x217A,0x216A}, 
+  {0x217B,0x216B}, {0x217C,0x216C}, {0x217D,0x216D}, {0x217E,0x216E}, {0x217F,0x216F}, 
+  {0x24D0,0x24B6}, {0x24D1,0x24B7}, {0x24D2,0x24B8}, {0x24D3,0x24B9}, {0x24D4,0x24BA}, 
+  {0x24D5,0x24BB}, {0x24D6,0x24BC}, {0x24D7,0x24BD}, {0x24D8,0x24BE}, {0x24D9,0x24BF}, 
+  {0x24DA,0x24C0}, {0x24DB,0x24C1}, {0x24DC,0x24C2}, {0x24DD,0x24C3}, {0x24DE,0x24C4}, 
+  {0x24DF,0x24C5}, {0x24E0,0x24C6}, {0x24E1,0x24C7}, {0x24E2,0x24C8}, {0x24E3,0x24C9}, 
+  {0x24E4,0x24CA}, {0x24E5,0x24CB}, {0x24E6,0x24CC}, {0x24E7,0x24CD}, {0x24E8,0x24CE}, 
+  {0x24E9,0x24CF}, {0xFF41,0xFF21}, {0xFF42,0xFF22}, {0xFF43,0xFF23}, {0xFF44,0xFF24}, 
+  {0xFF45,0xFF25}, {0xFF46,0xFF26}, {0xFF47,0xFF27}, {0xFF48,0xFF28}, {0xFF49,0xFF29}, 
+  {0xFF4A,0xFF2A}, {0xFF4B,0xFF2B}, {0xFF4C,0xFF2C}, {0xFF4D,0xFF2D}, {0xFF4E,0xFF2E}, 
+  {0xFF4F,0xFF2F}, {0xFF50,0xFF30}, {0xFF51,0xFF31}, {0xFF52,0xFF32}, {0xFF53,0xFF33}, 
+  {0xFF54,0xFF34}, {0xFF55,0xFF35}, {0xFF56,0xFF36}, {0xFF57,0xFF37}, {0xFF58,0xFF38}, 
+  {0xFF59,0xFF39}, {0xFF5A,0xFF3A} 
+};
+
+
+
+/* All lower-case translations are included here */
+
+#define NUM_TOLOWER_INFO 705
+static const unirelate tolower_info[NUM_TOLOWER_INFO] = {
+  {0x41,0x61}, {0x42,0x62}, {0x43,0x63}, {0x44,0x64}, {0x45,0x65}, 
+  {0x46,0x66}, {0x47,0x67}, {0x48,0x68}, {0x49,0x69}, {0x4A,0x6A}, 
+  {0x4B,0x6B}, {0x4C,0x6C}, {0x4D,0x6D}, {0x4E,0x6E}, {0x4F,0x6F}, 
+  {0x50,0x70}, {0x51,0x71}, {0x52,0x72}, {0x53,0x73}, {0x54,0x74}, 
+  {0x55,0x75}, {0x56,0x76}, {0x57,0x77}, {0x58,0x78}, {0x59,0x79}, 
+  {0x5A,0x7A}, {0xC0,0xE0}, {0xC1,0xE1}, {0xC2,0xE2}, {0xC3,0xE3}, 
+  {0xC4,0xE4}, {0xC5,0xE5}, {0xC6,0xE6}, {0xC7,0xE7}, {0xC8,0xE8}, 
+  {0xC9,0xE9}, {0xCA,0xEA}, {0xCB,0xEB}, {0xCC,0xEC}, {0xCD,0xED}, 
+  {0xCE,0xEE}, {0xCF,0xEF}, {0xD0,0xF0}, {0xD1,0xF1}, {0xD2,0xF2}, 
+  {0xD3,0xF3}, {0xD4,0xF4}, {0xD5,0xF5}, {0xD6,0xF6}, {0xD8,0xF8}, 
+  {0xD9,0xF9}, {0xDA,0xFA}, {0xDB,0xFB}, {0xDC,0xFC}, {0xDD,0xFD}, 
+  {0xDE,0xFE}, {0x100,0x101}, {0x102,0x103}, {0x104,0x105}, {0x106,0x107}, 
+  {0x108,0x109}, {0x10A,0x10B}, {0x10C,0x10D}, {0x10E,0x10F}, {0x110,0x111}, 
+  {0x112,0x113}, {0x114,0x115}, {0x116,0x117}, {0x118,0x119}, {0x11A,0x11B}, 
+  {0x11C,0x11D}, {0x11E,0x11F}, {0x120,0x121}, {0x122,0x123}, {0x124,0x125}, 
+  {0x126,0x127}, {0x128,0x129}, {0x12A,0x12B}, {0x12C,0x12D}, {0x12E,0x12F}, 
+  {0x130,0x69}, {0x132,0x133}, {0x134,0x135}, {0x136,0x137}, {0x139,0x13A}, 
+  {0x13B,0x13C}, {0x13D,0x13E}, {0x13F,0x140}, {0x141,0x142}, {0x143,0x144}, 
+  {0x145,0x146}, {0x147,0x148}, {0x14A,0x14B}, {0x14C,0x14D}, {0x14E,0x14F}, 
+  {0x150,0x151}, {0x152,0x153}, {0x154,0x155}, {0x156,0x157}, {0x158,0x159}, 
+  {0x15A,0x15B}, {0x15C,0x15D}, {0x15E,0x15F}, {0x160,0x161}, {0x162,0x163}, 
+  {0x164,0x165}, {0x166,0x167}, {0x168,0x169}, {0x16A,0x16B}, {0x16C,0x16D}, 
+  {0x16E,0x16F}, {0x170,0x171}, {0x172,0x173}, {0x174,0x175}, {0x176,0x177}, 
+  {0x178,0xFF}, {0x179,0x17A}, {0x17B,0x17C}, {0x17D,0x17E}, {0x181,0x253}, 
+  {0x182,0x183}, {0x184,0x185}, {0x186,0x254}, {0x187,0x188}, {0x189,0x256}, 
+  {0x18A,0x257}, {0x18B,0x18C}, {0x18E,0x1DD}, {0x18F,0x259}, {0x190,0x25B}, 
+  {0x191,0x192}, {0x193,0x260}, {0x194,0x263}, {0x196,0x269}, {0x197,0x268}, 
+  {0x198,0x199}, {0x19C,0x26F}, {0x19D,0x272}, {0x19F,0x275}, {0x1A0,0x1A1}, 
+  {0x1A2,0x1A3}, {0x1A4,0x1A5}, {0x1A7,0x1A8}, {0x1A9,0x283}, {0x1AC,0x1AD}, 
+  {0x1AE,0x288}, {0x1AF,0x1B0}, {0x1B1,0x28A}, {0x1B2,0x28B}, {0x1B3,0x1B4}, 
+  {0x1B5,0x1B6}, {0x1B7,0x292}, {0x1B8,0x1B9}, {0x1BC,0x1BD}, {0x1C4,0x1C6}, 
+  {0x1C5,0x1C6}, {0x1C7,0x1C9}, {0x1C8,0x1C9}, {0x1CA,0x1CC}, {0x1CB,0x1CC}, 
+  {0x1CD,0x1CE}, {0x1CF,0x1D0}, {0x1D1,0x1D2}, {0x1D3,0x1D4}, {0x1D5,0x1D6}, 
+  {0x1D7,0x1D8}, {0x1D9,0x1DA}, {0x1DB,0x1DC}, {0x1DE,0x1DF}, {0x1E0,0x1E1}, 
+  {0x1E2,0x1E3}, {0x1E4,0x1E5}, {0x1E6,0x1E7}, {0x1E8,0x1E9}, {0x1EA,0x1EB}, 
+  {0x1EC,0x1ED}, {0x1EE,0x1EF}, {0x1F1,0x1F3}, {0x1F2,0x1F3}, {0x1F4,0x1F5}, 
+  {0x1FA,0x1FB}, {0x1FC,0x1FD}, {0x1FE,0x1FF}, {0x200,0x201}, {0x202,0x203}, 
+  {0x204,0x205}, {0x206,0x207}, {0x208,0x209}, {0x20A,0x20B}, {0x20C,0x20D}, 
+  {0x20E,0x20F}, {0x210,0x211}, {0x212,0x213}, {0x214,0x215}, {0x216,0x217}, 
+  {0x386,0x3AC}, {0x388,0x3AD}, {0x389,0x3AE}, {0x38A,0x3AF}, {0x38C,0x3CC}, 
+  {0x38E,0x3CD}, {0x38F,0x3CE}, {0x391,0x3B1}, {0x392,0x3B2}, {0x393,0x3B3}, 
+  {0x394,0x3B4}, {0x395,0x3B5}, {0x396,0x3B6}, {0x397,0x3B7}, {0x398,0x3B8}, 
+  {0x399,0x3B9}, {0x39A,0x3BA}, {0x39B,0x3BB}, {0x39C,0x3BC}, {0x39D,0x3BD}, 
+  {0x39E,0x3BE}, {0x39F,0x3BF}, {0x3A0,0x3C0}, {0x3A1,0x3C1}, {0x3A3,0x3C3}, 
+  {0x3A4,0x3C4}, {0x3A5,0x3C5}, {0x3A6,0x3C6}, {0x3A7,0x3C7}, {0x3A8,0x3C8}, 
+  {0x3A9,0x3C9}, {0x3AA,0x3CA}, {0x3AB,0x3CB}, {0x3E2,0x3E3}, {0x3E4,0x3E5}, 
+  {0x3E6,0x3E7}, {0x3E8,0x3E9}, {0x3EA,0x3EB}, {0x3EC,0x3ED}, {0x3EE,0x3EF}, 
+  {0x401,0x451}, {0x402,0x452}, {0x403,0x453}, {0x404,0x454}, {0x405,0x455}, 
+  {0x406,0x456}, {0x407,0x457}, {0x408,0x458}, {0x409,0x459}, {0x40A,0x45A}, 
+  {0x40B,0x45B}, {0x40C,0x45C}, {0x40E,0x45E}, {0x40F,0x45F}, {0x410,0x430}, 
+  {0x411,0x431}, {0x412,0x432}, {0x413,0x433}, {0x414,0x434}, {0x415,0x435}, 
+  {0x416,0x436}, {0x417,0x437}, {0x418,0x438}, {0x419,0x439}, {0x41A,0x43A}, 
+  {0x41B,0x43B}, {0x41C,0x43C}, {0x41D,0x43D}, {0x41E,0x43E}, {0x41F,0x43F}, 
+  {0x420,0x440}, {0x421,0x441}, {0x422,0x442}, {0x423,0x443}, {0x424,0x444}, 
+  {0x425,0x445}, {0x426,0x446}, {0x427,0x447}, {0x428,0x448}, {0x429,0x449}, 
+  {0x42A,0x44A}, {0x42B,0x44B}, {0x42C,0x44C}, {0x42D,0x44D}, {0x42E,0x44E}, 
+  {0x42F,0x44F}, {0x460,0x461}, {0x462,0x463}, {0x464,0x465}, {0x466,0x467}, 
+  {0x468,0x469}, {0x46A,0x46B}, {0x46C,0x46D}, {0x46E,0x46F}, {0x470,0x471}, 
+  {0x472,0x473}, {0x474,0x475}, {0x476,0x477}, {0x478,0x479}, {0x47A,0x47B}, 
+  {0x47C,0x47D}, {0x47E,0x47F}, {0x480,0x481}, {0x490,0x491}, {0x492,0x493}, 
+  {0x494,0x495}, {0x496,0x497}, {0x498,0x499}, {0x49A,0x49B}, {0x49C,0x49D}, 
+  {0x49E,0x49F}, {0x4A0,0x4A1}, {0x4A2,0x4A3}, {0x4A4,0x4A5}, {0x4A6,0x4A7}, 
+  {0x4A8,0x4A9}, {0x4AA,0x4AB}, {0x4AC,0x4AD}, {0x4AE,0x4AF}, {0x4B0,0x4B1}, 
+  {0x4B2,0x4B3}, {0x4B4,0x4B5}, {0x4B6,0x4B7}, {0x4B8,0x4B9}, {0x4BA,0x4BB}, 
+  {0x4BC,0x4BD}, {0x4BE,0x4BF}, {0x4C1,0x4C2}, {0x4C3,0x4C4}, {0x4C7,0x4C8}, 
+  {0x4CB,0x4CC}, {0x4D0,0x4D1}, {0x4D2,0x4D3}, {0x4D4,0x4D5}, {0x4D6,0x4D7}, 
+  {0x4D8,0x4D9}, {0x4DA,0x4DB}, {0x4DC,0x4DD}, {0x4DE,0x4DF}, {0x4E0,0x4E1}, 
+  {0x4E2,0x4E3}, {0x4E4,0x4E5}, {0x4E6,0x4E7}, {0x4E8,0x4E9}, {0x4EA,0x4EB}, 
+  {0x4EE,0x4EF}, {0x4F0,0x4F1}, {0x4F2,0x4F3}, {0x4F4,0x4F5}, {0x4F8,0x4F9}, 
+  {0x531,0x561}, {0x532,0x562}, {0x533,0x563}, {0x534,0x564}, {0x535,0x565}, 
+  {0x536,0x566}, {0x537,0x567}, {0x538,0x568}, {0x539,0x569}, {0x53A,0x56A}, 
+  {0x53B,0x56B}, {0x53C,0x56C}, {0x53D,0x56D}, {0x53E,0x56E}, {0x53F,0x56F}, 
+  {0x540,0x570}, {0x541,0x571}, {0x542,0x572}, {0x543,0x573}, {0x544,0x574}, 
+  {0x545,0x575}, {0x546,0x576}, {0x547,0x577}, {0x548,0x578}, {0x549,0x579}, 
+  {0x54A,0x57A}, {0x54B,0x57B}, {0x54C,0x57C}, {0x54D,0x57D}, {0x54E,0x57E}, 
+  {0x54F,0x57F}, {0x550,0x580}, {0x551,0x581}, {0x552,0x582}, {0x553,0x583}, 
+  {0x554,0x584}, {0x555,0x585}, {0x556,0x586}, {0x10A0,0x10D0}, {0x10A1,0x10D1}, 
+  {0x10A2,0x10D2}, {0x10A3,0x10D3}, {0x10A4,0x10D4}, {0x10A5,0x10D5}, {0x10A6,0x10D6}, 
+  {0x10A7,0x10D7}, {0x10A8,0x10D8}, {0x10A9,0x10D9}, {0x10AA,0x10DA}, {0x10AB,0x10DB}, 
+  {0x10AC,0x10DC}, {0x10AD,0x10DD}, {0x10AE,0x10DE}, {0x10AF,0x10DF}, {0x10B0,0x10E0}, 
+  {0x10B1,0x10E1}, {0x10B2,0x10E2}, {0x10B3,0x10E3}, {0x10B4,0x10E4}, {0x10B5,0x10E5}, 
+  {0x10B6,0x10E6}, {0x10B7,0x10E7}, {0x10B8,0x10E8}, {0x10B9,0x10E9}, {0x10BA,0x10EA}, 
+  {0x10BB,0x10EB}, {0x10BC,0x10EC}, {0x10BD,0x10ED}, {0x10BE,0x10EE}, {0x10BF,0x10EF}, 
+  {0x10C0,0x10F0}, {0x10C1,0x10F1}, {0x10C2,0x10F2}, {0x10C3,0x10F3}, {0x10C4,0x10F4}, 
+  {0x10C5,0x10F5}, {0x1E00,0x1E01}, {0x1E02,0x1E03}, {0x1E04,0x1E05}, {0x1E06,0x1E07}, 
+  {0x1E08,0x1E09}, {0x1E0A,0x1E0B}, {0x1E0C,0x1E0D}, {0x1E0E,0x1E0F}, {0x1E10,0x1E11}, 
+  {0x1E12,0x1E13}, {0x1E14,0x1E15}, {0x1E16,0x1E17}, {0x1E18,0x1E19}, {0x1E1A,0x1E1B}, 
+  {0x1E1C,0x1E1D}, {0x1E1E,0x1E1F}, {0x1E20,0x1E21}, {0x1E22,0x1E23}, {0x1E24,0x1E25}, 
+  {0x1E26,0x1E27}, {0x1E28,0x1E29}, {0x1E2A,0x1E2B}, {0x1E2C,0x1E2D}, {0x1E2E,0x1E2F}, 
+  {0x1E30,0x1E31}, {0x1E32,0x1E33}, {0x1E34,0x1E35}, {0x1E36,0x1E37}, {0x1E38,0x1E39}, 
+  {0x1E3A,0x1E3B}, {0x1E3C,0x1E3D}, {0x1E3E,0x1E3F}, {0x1E40,0x1E41}, {0x1E42,0x1E43}, 
+  {0x1E44,0x1E45}, {0x1E46,0x1E47}, {0x1E48,0x1E49}, {0x1E4A,0x1E4B}, {0x1E4C,0x1E4D}, 
+  {0x1E4E,0x1E4F}, {0x1E50,0x1E51}, {0x1E52,0x1E53}, {0x1E54,0x1E55}, {0x1E56,0x1E57}, 
+  {0x1E58,0x1E59}, {0x1E5A,0x1E5B}, {0x1E5C,0x1E5D}, {0x1E5E,0x1E5F}, {0x1E60,0x1E61}, 
+  {0x1E62,0x1E63}, {0x1E64,0x1E65}, {0x1E66,0x1E67}, {0x1E68,0x1E69}, {0x1E6A,0x1E6B}, 
+  {0x1E6C,0x1E6D}, {0x1E6E,0x1E6F}, {0x1E70,0x1E71}, {0x1E72,0x1E73}, {0x1E74,0x1E75}, 
+  {0x1E76,0x1E77}, {0x1E78,0x1E79}, {0x1E7A,0x1E7B}, {0x1E7C,0x1E7D}, {0x1E7E,0x1E7F}, 
+  {0x1E80,0x1E81}, {0x1E82,0x1E83}, {0x1E84,0x1E85}, {0x1E86,0x1E87}, {0x1E88,0x1E89}, 
+  {0x1E8A,0x1E8B}, {0x1E8C,0x1E8D}, {0x1E8E,0x1E8F}, {0x1E90,0x1E91}, {0x1E92,0x1E93}, 
+  {0x1E94,0x1E95}, {0x1EA0,0x1EA1}, {0x1EA2,0x1EA3}, {0x1EA4,0x1EA5}, {0x1EA6,0x1EA7}, 
+  {0x1EA8,0x1EA9}, {0x1EAA,0x1EAB}, {0x1EAC,0x1EAD}, {0x1EAE,0x1EAF}, {0x1EB0,0x1EB1}, 
+  {0x1EB2,0x1EB3}, {0x1EB4,0x1EB5}, {0x1EB6,0x1EB7}, {0x1EB8,0x1EB9}, {0x1EBA,0x1EBB}, 
+  {0x1EBC,0x1EBD}, {0x1EBE,0x1EBF}, {0x1EC0,0x1EC1}, {0x1EC2,0x1EC3}, {0x1EC4,0x1EC5}, 
+  {0x1EC6,0x1EC7}, {0x1EC8,0x1EC9}, {0x1ECA,0x1ECB}, {0x1ECC,0x1ECD}, {0x1ECE,0x1ECF}, 
+  {0x1ED0,0x1ED1}, {0x1ED2,0x1ED3}, {0x1ED4,0x1ED5}, {0x1ED6,0x1ED7}, {0x1ED8,0x1ED9}, 
+  {0x1EDA,0x1EDB}, {0x1EDC,0x1EDD}, {0x1EDE,0x1EDF}, {0x1EE0,0x1EE1}, {0x1EE2,0x1EE3}, 
+  {0x1EE4,0x1EE5}, {0x1EE6,0x1EE7}, {0x1EE8,0x1EE9}, {0x1EEA,0x1EEB}, {0x1EEC,0x1EED}, 
+  {0x1EEE,0x1EEF}, {0x1EF0,0x1EF1}, {0x1EF2,0x1EF3}, {0x1EF4,0x1EF5}, {0x1EF6,0x1EF7}, 
+  {0x1EF8,0x1EF9}, {0x1F08,0x1F00}, {0x1F09,0x1F01}, {0x1F0A,0x1F02}, {0x1F0B,0x1F03}, 
+  {0x1F0C,0x1F04}, {0x1F0D,0x1F05}, {0x1F0E,0x1F06}, {0x1F0F,0x1F07}, {0x1F18,0x1F10}, 
+  {0x1F19,0x1F11}, {0x1F1A,0x1F12}, {0x1F1B,0x1F13}, {0x1F1C,0x1F14}, {0x1F1D,0x1F15}, 
+  {0x1F28,0x1F20}, {0x1F29,0x1F21}, {0x1F2A,0x1F22}, {0x1F2B,0x1F23}, {0x1F2C,0x1F24}, 
+  {0x1F2D,0x1F25}, {0x1F2E,0x1F26}, {0x1F2F,0x1F27}, {0x1F38,0x1F30}, {0x1F39,0x1F31}, 
+  {0x1F3A,0x1F32}, {0x1F3B,0x1F33}, {0x1F3C,0x1F34}, {0x1F3D,0x1F35}, {0x1F3E,0x1F36}, 
+  {0x1F3F,0x1F37}, {0x1F48,0x1F40}, {0x1F49,0x1F41}, {0x1F4A,0x1F42}, {0x1F4B,0x1F43}, 
+  {0x1F4C,0x1F44}, {0x1F4D,0x1F45}, {0x1F59,0x1F51}, {0x1F5B,0x1F53}, {0x1F5D,0x1F55}, 
+  {0x1F5F,0x1F57}, {0x1F68,0x1F60}, {0x1F69,0x1F61}, {0x1F6A,0x1F62}, {0x1F6B,0x1F63}, 
+  {0x1F6C,0x1F64}, {0x1F6D,0x1F65}, {0x1F6E,0x1F66}, {0x1F6F,0x1F67}, {0x1F88,0x1F80}, 
+  {0x1F89,0x1F81}, {0x1F8A,0x1F82}, {0x1F8B,0x1F83}, {0x1F8C,0x1F84}, {0x1F8D,0x1F85}, 
+  {0x1F8E,0x1F86}, {0x1F8F,0x1F87}, {0x1F98,0x1F90}, {0x1F99,0x1F91}, {0x1F9A,0x1F92}, 
+  {0x1F9B,0x1F93}, {0x1F9C,0x1F94}, {0x1F9D,0x1F95}, {0x1F9E,0x1F96}, {0x1F9F,0x1F97}, 
+  {0x1FA8,0x1FA0}, {0x1FA9,0x1FA1}, {0x1FAA,0x1FA2}, {0x1FAB,0x1FA3}, {0x1FAC,0x1FA4}, 
+  {0x1FAD,0x1FA5}, {0x1FAE,0x1FA6}, {0x1FAF,0x1FA7}, {0x1FB8,0x1FB0}, {0x1FB9,0x1FB1}, 
+  {0x1FBA,0x1F70}, {0x1FBB,0x1F71}, {0x1FBC,0x1FB3}, {0x1FC8,0x1F72}, {0x1FC9,0x1F73}, 
+  {0x1FCA,0x1F74}, {0x1FCB,0x1F75}, {0x1FCC,0x1FC3}, {0x1FD8,0x1FD0}, {0x1FD9,0x1FD1}, 
+  {0x1FDA,0x1F76}, {0x1FDB,0x1F77}, {0x1FE8,0x1FE0}, {0x1FE9,0x1FE1}, {0x1FEA,0x1F7A}, 
+  {0x1FEB,0x1F7B}, {0x1FEC,0x1FE5}, {0x1FF8,0x1F78}, {0x1FF9,0x1F79}, {0x1FFA,0x1F7C}, 
+  {0x1FFB,0x1F7D}, {0x1FFC,0x1FF3}, {0x2160,0x2170}, {0x2161,0x2171}, {0x2162,0x2172}, 
+  {0x2163,0x2173}, {0x2164,0x2174}, {0x2165,0x2175}, {0x2166,0x2176}, {0x2167,0x2177}, 
+  {0x2168,0x2178}, {0x2169,0x2179}, {0x216A,0x217A}, {0x216B,0x217B}, {0x216C,0x217C}, 
+  {0x216D,0x217D}, {0x216E,0x217E}, {0x216F,0x217F}, {0x24B6,0x24D0}, {0x24B7,0x24D1}, 
+  {0x24B8,0x24D2}, {0x24B9,0x24D3}, {0x24BA,0x24D4}, {0x24BB,0x24D5}, {0x24BC,0x24D6}, 
+  {0x24BD,0x24D7}, {0x24BE,0x24D8}, {0x24BF,0x24D9}, {0x24C0,0x24DA}, {0x24C1,0x24DB}, 
+  {0x24C2,0x24DC}, {0x24C3,0x24DD}, {0x24C4,0x24DE}, {0x24C5,0x24DF}, {0x24C6,0x24E0}, 
+  {0x24C7,0x24E1}, {0x24C8,0x24E2}, {0x24C9,0x24E3}, {0x24CA,0x24E4}, {0x24CB,0x24E5}, 
+  {0x24CC,0x24E6}, {0x24CD,0x24E7}, {0x24CE,0x24E8}, {0x24CF,0x24E9}, {0xFF21,0xFF41}, 
+  {0xFF22,0xFF42}, {0xFF23,0xFF43}, {0xFF24,0xFF44}, {0xFF25,0xFF45}, {0xFF26,0xFF46}, 
+  {0xFF27,0xFF47}, {0xFF28,0xFF48}, {0xFF29,0xFF49}, {0xFF2A,0xFF4A}, {0xFF2B,0xFF4B}, 
+  {0xFF2C,0xFF4C}, {0xFF2D,0xFF4D}, {0xFF2E,0xFF4E}, {0xFF2F,0xFF4F}, {0xFF30,0xFF50}, 
+  {0xFF31,0xFF51}, {0xFF32,0xFF52}, {0xFF33,0xFF53}, {0xFF34,0xFF54}, {0xFF35,0xFF55}, 
+  {0xFF36,0xFF56}, {0xFF37,0xFF57}, {0xFF38,0xFF58}, {0xFF39,0xFF59}, {0xFF3A,0xFF5A}
+};
+
+
+
+#define NUM_TOSIMPLIFIED_INFO 2145
+static const unirelate tosimplified_info[NUM_TOSIMPLIFIED_INFO] = {
+  {0x4E48,0x9EBD}, {0x4E82,0x4E71}, {0x4E9E,0x4E9A}, {0x4F47,0x4F2B}, {0x4F59,0x9980}, 
+  {0x4F86,0x6765}, {0x4F96,0x4ED1}, {0x4FE0,0x4FA0}, {0x5000,0x4F25}, {0x5006,0x4FE9}, 
+  {0x5009,0x4ED3}, {0x500B,0x4E2A}, {0x5011,0x4EEC}, {0x502B,0x4F26}, {0x5049,0x4F1F}, 
+  {0x5074,0x4FA7}, {0x5075,0x4FA6}, {0x5096,0x4F27}, {0x5098,0x4F1E}, {0x5099,0x5907}, 
+  {0x50AD,0x4F63}, {0x50B3,0x4F20}, {0x50B4,0x4F1B}, {0x50B5,0x503A}, {0x50B7,0x4F24}, 
+  {0x50BE,0x503E}, {0x50C2,0x507B}, {0x50C5,0x4EC5}, {0x50C9,0x4F65}, {0x50D1,0x4FA8}, 
+  {0x50D5,0x4EC6}, {0x50DE,0x4F2A}, {0x50E5,0x4FA5}, {0x50E8,0x507E}, {0x50F9,0x4EF7}, 
+  {0x5100,0x4EEA}, {0x5102,0x4FAC}, {0x5104,0x4EBF}, {0x5108,0x4FA9}, {0x5109,0x4FED}, 
+  {0x5110,0x50A7}, {0x5114,0x4FE6}, {0x5115,0x4FAA}, {0x511F,0x507F}, {0x512A,0x4F18}, 
+  {0x5132,0x50A8}, {0x5137,0x4FEA}, {0x513A,0x50A9}, {0x513B,0x50A5}, {0x513C,0x4FE8}, 
+  {0x5152,0x513F}, {0x5169,0x4E24}, {0x51C8,0x51C0}, {0x51CD,0x51BB}, {0x51F1,0x51EF}, 
+  {0x5244,0x522D}, {0x5247,0x5219}, {0x525B,0x521A}, {0x526E,0x5250}, {0x5274,0x5240}, 
+  {0x5275,0x521B}, {0x5283,0x5212}, {0x5287,0x5267}, {0x5289,0x5218}, {0x528A,0x523D}, 
+  {0x528C,0x523F}, {0x528D,0x5251}, {0x5291,0x5242}, {0x52C1,0x52B2}, {0x52D5,0x52A8}, 
+  {0x52D9,0x52A1}, {0x52DB,0x52CB}, {0x52DD,0x80DC}, {0x52DE,0x52B3}, {0x52E2,0x52BF}, 
+  {0x52F1,0x52A2}, {0x52F5,0x52B1}, {0x52F8,0x529D}, {0x532D,0x5326}, {0x532F,0x6C47}, 
+  {0x5331,0x532E}, {0x5340,0x533A}, {0x5354,0x534F}, {0x5399,0x538D}, {0x53A0,0x5395}, 
+  {0x53AD,0x538C}, {0x53B2,0x5389}, {0x53B4,0x53A3}, {0x53C3,0x53C2}, {0x53E2,0x4E1B}, 
+  {0x540E,0x5F8C}, {0x54BC,0x5459}, {0x54E1,0x5458}, {0x5504,0x5457}, {0x554F,0x95EE}, 
+  {0x5553,0x542F}, {0x555E,0x54D1}, {0x559A,0x5524}, {0x55AA,0x4E27}, {0x55AC,0x4E54}, 
+  {0x55AE,0x5355}, {0x55B2,0x54DF}, {0x55C6,0x545B}, {0x55C7,0x556C}, {0x55CE,0x5417}, 
+  {0x55DA,0x545C}, {0x55E9,0x5522}, {0x55F6,0x54D4}, {0x5606,0x53F9}, {0x560D,0x55BD}, 
+  {0x5614,0x5455}, {0x5616,0x5567}, {0x5617,0x5C1D}, {0x561C,0x551B}, {0x5629,0x54D7}, 
+  {0x562E,0x5520}, {0x562F,0x5578}, {0x5630,0x53FD}, {0x5635,0x54D3}, {0x5638,0x5452}, 
+  {0x565D,0x549D}, {0x5660,0x54D2}, {0x5665,0x54DD}, {0x5666,0x54D5}, {0x566F,0x55F3}, 
+  {0x5672,0x54D9}, {0x5674,0x55B7}, {0x5678,0x5428}, {0x5680,0x549B}, {0x5687,0x5413}, 
+  {0x568C,0x54DC}, {0x5695,0x565C}, {0x5699,0x556E}, {0x56A6,0x5456}, {0x56A8,0x5499}, 
+  {0x56B3,0x55BE}, {0x56B4,0x4E25}, {0x56B6,0x5624}, {0x56C0,0x556D}, {0x56C1,0x55EB}, 
+  {0x56C2,0x56A3}, {0x56C5,0x5181}, {0x56C8,0x5453}, {0x56D1,0x5631}, {0x5707,0x56F5}, 
+  {0x570B,0x56FD}, {0x570D,0x56F4}, {0x5712,0x56ED}, {0x5713,0x5706}, {0x5716,0x56FE}, 
+  {0x5718,0x56E2}, {0x57E1,0x57AD}, {0x57F7,0x6267}, {0x5805,0x575A}, {0x580A,0x57A9}, 
+  {0x5816,0x57B4}, {0x581D,0x57DA}, {0x582F,0x5C27}, {0x5831,0x62A5}, {0x5834,0x573A}, 
+  {0x584A,0x5757}, {0x584B,0x8314}, {0x584F,0x57B2}, {0x5852,0x57D8}, {0x5857,0x6D82}, 
+  {0x5862,0x575E}, {0x5864,0x57D9}, {0x5875,0x5C18}, {0x5879,0x5811}, {0x588A,0x57AB}, 
+  {0x589C,0x5760}, {0x58AE,0x5815}, {0x58B3,0x575F}, {0x58BB,0x5899}, {0x58BE,0x57A6}, 
+  {0x58C7,0x575B}, {0x58D3,0x538B}, {0x58D8,0x5792}, {0x58D9,0x5739}, {0x58DA,0x5786}, 
+  {0x58DE,0x574F}, {0x58DF,0x5784}, {0x58E0,0x5785}, {0x58E2,0x575C}, {0x58E9,0x575D}, 
+  {0x58EF,0x58EE}, {0x58FA,0x58F6}, {0x58FD,0x5BFF}, {0x5922,0x68A6}, {0x593E,0x5939}, 
+  {0x5950,0x5942}, {0x5969,0x5941}, {0x596A,0x593A}, {0x596C,0x5956}, {0x596E,0x594B}, 
+  {0x599D,0x5986}, {0x5A41,0x5A04}, {0x5A66,0x5987}, {0x5A6D,0x5A05}, {0x5AA7,0x5A32}, 
+  {0x5ABD,0x5988}, {0x5AD7,0x59AA}, {0x5AF5,0x59A9}, {0x5AFB,0x5A34}, {0x5B00,0x59AB}, 
+  {0x5B08,0x5A06}, {0x5B0B,0x5A75}, {0x5B0C,0x5A07}, {0x5B19,0x5AF1}, {0x5B21,0x5AD2}, 
+  {0x5B2A,0x5AD4}, {0x5B30,0x5A74}, {0x5B38,0x5A76}, {0x5B4C,0x5A08}, {0x5B6B,0x5B59}, 
+  {0x5B78,0x5B66}, {0x5B7F,0x5B6A}, {0x5BE2,0x5BDD}, {0x5BE6,0x5B9E}, {0x5BE7,0x5B81}, 
+  {0x5BE9,0x5BA1}, {0x5BEB,0x5199}, {0x5BEC,0x5BBD}, {0x5BF5,0x5BA0}, {0x5BF6,0x5B9D}, 
+  {0x5C07,0x5C06}, {0x5C08,0x4E13}, {0x5C0B,0x5BFB}, {0x5C0D,0x5BF9}, {0x5C0E,0x5BFC}, 
+  {0x5C37,0x5C34}, {0x5C62,0x5C61}, {0x5C64,0x5C42}, {0x5C68,0x5C66}, {0x5C6C,0x5C5E}, 
+  {0x5CA1,0x5188}, {0x5CF4,0x5C98}, {0x5CF6,0x5C9B}, {0x5CFD,0x5CE1}, {0x5D0D,0x5D03}, 
+  {0x5D17,0x5C97}, {0x5D22,0x5CE5}, {0x5D2C,0x5CBD}, {0x5D50,0x5C9A}, {0x5D81,0x5D5D}, 
+  {0x5D84,0x5D2D}, {0x5D87,0x5C96}, {0x5D97,0x5D02}, {0x5DA0,0x5CE4}, {0x5DA7,0x5CC4}, 
+  {0x5DB8,0x5D58}, {0x5DBA,0x5CAD}, {0x5DBC,0x5C7F}, {0x5DCB,0x5CBF}, {0x5DD2,0x5CE6}, 
+  {0x5DD4,0x5DC5}, {0x5DF0,0x5DEF}, {0x5E25,0x5E05}, {0x5E2B,0x5E08}, {0x5E33,0x5E10}, 
+  {0x5E36,0x5E26}, {0x5E40,0x5E27}, {0x5E43,0x5E0F}, {0x5E57,0x5E3C}, {0x5E58,0x5E3B}, 
+  {0x5E5F,0x5E1C}, {0x5E63,0x5E01}, {0x5E6B,0x5E2E}, {0x5E6C,0x5E31}, {0x5E79,0x5E72}, 
+  {0x5E7E,0x51E0}, {0x5EAB,0x5E93}, {0x5EDF,0x5E99}, {0x5EE0,0x5382}, {0x5EE1,0x5E91}, 
+  {0x5EE2,0x5E9F}, {0x5EE3,0x5E7F}, {0x5EEC,0x5E90}, {0x5EF3,0x5385}, {0x5F33,0x5F2A}, 
+  {0x5F35,0x5F20}, {0x5F48,0x5F39}, {0x5F4C,0x5F25}, {0x5F4E,0x5F2F}, {0x5F8C,0x540E}, 
+  {0x5F91,0x5F84}, {0x5F9E,0x4ECE}, {0x5FA0,0x5F95}, {0x5FA9,0x590D}, {0x5FB9,0x5F7B}, 
+  {0x60B5,0x6005}, {0x60B6,0x95F7}, {0x60E1,0x6076}, {0x60F1,0x607C}, {0x60F2,0x607D}, 
+  {0x60FB,0x607B}, {0x611B,0x7231}, {0x611C,0x60EC}, {0x6134,0x6006}, {0x6137,0x607A}, 
+  {0x613E,0x5FFE}, {0x614B,0x6001}, {0x6158,0x60E8}, {0x615A,0x60ED}, {0x615F,0x6078}, 
+  {0x6163,0x60EF}, {0x6164,0x60AB}, {0x616A,0x6004}, {0x616B,0x6002}, {0x616E,0x8651}, 
+  {0x6173,0x60AD}, {0x6176,0x5E86}, {0x6182,0x5FE7}, {0x618A,0x60EB}, {0x6190,0x601C}, 
+  {0x6191,0x51ED}, {0x6192,0x6126}, {0x619A,0x60EE}, {0x61A4,0x6124}, {0x61AB,0x60AF}, 
+  {0x61AE,0x6003}, {0x61B2,0x5BAA}, {0x61B6,0x5FC6}, {0x61C7,0x6073}, {0x61C9,0x5E94}, 
+  {0x61CC,0x603F}, {0x61DF,0x603C}, {0x61E3,0x61D1}, {0x61E8,0x6079}, {0x61F2,0x60E9}, 
+  {0x61F6,0x61D2}, {0x61F7,0x6000}, {0x61F8,0x60AC}, {0x61FA,0x5FCF}, {0x61FC,0x60E7}, 
+  {0x61FE,0x6151}, {0x6200,0x604B}, {0x6207,0x6206}, {0x6214,0x620B}, {0x6227,0x6217}, 
+  {0x6229,0x622C}, {0x6230,0x6218}, {0x6232,0x620F}, {0x633E,0x631F}, {0x6368,0x820D}, 
+  {0x636B,0x626A}, {0x6383,0x626B}, {0x6384,0x62A1}, {0x6399,0x6323}, {0x63C0,0x62E3}, 
+  {0x63DA,0x626C}, {0x63DB,0x6362}, {0x63EE,0x6325}, {0x640D,0x635F}, {0x6417,0x6363}, 
+  {0x6436,0x62A2}, {0x6451,0x63B4}, {0x645C,0x63BC}, {0x645F,0x6402}, {0x646F,0x631A}, 
+  {0x6473,0x62A0}, {0x6476,0x629F}, {0x647B,0x63BA}, {0x6488,0x635E}, {0x6493,0x6320}, 
+  {0x649F,0x6322}, {0x64A3,0x63B8}, {0x64A5,0x62E8}, {0x64AB,0x629A}, {0x64B2,0x6251}, 
+  {0x64B3,0x63FF}, {0x64BB,0x631E}, {0x64BE,0x631D}, {0x64BF,0x6361}, {0x64C1,0x62E5}, 
+  {0x64C4,0x63B3}, {0x64C7,0x62E9}, {0x64CA,0x51FB}, {0x64CB,0x6321}, {0x64D4,0x62C5}, 
+  {0x64DA,0x636E}, {0x64E0,0x6324}, {0x64EC,0x62DF}, {0x64EF,0x6448}, {0x64F0,0x62E7}, 
+  {0x64F1,0x6401}, {0x64F2,0x63B7}, {0x64F4,0x6269}, {0x64F7,0x64B7}, {0x64FA,0x6446}, 
+  {0x64FB,0x64DE}, {0x64FC,0x64B8}, {0x64FE,0x6270}, {0x6504,0x6445}, {0x6506,0x64B5}, 
+  {0x650F,0x62E2}, {0x6514,0x62E6}, {0x6516,0x6484}, {0x6519,0x6400}, {0x651B,0x64BA}, 
+  {0x651D,0x6444}, {0x6522,0x6512}, {0x6523,0x631B}, {0x6524,0x644A}, {0x652A,0x6405}, 
+  {0x652C,0x63FD}, {0x6557,0x8D25}, {0x6575,0x654C}, {0x6578,0x6570}, {0x6582,0x655B}, 
+  {0x6583,0x6BD9}, {0x6595,0x6593}, {0x65AC,0x65A9}, {0x65B7,0x65AD}, {0x6642,0x65F6}, 
+  {0x6649,0x664B}, {0x665D,0x663C}, {0x6688,0x6655}, {0x6689,0x6656}, {0x66A2,0x7545}, 
+  {0x66AB,0x6682}, {0x66C4,0x6654}, {0x66C7,0x6619}, {0x66C9,0x6653}, {0x66D6,0x66A7}, 
+  {0x66E0,0x65F7}, {0x66EC,0x6652}, {0x66F8,0x4E66}, {0x6703,0x4F1A}, {0x6727,0x80E7}, 
+  {0x6771,0x4E1C}, {0x6898,0x67A7}, {0x689D,0x6761}, {0x689F,0x67AD}, {0x68C4,0x5F03}, 
+  {0x68D6,0x67A8}, {0x68D7,0x67A3}, {0x68DF,0x680B}, {0x68E7,0x6808}, {0x68F2,0x6816}, 
+  {0x690F,0x6860}, {0x694A,0x6768}, {0x6953,0x67AB}, {0x6968,0x6862}, {0x696D,0x4E1A}, 
+  {0x6975,0x6781}, {0x69AA,0x6769}, {0x69AE,0x8363}, {0x69BF,0x6864}, {0x69CB,0x6784}, 
+  {0x69CD,0x67AA}, {0x69E7,0x6920}, {0x69F3,0x6868}, {0x6A01,0x6869}, {0x6A02,0x4E50}, 
+  {0x6A05,0x679E}, {0x6A13,0x697C}, {0x6A19,0x6807}, {0x6A1E,0x67A2}, {0x6A23,0x6837}, 
+  {0x6A38,0x6734}, {0x6A39,0x6811}, {0x6A3A,0x6866}, {0x6A48,0x6861}, {0x6A4B,0x6865}, 
+  {0x6A5F,0x673A}, {0x6A62,0x692D}, {0x6A89,0x67FD}, {0x6A94,0x6863}, {0x6A9C,0x6867}, 
+  {0x6AA2,0x68C0}, {0x6AA3,0x6A2F}, {0x6AB3,0x69DF}, {0x6AB8,0x67E0}, {0x6ABB,0x69DB}, 
+  {0x6AC3,0x67DC}, {0x6AD3,0x6A79}, {0x6ADA,0x6988}, {0x6ADB,0x6809}, {0x6ADD,0x691F}, 
+  {0x6ADE,0x6A7C}, {0x6ADF,0x680E}, {0x6AE7,0x69E0}, {0x6AE8,0x680C}, {0x6AEA,0x67A5}, 
+  {0x6AEC,0x6987}, {0x6AF3,0x680A}, {0x6AF8,0x6989}, {0x6AFB,0x6A31}, {0x6B04,0x680F}, 
+  {0x6B0A,0x6743}, {0x6B0F,0x6924}, {0x6B12,0x683E}, {0x6B16,0x6984}, {0x6B1E,0x68C2}, 
+  {0x6B3D,0x94A6}, {0x6B50,0x6B27}, {0x6B5F,0x6B24}, {0x6B61,0x6B22}, {0x6B72,0x5C81}, 
+  {0x6B77,0x5386}, {0x6B78,0x5F52}, {0x6B98,0x6B8B}, {0x6B9E,0x6B92}, {0x6BA4,0x6B87}, 
+  {0x6BAB,0x6B9A}, {0x6BAE,0x6B93}, {0x6BAF,0x6BA1}, {0x6BB2,0x6B7C}, {0x6BBA,0x6740}, 
+  {0x6BBB,0x58F3}, {0x6BC6,0x6BB4}, {0x6BFF,0x6BF5}, {0x6C08,0x6BE1}, {0x6C0C,0x6C07}, 
+  {0x6C23,0x6C14}, {0x6C2B,0x6C22}, {0x6C2C,0x6C29}, {0x6D79,0x6D43}, {0x6D87,0x6CFE}, 
+  {0x6DEA,0x6CA6}, {0x6DF5,0x6E0A}, {0x6DF6,0x6D9E}, {0x6DFA,0x6D45}, {0x6E19,0x6DA3}, 
+  {0x6E26,0x6DA1}, {0x6E2C,0x6D4B}, {0x6E3E,0x6D51}, {0x6E5E,0x6D48}, {0x6E6F,0x6C64}, 
+  {0x6E96,0x51C6}, {0x6E9D,0x6C9F}, {0x6EC4,0x6CA7}, {0x6EC5,0x706D}, {0x6ECC,0x6DA4}, 
+  {0x6ECE,0x8365}, {0x6EEC,0x6CAA}, {0x6EEF,0x6EDE}, {0x6EF2,0x6E17}, {0x6EF7,0x5364}, 
+  {0x6EF8,0x6D52}, {0x6EFF,0x6EE1}, {0x6F01,0x6E14}, {0x6F1A,0x6CA4}, {0x6F22,0x6C49}, 
+  {0x6F23,0x6D9F}, {0x6F2C,0x6E0D}, {0x6F32,0x6DA8}, {0x6F38,0x6E10}, {0x6F3F,0x6D46}, 
+  {0x6F41,0x988D}, {0x6F51,0x6CFC}, {0x6F54,0x6D01}, {0x6F59,0x6CA9}, {0x6F5B,0x6F5C}, 
+  {0x6F64,0x6DA6}, {0x6F6F,0x6D54}, {0x6F70,0x6E83}, {0x6F77,0x6ED7}, {0x6F7F,0x6DA0}, 
+  {0x6F80,0x6DA9}, {0x6F86,0x6D47}, {0x6F87,0x6D9D}, {0x6F97,0x6DA7}, {0x6FA0,0x6E11}, 
+  {0x6FA4,0x6CFD}, {0x6FA9,0x6CF6}, {0x6FAE,0x6D4D}, {0x6FB1,0x6DC0}, {0x6FC1,0x6D4A}, 
+  {0x6FC3,0x6D53}, {0x6FD5,0x6E7F}, {0x6FD8,0x6CDE}, {0x6FDF,0x6D4E}, {0x6FE4,0x6D9B}, 
+  {0x6FEB,0x6EE5}, {0x6FF0,0x6F4D}, {0x6FF1,0x6EE8}, {0x6FFA,0x6E85}, {0x6FFC,0x6CFA}, 
+  {0x6FFE,0x6EE4}, {0x7005,0x6EE2}, {0x7006,0x6E0E}, {0x7009,0x6CFB}, {0x700B,0x6E16}, 
+  {0x700F,0x6D4F}, {0x7015,0x6FD2}, {0x7018,0x6CF8}, {0x701D,0x6CA5}, {0x701F,0x6F47}, 
+  {0x7020,0x6F46}, {0x7027,0x6CF7}, {0x7028,0x6FD1}, {0x7032,0x6F4B}, {0x703E,0x6F9C}, 
+  {0x7043,0x6CA3}, {0x7044,0x6EE0}, {0x7051,0x6D12}, {0x7055,0x6F13}, {0x7058,0x6EE9}, 
+  {0x705D,0x704F}, {0x7063,0x6E7E}, {0x7064,0x6EE6}, {0x7067,0x6EDF}, {0x70CF,0x4E4C}, 
+  {0x70F4,0x70C3}, {0x7121,0x65E0}, {0x7149,0x70BC}, {0x7152,0x709C}, {0x7162,0x8315}, 
+  {0x7165,0x7115}, {0x7169,0x70E6}, {0x716C,0x7080}, {0x7192,0x8367}, {0x7197,0x709D}, 
+  {0x71B1,0x70ED}, {0x71BE,0x70BD}, {0x71C1,0x70E8}, {0x71C8,0x706F}, {0x71D2,0x70E7}, 
+  {0x71D9,0x70EB}, {0x71DC,0x7116}, {0x71DF,0x8425}, {0x71E6,0x707F}, {0x71ED,0x70DB}, 
+  {0x71F4,0x70E9}, {0x71FC,0x70EC}, {0x71FE,0x7118}, {0x720D,0x70C1}, {0x7210,0x7089}, 
+  {0x721B,0x70C2}, {0x722D,0x4E89}, {0x7232,0x4E3A}, {0x723A,0x7237}, {0x723E,0x5C14}, 
+  {0x7258,0x724D}, {0x727D,0x7275}, {0x7296,0x8366}, {0x72A2,0x728A}, {0x72A7,0x727A}, 
+  {0x72C0,0x72B6}, {0x72F9,0x72ED}, {0x72FD,0x72C8}, {0x7319,0x72F0}, {0x7336,0x72B9}, 
+  {0x733B,0x72F2}, {0x7341,0x72B8}, {0x7344,0x72F1}, {0x7345,0x72EE}, {0x7368,0x72EC}, 
+  {0x736A,0x72EF}, {0x736B,0x7303}, {0x7370,0x72DE}, {0x7372,0x83B7}, {0x7375,0x730E}, 
+  {0x7377,0x72B7}, {0x7378,0x517D}, {0x737A,0x736D}, {0x737B,0x732E}, {0x737C,0x7315}, 
+  {0x7380,0x7321}, {0x73FE,0x73B0}, {0x743F,0x73F2}, {0x744B,0x73AE}, {0x7463,0x7410}, 
+  {0x7469,0x83B9}, {0x746A,0x739B}, {0x7489,0x740F}, {0x74A3,0x7391}, {0x74A6,0x7477}, 
+  {0x74B0,0x73AF}, {0x74BD,0x73BA}, {0x74CA,0x743C}, {0x74CF,0x73D1}, {0x74D4,0x748E}, 
+  {0x74DA,0x74D2}, {0x750C,0x74EF}, {0x7523,0x4EA7}, {0x755D,0x4EA9}, {0x7562,0x6BD5}, 
+  {0x756B,0x753B}, {0x7576,0x5F53}, {0x7587,0x7574}, {0x758A,0x53E0}, {0x75D9,0x75C9}, 
+  {0x7602,0x75D6}, {0x760B,0x75AF}, {0x760D,0x75A1}, {0x7613,0x75EA}, {0x761E,0x7617}, 
+  {0x7621,0x75AE}, {0x7627,0x759F}, {0x763B,0x7618}, {0x7642,0x7597}, {0x7646,0x75E8}, 
+  {0x7647,0x75EB}, {0x7649,0x7605}, {0x7658,0x75A0}, {0x765F,0x762A}, {0x7662,0x75D2}, 
+  {0x7664,0x7596}, {0x7665,0x75C7}, {0x7667,0x75AC}, {0x7669,0x765E}, {0x766C,0x7663}, 
+  {0x766D,0x763F}, {0x766E,0x763E}, {0x7670,0x75C8}, {0x7671,0x762B}, {0x7672,0x766B}, 
+  {0x767C,0x53D1}, {0x769A,0x7691}, {0x76B8,0x76B2}, {0x76BA,0x76B1}, {0x76DE,0x76CF}, 
+  {0x76E1,0x5C3D}, {0x76E3,0x76D1}, {0x76E4,0x76D8}, {0x76E7,0x5362}, {0x775C,0x7741}, 
+  {0x775E,0x7750}, {0x7798,0x770D}, {0x779E,0x7792}, {0x77BC,0x7751}, {0x77DA,0x77A9}, 
+  {0x77EF,0x77EB}, {0x7864,0x7856}, {0x7868,0x7817}, {0x786F,0x781A}, {0x78A9,0x7855}, 
+  {0x78AD,0x7800}, {0x78B8,0x781C}, {0x78BA,0x786E}, {0x78BC,0x7801}, {0x78DA,0x7816}, 
+  {0x78E3,0x789C}, {0x78E7,0x789B}, {0x78EF,0x77F6}, {0x78FD,0x7857}, {0x790E,0x7840}, 
+  {0x7919,0x788D}, {0x7926,0x77FF}, {0x792A,0x783A}, {0x792B,0x783E}, {0x792C,0x77FE}, 
+  {0x7931,0x783B}, {0x798D,0x7978}, {0x798E,0x796F}, {0x79AA,0x7985}, {0x79AE,0x793C}, 
+  {0x79B0,0x7962}, {0x79B1,0x7977}, {0x7A2E,0x79CD}, {0x7A31,0x79F0}, {0x7A4C,0x7A23}, 
+  {0x7A4D,0x79EF}, {0x7A4E,0x9896}, {0x7A61,0x7A51}, {0x7A62,0x79FD}, {0x7A69,0x7A33}, 
+  {0x7AA9,0x7A9D}, {0x7AAA,0x6D3C}, {0x7AAE,0x7A77}, {0x7AB6,0x7AAD}, {0x7ABA,0x7AA5}, 
+  {0x7AC4,0x7A9C}, {0x7AC5,0x7A8D}, {0x7AC7,0x7AA6}, {0x7AC8,0x7076}, {0x7ACA,0x7A83}, 
+  {0x7AEA,0x7AD6}, {0x7AF6,0x7ADE}, {0x7B46,0x7B14}, {0x7B67,0x7B15}, {0x7B8B,0x7B3A}, 
+  {0x7B8F,0x7B5D}, {0x7BC0,0x8282}, {0x7BC4,0x8303}, {0x7BC9,0x7B51}, {0x7BCB,0x7BA7}, 
+  {0x7BE4,0x7B03}, {0x7BE9,0x7B5B}, {0x7BF3,0x7B5A}, {0x7C00,0x7BA6}, {0x7C0D,0x7BD3}, 
+  {0x7C1E,0x7BAA}, {0x7C21,0x7B80}, {0x7C23,0x7BD1}, {0x7C2B,0x7BAB}, {0x7C3D,0x7B7E}, 
+  {0x7C3E,0x5E18}, {0x7C43,0x7BEE}, {0x7C4C,0x7B79}, {0x7C5C,0x7BA8}, {0x7C5F,0x7C41}, 
+  {0x7C60,0x7B3C}, {0x7C69,0x7B3E}, {0x7C6A,0x7C16}, {0x7C6C,0x7BF1}, {0x7C6E,0x7BA9}, 
+  {0x7CDD,0x7CC1}, {0x7CDE,0x7CAA}, {0x7CE7,0x7CAE}, {0x7CF2,0x7C9D}, {0x7CF4,0x7C74}, 
+  {0x7CF6,0x7C9C}, {0x7CF9,0x7E9F}, {0x7CFE,0x7EA0}, {0x7D00,0x7EAA}, {0x7D02,0x7EA3}, 
+  {0x7D04,0x7EA6}, {0x7D05,0x7EA2}, {0x7D06,0x7EA1}, {0x7D07,0x7EA5}, {0x7D08,0x7EA8}, 
+  {0x7D09,0x7EAB}, {0x7D0B,0x7EB9}, {0x7D0D,0x7EB3}, {0x7D10,0x7EBD}, {0x7D13,0x7EBE}, 
+  {0x7D14,0x7EAF}, {0x7D15,0x7EB0}, {0x7D17,0x7EB1}, {0x7D19,0x7EB8}, {0x7D1A,0x7EA7}, 
+  {0x7D1B,0x7EB7}, {0x7D1C,0x7EAD}, {0x7D21,0x7EBA}, {0x7D30,0x7EC6}, {0x7D31,0x7EC2}, 
+  {0x7D32,0x7EC1}, {0x7D33,0x7EC5}, {0x7D39,0x7ECD}, {0x7D3A,0x7EC0}, {0x7D3C,0x7ECB}, 
+  {0x7D3F,0x7ED0}, {0x7D40,0x7ECC}, {0x7D42,0x7EC8}, {0x7D44,0x7EC4}, {0x7D46,0x7ECA}, 
+  {0x7D4E,0x7ED7}, {0x7D50,0x7ED3}, {0x7D5D,0x7ED4}, {0x7D5E,0x7EDE}, {0x7D61,0x7EDC}, 
+  {0x7D62,0x7EDA}, {0x7D66,0x7ED9}, {0x7D68,0x7ED2}, {0x7D71,0x7EDF}, {0x7D72,0x4E1D}, 
+  {0x7D73,0x7EDB}, {0x7D76,0x7EDD}, {0x7D79,0x7EE2}, {0x7D81,0x7ED1}, {0x7D83,0x7EE1}, 
+  {0x7D86,0x7EE0}, {0x7D88,0x7EE8}, {0x7D89,0x7EE3}, {0x7D8F,0x7EE5}, {0x7D93,0x7ECF}, 
+  {0x7D9C,0x7EFC}, {0x7D9E,0x7F0D}, {0x7DA2,0x7EF8}, {0x7DA3,0x7EFB}, {0x7DAB,0x7EBF}, 
+  {0x7DAC,0x7EF6}, {0x7DAD,0x7EF4}, {0x7DB0,0x7EFE}, {0x7DB1,0x7EB2}, {0x7DB2,0x7F51}, 
+  {0x7DB3,0x7EF7}, {0x7DB4,0x7F00}, {0x7DB8,0x7EB6}, {0x7DB9,0x7EFA}, {0x7DBA,0x7EEE}, 
+  {0x7DBB,0x7EFD}, {0x7DBD,0x7EF0}, {0x7DBE,0x7EEB}, {0x7DBF,0x7EF5}, {0x7DC4,0x7EF2}, 
+  {0x7DC7,0x7F01}, {0x7DCA,0x7D27}, {0x7DCB,0x7EEF}, {0x7DD1,0x7EFF}, {0x7DD2,0x7EEA}, 
+  {0x7DD4,0x7EF1}, {0x7DD7,0x7F03}, {0x7DD8,0x7F04}, {0x7DD9,0x7F02}, {0x7DDD,0x7F09}, 
+  {0x7DDE,0x7F0E}, {0x7DE0,0x7F14}, {0x7DE1,0x7F17}, {0x7DE3,0x7F18}, {0x7DE6,0x7F0C}, 
+  {0x7DE8,0x7F16}, {0x7DE9,0x7F13}, {0x7DEC,0x7F05}, {0x7DEF,0x7EAC}, {0x7DF1,0x7F11}, 
+  {0x7DF2,0x7F08}, {0x7DF4,0x7EC3}, {0x7DF6,0x7F0F}, {0x7DF9,0x7F07}, {0x7E08,0x8426}, 
+  {0x7E09,0x7F19}, {0x7E0A,0x7F22}, {0x7E0B,0x7F12}, {0x7E10,0x7EC9}, {0x7E11,0x7F23}, 
+  {0x7E1B,0x7F1A}, {0x7E1D,0x7F1C}, {0x7E1E,0x7F1F}, {0x7E1F,0x7F1B}, {0x7E23,0x53BF}, 
+  {0x7E27,0x7EE6}, {0x7E2B,0x7F1D}, {0x7E2D,0x7F21}, {0x7E2E,0x7F29}, {0x7E31,0x7EB5}, 
+  {0x7E32,0x7F27}, {0x7E35,0x7F26}, {0x7E36,0x7D77}, {0x7E37,0x7F15}, {0x7E39,0x7F25}, 
+  {0x7E3D,0x603B}, {0x7E3E,0x7EE9}, {0x7E45,0x7F2B}, {0x7E46,0x7F2A}, {0x7E52,0x7F2F}, 
+  {0x7E54,0x7EC7}, {0x7E55,0x7F2E}, {0x7E5A,0x7F2D}, {0x7E5E,0x7ED5}, {0x7E62,0x7F0B}, 
+  {0x7E69,0x7EF3}, {0x7E6A,0x7ED8}, {0x7E6D,0x8327}, {0x7E6E,0x7F30}, {0x7E6F,0x7F33}, 
+  {0x7E70,0x7F32}, {0x7E73,0x7F34}, {0x7E79,0x7ECE}, {0x7E7C,0x7EE7}, {0x7E7D,0x7F24}, 
+  {0x7E7E,0x7F31}, {0x7E88,0x7F2C}, {0x7E8A,0x7EA9}, {0x7E8C,0x7EED}, {0x7E8F,0x7F20}, 
+  {0x7E93,0x7F28}, {0x7E96,0x7EA4}, {0x7E98,0x7F35}, {0x7E9C,0x7F06}, {0x7F4C,0x7F42}, 
+  {0x7F70,0x7F5A}, {0x7F77,0x7F62}, {0x7F85,0x7F57}, {0x7F86,0x7F74}, {0x7F88,0x7F81}, 
+  {0x7FA5,0x7F9F}, {0x7FA9,0x4E49}, {0x7FD2,0x4E60}, {0x7FF9,0x7FD8}, {0x802C,0x8027}, 
+  {0x802E,0x8022}, {0x8056,0x5723}, {0x805E,0x95FB}, {0x806F,0x8054}, {0x8070,0x806A}, 
+  {0x8072,0x58F0}, {0x8073,0x8038}, {0x8075,0x8069}, {0x8076,0x8042}, {0x8077,0x804C}, 
+  {0x8079,0x804D}, {0x807D,0x542C}, {0x807E,0x804B}, {0x8085,0x8083}, {0x8105,0x80C1}, 
+  {0x811B,0x80EB}, {0x8139,0x80C0}, {0x814E,0x80BE}, {0x8156,0x80E8}, {0x8161,0x8136}, 
+  {0x8166,0x8111}, {0x816B,0x80BF}, {0x8178,0x80A0}, {0x819A,0x80A4}, {0x81A0,0x80F6}, 
+  {0x81A9,0x817B}, {0x81BD,0x80C6}, {0x81BE,0x810D}, {0x81BF,0x8113}, {0x81C9,0x8138}, 
+  {0x81CD,0x8110}, {0x81CF,0x8191}, {0x81D8,0x814A}, {0x81DA,0x80EA}, {0x81DF,0x810F}, 
+  {0x81E0,0x8114}, {0x81E8,0x4E34}, {0x81FA,0x53F0}, {0x8207,0x4E0E}, {0x8208,0x5174}, 
+  {0x8209,0x4E3E}, {0x820A,0x65E7}, {0x8259,0x8231}, {0x8264,0x8223}, {0x8266,0x8230}, 
+  {0x826B,0x823B}, {0x8271,0x8270}, {0x8277,0x8273}, {0x82BB,0x520D}, {0x82E7,0x82CE}, 
+  {0x838A,0x5E84}, {0x8396,0x830E}, {0x83A2,0x835A}, {0x83A7,0x82CB}, {0x83EF,0x534E}, 
+  {0x8407,0x82CC}, {0x840A,0x83B1}, {0x842C,0x4E07}, {0x8435,0x83B4}, {0x8449,0x53F6}, 
+  {0x8452,0x836D}, {0x8464,0x836E}, {0x8466,0x82C7}, {0x8477,0x8364}, {0x8493,0x83BC}, 
+  {0x8494,0x83B3}, {0x84BC,0x82CD}, {0x84C0,0x836A}, {0x84CB,0x76D6}, {0x84EE,0x83B2}, 
+  {0x84EF,0x82C1}, {0x84FD,0x835C}, {0x851E,0x848C}, {0x8523,0x848B}, {0x8526,0x8311}, 
+  {0x852D,0x836B}, {0x8541,0x8368}, {0x8546,0x8487}, {0x854E,0x835E}, {0x8552,0x836C}, 
+  {0x8553,0x82B8}, {0x8555,0x83B8}, {0x8558,0x835B}, {0x8562,0x8489}, {0x8569,0x8361}, 
+  {0x856A,0x829C}, {0x856D,0x8427}, {0x8577,0x84E3}, {0x8588,0x835F}, {0x858A,0x84DF}, 
+  {0x858C,0x8297}, {0x8594,0x8537}, {0x859F,0x83B6}, {0x85A6,0x8350}, {0x85A9,0x8428}, 
+  {0x85BA,0x8360}, {0x85CD,0x84DD}, {0x85CE,0x8369}, {0x85DD,0x827A}, {0x85E5,0x836F}, 
+  {0x85EA,0x85AE}, {0x85F4,0x8574}, {0x85F6,0x82C8}, {0x85F9,0x853C}, {0x85FA,0x853A}, 
+  {0x8604,0x8572}, {0x8606,0x82A6}, {0x8607,0x82CF}, {0x860B,0x82F9}, {0x861A,0x85D3}, 
+  {0x861E,0x8539}, {0x8622,0x830F}, {0x862D,0x5170}, {0x863A,0x84E0}, {0x863F,0x841D}, 
+  {0x8655,0x5904}, {0x865C,0x864F}, {0x865F,0x53F7}, {0x8667,0x4E8F}, {0x86FA,0x86F1}, 
+  {0x8706,0x86AC}, {0x8755,0x8680}, {0x8766,0x867E}, {0x8778,0x8717}, {0x8784,0x86F3}, 
+  {0x879E,0x8682}, {0x87A2,0x8424}, {0x87BB,0x877C}, {0x87C4,0x86F0}, {0x87C8,0x8748}, 
+  {0x87CE,0x87A8}, {0x87E3,0x866E}, {0x87EC,0x8749}, {0x87EF,0x86F2}, {0x87F2,0x866B}, 
+  {0x87F6,0x86CF}, {0x87FB,0x8681}, {0x8805,0x8747}, {0x8806,0x867F}, {0x8810,0x86F4}, 
+  {0x8811,0x877E}, {0x881F,0x8721}, {0x8823,0x86CE}, {0x8831,0x86CA}, {0x8836,0x8695}, 
+  {0x883B,0x86EE}, {0x8846,0x4F17}, {0x8853,0x672F}, {0x885B,0x536B}, {0x885D,0x51B2}, 
+  {0x8879,0x53EA}, {0x88CA,0x8885}, {0x88CF,0x91CC}, {0x88DC,0x8865}, {0x88DD,0x88C5}, 
+  {0x8932,0x88E4}, {0x8933,0x88E2}, {0x8938,0x891B}, {0x893B,0x4EB5}, {0x8947,0x88E5}, 
+  {0x8956,0x8884}, {0x895D,0x88E3}, {0x8960,0x88C6}, {0x8964,0x8934}, {0x896A,0x889C}, 
+  {0x896F,0x886C}, {0x8972,0x88AD}, {0x898B,0x89C1}, {0x898F,0x89C4}, {0x8993,0x89C5}, 
+  {0x8996,0x89C6}, {0x8998,0x89C7}, {0x89A1,0x89CB}, {0x89A6,0x89CE}, {0x89AA,0x4EB2}, 
+  {0x89AC,0x89CA}, {0x89AF,0x89CF}, {0x89B2,0x89D0}, {0x89B7,0x89D1}, {0x89BA,0x89C9}, 
+  {0x89BD,0x89C8}, {0x89BF,0x89CC}, {0x89C0,0x89C2}, {0x89F4,0x89DE}, {0x89F6,0x89EF}, 
+  {0x89F8,0x89E6}, {0x8A01,0x8BA0}, {0x8A02,0x8BA2}, {0x8A03,0x8BA3}, {0x8A08,0x8BA1}, 
+  {0x8A0A,0x8BAF}, {0x8A0C,0x8BA7}, {0x8A0E,0x8BA8}, {0x8A10,0x8BA6}, {0x8A13,0x8BAD}, 
+  {0x8A15,0x8BAA}, {0x8A16,0x8BAB}, {0x8A18,0x8BB0}, {0x8A1B,0x8BB9}, {0x8A1D,0x8BB6}, 
+  {0x8A1F,0x8BBC}, {0x8A23,0x8BC0}, {0x8A25,0x8BB7}, {0x8A2A,0x8BBF}, {0x8A2D,0x8BBE}, 
+  {0x8A31,0x8BB8}, {0x8A34,0x8BC9}, {0x8A36,0x8BC3}, {0x8A3A,0x8BCA}, {0x8A41,0x8BC2}, 
+  {0x8A46,0x8BCB}, {0x8A4E,0x8BB5}, {0x8A50,0x8BC8}, {0x8A52,0x8BD2}, {0x8A54,0x8BCF}, 
+  {0x8A55,0x8BC4}, {0x8A58,0x8BCE}, {0x8A5B,0x8BC5}, {0x8A5E,0x8BCD}, {0x8A61,0x8BE9}, 
+  {0x8A62,0x8BE2}, {0x8A63,0x8BE3}, {0x8A66,0x8BD5}, {0x8A69,0x8BD7}, {0x8A6B,0x8BE7}, 
+  {0x8A6C,0x8BDF}, {0x8A6D,0x8BE1}, {0x8A6E,0x8BE0}, {0x8A70,0x8BD8}, {0x8A71,0x8BDD}, 
+  {0x8A72,0x8BE5}, {0x8A73,0x8BE6}, {0x8A75,0x8BDC}, {0x8A7C,0x8BD9}, {0x8A7F,0x8BD6}, 
+  {0x8A84,0x8BD4}, {0x8A85,0x8BDB}, {0x8A86,0x8BD3}, {0x8A87,0x5938}, {0x8A8D,0x8BA4}, 
+  {0x8A91,0x8BF3}, {0x8A92,0x8BF6}, {0x8A95,0x8BDE}, {0x8A98,0x8BF1}, {0x8A9A,0x8BEE}, 
+  {0x8A9E,0x8BED}, {0x8AA0,0x8BDA}, {0x8AA1,0x8BEB}, {0x8AA3,0x8BEC}, {0x8AA4,0x8BEF}, 
+  {0x8AA5,0x8BF0}, {0x8AA6,0x8BF5}, {0x8AA8,0x8BF2}, {0x8AAC,0x8BF4}, {0x8AB0,0x8C01}, 
+  {0x8AB2,0x8BFE}, {0x8AB6,0x8C07}, {0x8AB9,0x8BFD}, {0x8ABC,0x8C0A}, {0x8ABF,0x8C03}, 
+  {0x8AC2,0x8C04}, {0x8AC4,0x8C06}, {0x8AC7,0x8C08}, {0x8AC9,0x8BFF}, {0x8ACB,0x8BF7}, 
+  {0x8ACD,0x8BE4}, {0x8ACF,0x8BF9}, {0x8AD1,0x8BFC}, {0x8AD2,0x8C05}, {0x8AD6,0x8BBA}, 
+  {0x8AD7,0x8C02}, {0x8ADB,0x8C00}, {0x8ADC,0x8C0D}, {0x8ADE,0x8C1D}, {0x8AE2,0x8BE8}, 
+  {0x8AE4,0x8C14}, {0x8AE6,0x8C1B}, {0x8AE7,0x8C10}, {0x8AEB,0x8C0F}, {0x8AED,0x8C15}, 
+  {0x8AEE,0x8C18}, {0x8AF1,0x8BB3}, {0x8AF3,0x8C19}, {0x8AF6,0x8C0C}, {0x8AF7,0x8BBD}, 
+  {0x8AF8,0x8BF8}, {0x8AFA,0x8C1A}, {0x8AFC,0x8C16}, {0x8AFE,0x8BFA}, {0x8B00,0x8C0B}, 
+  {0x8B01,0x8C12}, {0x8B02,0x8C13}, {0x8B04,0x8A8A}, {0x8B05,0x8BCC}, {0x8B0A,0x8C0E}, 
+  {0x8B0E,0x8C1C}, {0x8B10,0x8C27}, {0x8B14,0x8C11}, {0x8B16,0x8C21}, {0x8B17,0x8C24}, 
+  {0x8B19,0x8C26}, {0x8B1A,0x8C25}, {0x8B1B,0x8BB2}, {0x8B1D,0x8C22}, {0x8B21,0x8C23}, 
+  {0x8B28,0x8C1F}, {0x8B2B,0x8C2A}, {0x8B2C,0x8C2C}, {0x8B2D,0x8C2B}, {0x8B33,0x8BB4}, 
+  {0x8B39,0x8C28}, {0x8B3E,0x8C29}, {0x8B49,0x8BC1}, {0x8B4E,0x8C32}, {0x8B4F,0x8BA5}, 
+  {0x8B56,0x8C2E}, {0x8B58,0x8BC6}, {0x8B59,0x8C2F}, {0x8B5A,0x8C2D}, {0x8B5C,0x8C31}, 
+  {0x8B6B,0x8C35}, {0x8B6F,0x8BD1}, {0x8B70,0x8BAE}, {0x8B74,0x8C34}, {0x8B77,0x62A4}, 
+  {0x8B7D,0x8A89}, {0x8B80,0x8BFB}, {0x8B8A,0x53D8}, {0x8B8E,0x96E0}, {0x8B92,0x8C17}, 
+  {0x8B93,0x8BA9}, {0x8B95,0x8C30}, {0x8B96,0x8C36}, {0x8B9C,0x8C20}, {0x8B9E,0x8C33}, 
+  {0x8C48,0x5C82}, {0x8C50,0x4E30}, {0x8C9D,0x8D1D}, {0x8C9E,0x8D1E}, {0x8CA0,0x8D1F}, 
+  {0x8CA1,0x8D22}, {0x8CA2,0x8D21}, {0x8CA7,0x8D2B}, {0x8CA8,0x8D27}, {0x8CA9,0x8D29}, 
+  {0x8CAA,0x8D2A}, {0x8CAB,0x8D2F}, {0x8CAC,0x8D23}, {0x8CAF,0x8D2E}, {0x8CB0,0x8D33}, 
+  {0x8CB2,0x8D40}, {0x8CB3,0x8D30}, {0x8CB4,0x8D35}, {0x8CB6,0x8D2C}, {0x8CB7,0x4E70}, 
+  {0x8CB8,0x8D37}, {0x8CBA,0x8D36}, {0x8CBB,0x8D39}, {0x8CBC,0x8D34}, {0x8CBD,0x8D3B}, 
+  {0x8CBF,0x8D38}, {0x8CC0,0x8D3A}, {0x8CC1,0x8D32}, {0x8CC2,0x8D42}, {0x8CC3,0x8D41}, 
+  {0x8CC4,0x8D3F}, {0x8CC5,0x8D45}, {0x8CC7,0x8D44}, {0x8CC8,0x8D3E}, {0x8CCA,0x8D3C}, 
+  {0x8CD1,0x8D48}, {0x8CD2,0x8D4A}, {0x8CD3,0x5BBE}, {0x8CD5,0x8D47}, {0x8CDA,0x8D49}, 
+  {0x8CDC,0x8D50}, {0x8CDE,0x8D4F}, {0x8CE0,0x8D54}, {0x8CE1,0x8D53}, {0x8CE2,0x8D24}, 
+  {0x8CE3,0x5356}, {0x8CE4,0x8D31}, {0x8CE6,0x8D4B}, {0x8CE7,0x8D55}, {0x8CEA,0x8D28}, 
+  {0x8CEB,0x8D4D}, {0x8CEC,0x8D26}, {0x8CED,0x8D4C}, {0x8CF4,0x8D56}, {0x8CFA,0x8D5A}, 
+  {0x8CFB,0x8D59}, {0x8CFC,0x8D2D}, {0x8CFD,0x8D5B}, {0x8CFE,0x8D5C}, {0x8D04,0x8D3D}, 
+  {0x8D05,0x8D58}, {0x8D08,0x8D60}, {0x8D0A,0x8D5E}, {0x8D0B,0x8D5D}, {0x8D0D,0x8D61}, 
+  {0x8D0F,0x8D62}, {0x8D10,0x8D46}, {0x8D16,0x8D4E}, {0x8D1B,0x8D63}, {0x8D1C,0x8D43}, 
+  {0x8D95,0x8D76}, {0x8D99,0x8D75}, {0x8DA8,0x8D8B}, {0x8DB2,0x8DB1}, {0x8E10,0x8DF5}, 
+  {0x8E34,0x8E0A}, {0x8E4C,0x8DC4}, {0x8E55,0x8DF8}, {0x8E63,0x8E52}, {0x8E7A,0x8DF7}, 
+  {0x8E89,0x8DB8}, {0x8E8A,0x8E0C}, {0x8E8B,0x8DFB}, {0x8E8D,0x8DC3}, {0x8E91,0x8E2F}, 
+  {0x8E92,0x8DDE}, {0x8E93,0x8E2C}, {0x8E9A,0x8DF9}, {0x8EA1,0x8E51}, {0x8EA5,0x8E7F}, 
+  {0x8EA6,0x8E9C}, {0x8EAA,0x8E8F}, {0x8EC0,0x8EAF}, {0x8ECA,0x8F66}, {0x8ECB,0x8F67}, 
+  {0x8ECC,0x8F68}, {0x8ECD,0x519B}, {0x8ED2,0x8F69}, {0x8ED4,0x8F6B}, {0x8EDB,0x8F6D}, 
+  {0x8EDF,0x8F6F}, {0x8EE4,0x8F77}, {0x8EEB,0x8F78}, {0x8EF2,0x8F71}, {0x8EF8,0x8F74}, 
+  {0x8EF9,0x8F75}, {0x8EFA,0x8F7A}, {0x8EFB,0x8F72}, {0x8EFC,0x8F76}, {0x8EFE,0x8F7C}, 
+  {0x8F03,0x8F83}, {0x8F05,0x8F82}, {0x8F07,0x8F81}, {0x8F09,0x8F7D}, {0x8F0A,0x8F7E}, 
+  {0x8F12,0x8F84}, {0x8F14,0x8F85}, {0x8F15,0x8F7B}, {0x8F1B,0x8F86}, {0x8F1C,0x8F8E}, 
+  {0x8F1D,0x8F89}, {0x8F1E,0x8F8B}, {0x8F1F,0x8F8D}, {0x8F25,0x8F8A}, {0x8F26,0x8F87}, 
+  {0x8F29,0x8F88}, {0x8F2A,0x8F6E}, {0x8F2F,0x8F91}, {0x8F33,0x8F8F}, {0x8F38,0x8F93}, 
+  {0x8F3B,0x8F90}, {0x8F3E,0x8F97}, {0x8F3F,0x8206}, {0x8F42,0x6BC2}, {0x8F44,0x8F96}, 
+  {0x8F45,0x8F95}, {0x8F46,0x8F98}, {0x8F49,0x8F6C}, {0x8F4D,0x8F99}, {0x8F4E,0x8F7F}, 
+  {0x8F54,0x8F9A}, {0x8F5F,0x8F70}, {0x8F61,0x8F94}, {0x8F62,0x8F79}, {0x8F64,0x8F73}, 
+  {0x8FA6,0x529E}, {0x8FAD,0x8F9E}, {0x8FAE,0x8FAB}, {0x8FAF,0x8FA9}, {0x8FB2,0x519C}, 
+  {0x9015,0x8FF3}, {0x9019,0x8FD9}, {0x9023,0x8FDE}, {0x9032,0x8FDB}, {0x904B,0x8FD0}, 
+  {0x904E,0x8FC7}, {0x9054,0x8FBE}, {0x9055,0x8FDD}, {0x905C,0x900A}, {0x905E,0x9012}, 
+  {0x9060,0x8FDC}, {0x9069,0x9002}, {0x9072,0x8FDF}, {0x9077,0x8FC1}, {0x9078,0x9009}, 
+  {0x907A,0x9057}, {0x907C,0x8FBD}, {0x9081,0x8FC8}, {0x9084,0x8FD8}, {0x9087,0x8FE9}, 
+  {0x908A,0x8FB9}, {0x908F,0x903B}, {0x9090,0x9026}, {0x90DF,0x90CF}, {0x90F5,0x90AE}, 
+  {0x9106,0x90D3}, {0x9109,0x4E61}, {0x9112,0x90B9}, {0x9114,0x90AC}, {0x9116,0x90E7}, 
+  {0x9127,0x9093}, {0x912D,0x90D1}, {0x9130,0x90BB}, {0x9132,0x90F8}, {0x9134,0x90BA}, 
+  {0x9136,0x90D0}, {0x913A,0x909D}, {0x9148,0x90E6}, {0x9196,0x915D}, {0x919C,0x4E11}, 
+  {0x91AB,0x533B}, {0x91AC,0x9171}, {0x91C0,0x917F}, {0x91C1,0x8845}, {0x91C3,0x917E}, 
+  {0x91C5,0x917D}, {0x91CB,0x91CA}, {0x91D2,0x9485}, {0x91D3,0x9486}, {0x91D4,0x9487}, 
+  {0x91D5,0x948C}, {0x91D7,0x948A}, {0x91D8,0x9489}, {0x91D9,0x948B}, {0x91DD,0x9488}, 
+  {0x91E3,0x9493}, {0x91E4,0x9490}, {0x91E7,0x948F}, {0x91E9,0x9492}, {0x91F5,0x9497}, 
+  {0x91F7,0x948D}, {0x91F9,0x9495}, {0x91FA,0x948E}, {0x9200,0x94AF}, {0x9201,0x94AB}, 
+  {0x9204,0x94AD}, {0x9208,0x949A}, {0x9209,0x94A0}, {0x920D,0x949D}, {0x920E,0x94A9}, 
+  {0x9210,0x94A4}, {0x9211,0x94A3}, {0x9214,0x949E}, {0x9215,0x94AE}, {0x921E,0x94A7}, 
+  {0x9223,0x9499}, {0x9225,0x94AC}, {0x9226,0x949B}, {0x9227,0x94AA}, {0x922E,0x94CC}, 
+  {0x9230,0x94C8}, {0x9233,0x94B6}, {0x9234,0x94C3}, {0x9237,0x94B4}, {0x9238,0x94B9}, 
+  {0x9239,0x94CD}, {0x923A,0x94B0}, {0x923D,0x94B8}, {0x923E,0x94C0}, {0x923F,0x94BF}, 
+  {0x9240,0x94BE}, {0x9245,0x949C}, {0x9248,0x94CA}, {0x9249,0x94C9}, {0x924D,0x94CB}, 
+  {0x9251,0x94C2}, {0x9255,0x94B7}, {0x9257,0x94B3}, {0x925A,0x94C6}, {0x925B,0x94C5}, 
+  {0x925E,0x94BA}, {0x9262,0x94B5}, {0x9266,0x94B2}, {0x926C,0x94BC}, {0x926D,0x94BD}, 
+  {0x9278,0x94F0}, {0x927A,0x94D2}, {0x927B,0x94EC}, {0x927F,0x94EA}, {0x9280,0x94F6}, 
+  {0x9283,0x94F3}, {0x9285,0x94DC}, {0x9291,0x94E3}, {0x9293,0x94E8}, {0x9296,0x94E2}, 
+  {0x9298,0x94ED}, {0x929A,0x94EB}, {0x929C,0x8854}, {0x92A0,0x94D1}, {0x92A3,0x94F7}, 
+  {0x92A5,0x94F1}, {0x92A6,0x94DF}, {0x92A8,0x94F5}, {0x92A9,0x94E5}, {0x92AA,0x94D5}, 
+  {0x92AB,0x94EF}, {0x92AC,0x94D0}, {0x92B1,0x94DE}, {0x92B7,0x9500}, {0x92B9,0x9508}, 
+  {0x92BB,0x9511}, {0x92BC,0x9509}, {0x92C1,0x94DD}, {0x92C3,0x9512}, {0x92C5,0x950C}, 
+  {0x92C7,0x94A1}, {0x92CC,0x94E4}, {0x92CF,0x94D7}, {0x92D2,0x950B}, {0x92DD,0x950A}, 
+  {0x92DF,0x9513}, {0x92E3,0x94D8}, {0x92E4,0x9504}, {0x92E5,0x9503}, {0x92E6,0x9514}, 
+  {0x92E8,0x9507}, {0x92EA,0x94FA}, {0x92ED,0x9510}, {0x92EE,0x94D6}, {0x92EF,0x9506}, 
+  {0x92F0,0x9502}, {0x92F1,0x94FD}, {0x92F6,0x950D}, {0x92F8,0x952F}, {0x92FC,0x94A2}, 
+  {0x9301,0x951E}, {0x9306,0x9516}, {0x9307,0x952B}, {0x9308,0x9529}, {0x9310,0x9525}, 
+  {0x9312,0x9515}, {0x9315,0x951F}, {0x9318,0x9524}, {0x9319,0x9531}, {0x931A,0x94EE}, 
+  {0x931B,0x951B}, {0x931F,0x952C}, {0x9320,0x952D}, {0x9322,0x94B1}, {0x9326,0x9526}, 
+  {0x9328,0x951A}, {0x932B,0x9521}, {0x932E,0x9522}, {0x932F,0x9519}, {0x9332,0x5F55}, 
+  {0x9333,0x9530}, {0x9338,0x94FC}, {0x9340,0x951D}, {0x9341,0x9528}, {0x9343,0x952A}, 
+  {0x9346,0x9494}, {0x9347,0x9534}, {0x934B,0x9505}, {0x934D,0x9540}, {0x9354,0x9537}, 
+  {0x9358,0x94E1}, {0x935B,0x953B}, {0x9364,0x9538}, {0x9365,0x9532}, {0x9369,0x9518}, 
+  {0x936C,0x9539}, {0x9370,0x953E}, {0x9375,0x952E}, {0x9376,0x9536}, {0x937A,0x9517}, 
+  {0x937E,0x953A}, {0x9382,0x9541}, {0x9384,0x953F}, {0x9387,0x9545}, {0x938A,0x9551}, 
+  {0x9396,0x9501}, {0x9398,0x9549}, {0x93A2,0x94A8}, {0x93A3,0x84E5}, {0x93A6,0x954F}, 
+  {0x93A7,0x94E0}, {0x93A9,0x94E9}, {0x93AA,0x953C}, {0x93AC,0x9550}, {0x93AE,0x9547}, 
+  {0x93B0,0x9552}, {0x93B3,0x954D}, {0x93B5,0x9553}, {0x93B8,0x954C}, {0x93BF,0x954E}, 
+  {0x93C3,0x955E}, {0x93C7,0x955F}, {0x93C8,0x94FE}, {0x93CC,0x9546}, {0x93CD,0x9559}, 
+  {0x93D1,0x955D}, {0x93D7,0x94FF}, {0x93D8,0x9535}, {0x93DC,0x9557}, {0x93DD,0x9558}, 
+  {0x93DE,0x955B}, {0x93DF,0x94F2}, {0x93E1,0x955C}, {0x93E2,0x9556}, {0x93E4,0x9542}, 
+  {0x93E8,0x933E}, {0x93F5,0x94E7}, {0x93F7,0x9564}, {0x93F9,0x956A}, {0x9403,0x94D9}, 
+  {0x940B,0x94F4}, {0x9410,0x9563}, {0x9412,0x94F9}, {0x9413,0x9566}, {0x9414,0x9561}, 
+  {0x9418,0x949F}, {0x9419,0x956B}, {0x941D,0x9562}, {0x9420,0x9568}, {0x9426,0x950E}, 
+  {0x9427,0x950F}, {0x9428,0x9544}, {0x942E,0x9570}, {0x9432,0x956F}, {0x9433,0x956D}, 
+  {0x9435,0x94C1}, {0x9438,0x94CE}, {0x943A,0x94DB}, {0x943F,0x9571}, {0x9444,0x94F8}, 
+  {0x944A,0x956C}, {0x944C,0x9554}, {0x9452,0x9274}, {0x9454,0x9572}, {0x9460,0x94C4}, 
+  {0x9463,0x9573}, {0x9465,0x9565}, {0x946D,0x9567}, {0x9470,0x94A5}, {0x9472,0x9576}, 
+  {0x9477,0x954A}, {0x9479,0x9569}, {0x947C,0x9523}, {0x947D,0x94BB}, {0x947E,0x92AE}, 
+  {0x947F,0x51FF}, {0x9577,0x957F}, {0x9580,0x95E8}, {0x9582,0x95E9}, {0x9583,0x95EA}, 
+  {0x9586,0x95EB}, {0x9589,0x95ED}, {0x958B,0x5F00}, {0x958C,0x95F6}, {0x958E,0x95F3}, 
+  {0x958F,0x95F0}, {0x9591,0x95F2}, {0x9593,0x95F4}, {0x9594,0x95F5}, {0x9598,0x95F8}, 
+  {0x95A1,0x9602}, {0x95A3,0x9601}, {0x95A5,0x9600}, {0x95A8,0x95FA}, {0x95A9,0x95FD}, 
+  {0x95AB,0x9603}, {0x95AC,0x9606}, {0x95AD,0x95FE}, {0x95B2,0x9605}, {0x95B6,0x960A}, 
+  {0x95B9,0x9609}, {0x95BB,0x960E}, {0x95BC,0x960F}, {0x95BD,0x960D}, {0x95BE,0x9608}, 
+  {0x95BF,0x960C}, {0x95C3,0x9612}, {0x95C8,0x95F1}, {0x95CA,0x9614}, {0x95CB,0x9615}, 
+  {0x95CC,0x9611}, {0x95D0,0x9617}, {0x95D4,0x9616}, {0x95D5,0x9619}, {0x95D6,0x95EF}, 
+  {0x95DC,0x5173}, {0x95DE,0x961A}, {0x95E1,0x9610}, {0x95E5,0x95FC}, {0x9658,0x9649}, 
+  {0x965D,0x9655}, {0x9663,0x9635}, {0x9670,0x9634}, {0x9673,0x9648}, {0x9678,0x9646}, 
+  {0x967D,0x9633}, {0x9689,0x9667}, {0x968A,0x961F}, {0x968E,0x9636}, {0x9695,0x9668}, 
+  {0x969B,0x9645}, {0x96A8,0x968F}, {0x96AA,0x9669}, {0x96B1,0x9690}, {0x96B4,0x9647}, 
+  {0x96B8,0x96B6}, {0x96D6,0x867D}, {0x96D9,0x53CC}, {0x96DB,0x96CF}, {0x96DC,0x6742}, 
+  {0x96E2,0x79BB}, {0x96E3,0x96BE}, {0x96F2,0x4E91}, {0x96FB,0x7535}, {0x9727,0x96FE}, 
+  {0x973D,0x9701}, {0x9742,0x96F3}, {0x9744,0x972D}, {0x9748,0x7075}, {0x975A,0x9753}, 
+  {0x975C,0x9759}, {0x9768,0x9765}, {0x978F,0x5DE9}, {0x97BD,0x9792}, {0x97C3,0x9791}, 
+  {0x97C9,0x97AF}, {0x97CB,0x97E6}, {0x97CC,0x97E7}, {0x97D3,0x97E9}, {0x97D9,0x97EA}, 
+  {0x97DC,0x97EC}, {0x97DE,0x97EB}, {0x97FF,0x54CD}, {0x9801,0x9875}, {0x9802,0x9876}, 
+  {0x9803,0x9877}, {0x9805,0x9879}, {0x9806,0x987A}, {0x9807,0x9878}, {0x9808,0x987B}, 
+  {0x980A,0x987C}, {0x980C,0x9882}, {0x980E,0x9880}, {0x980F,0x9883}, {0x9810,0x9884}, 
+  {0x9811,0x987D}, {0x9812,0x9881}, {0x9813,0x987F}, {0x9817,0x9887}, {0x9818,0x9886}, 
+  {0x981C,0x988C}, {0x9821,0x9889}, {0x9824,0x9890}, {0x9826,0x988F}, {0x982D,0x5934}, 
+  {0x9830,0x988A}, {0x9837,0x9894}, {0x9838,0x9888}, {0x983B,0x9891}, {0x983D,0x9893}, 
+  {0x9846,0x9897}, {0x984C,0x9898}, {0x984D,0x989D}, {0x984E,0x989A}, {0x9853,0x989B}, 
+  {0x9854,0x989C}, {0x9858,0x613F}, {0x9859,0x98A1}, {0x985B,0x98A0}, {0x985E,0x7C7B}, 
+  {0x9862,0x989F}, {0x9865,0x98A2}, {0x9867,0x987E}, {0x986B,0x98A4}, {0x986C,0x98A5}, 
+  {0x986F,0x663E}, {0x9870,0x98A6}, {0x9871,0x9885}, {0x9873,0x989E}, {0x9874,0x98A7}, 
+  {0x98A8,0x98CE}, {0x98AE,0x98D1}, {0x98AF,0x98D2}, {0x98B6,0x98D3}, {0x98BC,0x98D5}, 
+  {0x98C4,0x98D8}, {0x98C6,0x98D9}, {0x98C8,0x98DA}, {0x98DB,0x98DE}, {0x98E0,0x9963}, 
+  {0x98E9,0x9968}, {0x98EA,0x996A}, {0x98EB,0x996B}, {0x98ED,0x996C}, {0x98EF,0x996D}, 
+  {0x98F2,0x996E}, {0x98F4,0x9974}, {0x98FC,0x9972}, {0x98FD,0x9971}, {0x98FE,0x9970}, 
+  {0x9903,0x997A}, {0x9905,0x997C}, {0x9909,0x9977}, {0x990A,0x517B}, {0x990C,0x9975}, 
+  {0x9911,0x997D}, {0x9912,0x9981}, {0x9913,0x997F}, {0x9918,0x4F59}, {0x991B,0x9984}, 
+  {0x991E,0x996F}, {0x9921,0x9985}, {0x9928,0x9986}, {0x9933,0x9967}, {0x9937,0x9987}, 
+  {0x993C,0x9969}, {0x993E,0x998F}, {0x993F,0x998A}, {0x9943,0x998D}, {0x9945,0x9992}, 
+  {0x9948,0x9990}, {0x9949,0x9991}, {0x994A,0x9993}, {0x994B,0x9988}, {0x994C,0x9994}, 
+  {0x9951,0x9965}, {0x9952,0x9976}, {0x9957,0x98E8}, {0x995C,0x990D}, {0x995E,0x998B}, 
+  {0x9962,0x9995}, {0x99AC,0x9A6C}, {0x99AD,0x9A6D}, {0x99AE,0x51AF}, {0x99B1,0x9A6E}, 
+  {0x99B3,0x9A70}, {0x99B4,0x9A6F}, {0x99C1,0x9A73}, {0x99D0,0x9A7B}, {0x99D1,0x9A7D}, 
+  {0x99D2,0x9A79}, {0x99D4,0x9A75}, {0x99D5,0x9A7E}, {0x99D8,0x9A80}, {0x99D9,0x9A78}, 
+  {0x99DB,0x9A76}, {0x99DD,0x9A7C}, {0x99DF,0x9A77}, {0x99E1,0x9A82}, {0x99E2,0x9A88}, 
+  {0x99ED,0x9A87}, {0x99F1,0x9A86}, {0x99FF,0x9A8F}, {0x9A01,0x9A8B}, {0x9A05,0x9A93}, 
+  {0x9A0D,0x9A92}, {0x9A0E,0x9A91}, {0x9A0F,0x9A90}, {0x9A16,0x9A9B}, {0x9A19,0x9A97}, 
+  {0x9A2B,0x9A9E}, {0x9A2D,0x9A98}, {0x9A2E,0x9A9D}, {0x9A30,0x817E}, {0x9A36,0x9A7A}, 
+  {0x9A37,0x9A9A}, {0x9A38,0x9A9F}, {0x9A3E,0x9AA1}, {0x9A40,0x84E6}, {0x9A41,0x9A9C}, 
+  {0x9A42,0x9A96}, {0x9A43,0x9AA0}, {0x9A44,0x9AA2}, {0x9A45,0x9A71}, {0x9A4A,0x9A85}, 
+  {0x9A4D,0x9A81}, {0x9A4F,0x9AA3}, {0x9A55,0x9A84}, {0x9A57,0x9A8C}, {0x9A5A,0x60CA}, 
+  {0x9A5B,0x9A7F}, {0x9A5F,0x9AA4}, {0x9A62,0x9A74}, {0x9A64,0x9AA7}, {0x9A65,0x9AA5}, 
+  {0x9A6A,0x9A8A}, {0x9AAF,0x80AE}, {0x9ACF,0x9AC5}, {0x9AD4,0x4F53}, {0x9AD5,0x9ACC}, 
+  {0x9AD6,0x9ACB}, {0x9B06,0x677E}, {0x9B22,0x9B13}, {0x9B25,0x6597}, {0x9B27,0x95F9}, 
+  {0x9B29,0x960B}, {0x9B2E,0x9604}, {0x9B31,0x90C1}, {0x9B4E,0x9B49}, {0x9B58,0x9B47}, 
+  {0x9B5A,0x9C7C}, {0x9B6F,0x9C81}, {0x9B74,0x9C82}, {0x9B77,0x9C7F}, {0x9B81,0x9C85}, 
+  {0x9B83,0x9C86}, {0x9B8E,0x9C87}, {0x9B90,0x9C90}, {0x9B91,0x9C8D}, {0x9B92,0x9C8B}, 
+  {0x9B9A,0x9C92}, {0x9B9D,0x9C9E}, {0x9B9E,0x9C95}, {0x9BAA,0x9C94}, {0x9BAB,0x9C9B}, 
+  {0x9BAD,0x9C91}, {0x9BAE,0x9C9C}, {0x9BC0,0x9CA7}, {0x9BC1,0x9CA0}, {0x9BC7,0x9CA9}, 
+  {0x9BC9,0x9CA4}, {0x9BCA,0x9CA8}, {0x9BD4,0x9CBB}, {0x9BD6,0x9CAD}, {0x9BDB,0x9CB7}, 
+  {0x9BDD,0x9CB4}, {0x9BE1,0x9CB1}, {0x9BE2,0x9CB5}, {0x9BE4,0x9CB2}, {0x9BE7,0x9CB3}, 
+  {0x9BE8,0x9CB8}, {0x9BEA,0x9CAE}, {0x9BEB,0x9CB0}, {0x9BF0,0x9CB6}, {0x9BF4,0x9CBA}, 
+  {0x9BFD,0x9CAB}, {0x9BFF,0x9CCA}, {0x9C08,0x9CBD}, {0x9C09,0x9CC7}, {0x9C0D,0x9CC5}, 
+  {0x9C10,0x9CC4}, {0x9C12,0x9CC6}, {0x9C13,0x9CC3}, {0x9C20,0x9CCB}, {0x9C23,0x9CA5}, 
+  {0x9C25,0x9CCF}, {0x9C28,0x9CCE}, {0x9C29,0x9CD0}, {0x9C2D,0x9CCD}, {0x9C31,0x9CA2}, 
+  {0x9C32,0x9CCC}, {0x9C33,0x9CD3}, {0x9C35,0x9CD8}, {0x9C37,0x9CA6}, {0x9C39,0x9CA3}, 
+  {0x9C3B,0x9CD7}, {0x9C3E,0x9CD4}, {0x9C45,0x9CD9}, {0x9C48,0x9CD5}, {0x9C49,0x9CD6}, 
+  {0x9C52,0x9CDF}, {0x9C54,0x9CDD}, {0x9C56,0x9CDC}, {0x9C57,0x9CDE}, {0x9C58,0x9C9F}, 
+  {0x9C5D,0x9CBC}, {0x9C5F,0x9C8E}, {0x9C67,0x9CE2}, {0x9C6D,0x9C9A}, {0x9C78,0x9C88}, 
+  {0x9C7A,0x9CA1}, {0x9CE5,0x9E1F}, {0x9CE9,0x9E20}, {0x9CEC,0x51EB}, {0x9CF3,0x51E4}, 
+  {0x9CF4,0x9E23}, {0x9CF6,0x9E22}, {0x9D06,0x9E29}, {0x9D07,0x9E28}, {0x9D09,0x9E26}, 
+  {0x9D15,0x9E35}, {0x9D1B,0x9E33}, {0x9D1D,0x9E32}, {0x9D1F,0x9E31}, {0x9D23,0x9E2A}, 
+  {0x9D26,0x9E2F}, {0x9D28,0x9E2D}, {0x9D2F,0x9E38}, {0x9D30,0x9E39}, {0x9D3B,0x9E3F}, 
+  {0x9D3F,0x9E3D}, {0x9D42,0x9E3A}, {0x9D51,0x9E43}, {0x9D52,0x9E46}, {0x9D53,0x9E41}, 
+  {0x9D5C,0x9E48}, {0x9D5D,0x9E45}, {0x9D60,0x9E44}, {0x9D61,0x9E49}, {0x9D6A,0x9E4C}, 
+  {0x9D6C,0x9E4F}, {0x9D6F,0x9E4E}, {0x9D72,0x9E4A}, {0x9D87,0x9E2B}, {0x9D89,0x9E51}, 
+  {0x9D93,0x9E4B}, {0x9D98,0x9E55}, {0x9D9A,0x9E57}, {0x9DA5,0x9E5B}, {0x9DA9,0x9E5C}, 
+  {0x9DAF,0x83BA}, {0x9DB4,0x9E64}, {0x9DBB,0x9E58}, {0x9DBC,0x9E63}, {0x9DC0,0x9E5A}, 
+  {0x9DC2,0x9E5E}, {0x9DC4,0x9E21}, {0x9DD3,0x9E67}, {0x9DD7,0x9E25}, {0x9DD9,0x9E37}, 
+  {0x9DDA,0x9E68}, {0x9DE5,0x9E36}, {0x9DE6,0x9E6A}, {0x9DEF,0x9E69}, {0x9DF2,0x9E6B}, 
+  {0x9DF3,0x9E47}, {0x9DF8,0x9E6C}, {0x9DF9,0x9E70}, {0x9DFA,0x9E6D}, {0x9E0C,0x9E71}, 
+  {0x9E15,0x9E2C}, {0x9E1A,0x9E66}, {0x9E1B,0x9E73}, {0x9E1D,0x9E42}, {0x9E1E,0x9E3E}, 
+  {0x9E7A,0x9E7E}, {0x9E7C,0x7877}, {0x9E7D,0x76D0}, {0x9E97,0x4E3D}, {0x9EA5,0x9EA6}, 
+  {0x9EA9,0x9EB8}, {0x9EBD,0x4E48}, {0x9ECC,0x9EC9}, {0x9EDE,0x70B9}, {0x9EE8,0x515A}, 
+  {0x9EF2,0x9EEA}, {0x9EF7,0x9EE9}, {0x9EFD,0x9EFE}, {0x9EFF,0x9F0B}, {0x9F09,0x9F0D}, 
+  {0x9F4A,0x9F50}, {0x9F4B,0x658B}, {0x9F4F,0x9F51}, {0x9F52,0x9F7F}, {0x9F54,0x9F80}, 
+  {0x9F59,0x9F85}, {0x9F5C,0x9F87}, {0x9F5F,0x9F83}, {0x9F60,0x9F86}, {0x9F61,0x9F84}, 
+  {0x9F66,0x9F88}, {0x9F6A,0x9F8A}, {0x9F6C,0x9F89}, {0x9F72,0x9F8B}, {0x9F77,0x9F8C}, 
+  {0x9F8D,0x9F99}, {0x9F90,0x5E9E}, {0x9F94,0x9F9A}, {0x9F95,0x9F9B}, {0x9F9C,0x9F9F}
+};
+
+
+
+/* the letters correspond to unicode characters which
+ * have Lu, Ll, Lt, Lm, Lo, Mn, Mc, or Me in their
+ * GENERAL CATEGORY */
+
+#define NUM_LETTER_INFO 276
+static const unirange letter_info[NUM_LETTER_INFO] = {
+  {0x41,0x5a}, {0x61,0x7a}, {0xaa,0xaa}, {0xb5,0xb5}, 
+  {0xba,0xba}, {0xc0,0xd6}, {0xd8,0xf6}, {0xf8,0x1f5}, 
+  {0x1fa,0x217}, {0x250,0x2a8}, {0x2b0,0x2b8}, {0x2bb,0x2c1}, 
+  {0x2d0,0x2d1}, {0x2e0,0x2e4}, {0x300,0x345}, {0x360,0x361}, 
+  {0x37a,0x37a}, {0x386,0x386}, {0x388,0x38a}, {0x38c,0x38c}, 
+  {0x38e,0x3a1}, {0x3a3,0x3ce}, {0x3d0,0x3d6}, {0x3da,0x3da}, 
+  {0x3dc,0x3dc}, {0x3de,0x3de}, {0x3e0,0x3e0}, {0x3e2,0x3f3}, 
+  {0x401,0x40c}, {0x40e,0x44f}, {0x451,0x45c}, {0x45e,0x481}, 
+  {0x483,0x486}, {0x490,0x4c4}, {0x4c7,0x4c8}, {0x4cb,0x4cc}, 
+  {0x4d0,0x4eb}, {0x4ee,0x4f5}, {0x4f8,0x4f9}, {0x531,0x556}, 
+  {0x559,0x559}, {0x561,0x587}, {0x591,0x5a1}, {0x5a3,0x5b9}, 
+  {0x5bb,0x5bd}, {0x5bf,0x5bf}, {0x5c1,0x5c2}, {0x5c4,0x5c4}, 
+  {0x5d0,0x5ea}, {0x5f0,0x5f2}, {0x621,0x63a}, {0x640,0x652}, 
+  {0x670,0x6b7}, {0x6ba,0x6be}, {0x6c0,0x6ce}, {0x6d0,0x6d3}, 
+  {0x6d5,0x6e8}, {0x6ea,0x6ed}, {0x901,0x903}, {0x905,0x939}, 
+  {0x93c,0x94d}, {0x951,0x954}, {0x958,0x963}, {0x981,0x983}, 
+  {0x985,0x98c}, {0x98f,0x990}, {0x993,0x9a8}, {0x9aa,0x9b0}, 
+  {0x9b2,0x9b2}, {0x9b6,0x9b9}, {0x9bc,0x9bc}, {0x9be,0x9c4}, 
+  {0x9c7,0x9c8}, {0x9cb,0x9cd}, {0x9d7,0x9d7}, {0x9dc,0x9dd}, 
+  {0x9df,0x9e3}, {0x9f0,0x9f1}, {0xa02,0xa02}, {0xa05,0xa0a}, 
+  {0xa0f,0xa10}, {0xa13,0xa28}, {0xa2a,0xa30}, {0xa32,0xa33}, 
+  {0xa35,0xa36}, {0xa38,0xa39}, {0xa3c,0xa3c}, {0xa3e,0xa42}, 
+  {0xa47,0xa48}, {0xa4b,0xa4d}, {0xa59,0xa5c}, {0xa5e,0xa5e}, 
+  {0xa70,0xa74}, {0xa81,0xa83}, {0xa85,0xa8b}, {0xa8d,0xa8d}, 
+  {0xa8f,0xa91}, {0xa93,0xaa8}, {0xaaa,0xab0}, {0xab2,0xab3}, 
+  {0xab5,0xab9}, {0xabc,0xac5}, {0xac7,0xac9}, {0xacb,0xacd}, 
+  {0xae0,0xae0}, {0xb01,0xb03}, {0xb05,0xb0c}, {0xb0f,0xb10}, 
+  {0xb13,0xb28}, {0xb2a,0xb30}, {0xb32,0xb33}, {0xb36,0xb39}, 
+  {0xb3c,0xb43}, {0xb47,0xb48}, {0xb4b,0xb4d}, {0xb56,0xb57}, 
+  {0xb5c,0xb5d}, {0xb5f,0xb61}, {0xb82,0xb83}, {0xb85,0xb8a}, 
+  {0xb8e,0xb90}, {0xb92,0xb95}, {0xb99,0xb9a}, {0xb9c,0xb9c}, 
+  {0xb9e,0xb9f}, {0xba3,0xba4}, {0xba8,0xbaa}, {0xbae,0xbb5}, 
+  {0xbb7,0xbb9}, {0xbbe,0xbc2}, {0xbc6,0xbc8}, {0xbca,0xbcd}, 
+  {0xbd7,0xbd7}, {0xc01,0xc03}, {0xc05,0xc0c}, {0xc0e,0xc10}, 
+  {0xc12,0xc28}, {0xc2a,0xc33}, {0xc35,0xc39}, {0xc3e,0xc44}, 
+  {0xc46,0xc48}, {0xc4a,0xc4d}, {0xc55,0xc56}, {0xc60,0xc61}, 
+  {0xc82,0xc83}, {0xc85,0xc8c}, {0xc8e,0xc90}, {0xc92,0xca8}, 
+  {0xcaa,0xcb3}, {0xcb5,0xcb9}, {0xcbe,0xcc4}, {0xcc6,0xcc8}, 
+  {0xcca,0xccd}, {0xcd5,0xcd6}, {0xcde,0xcde}, {0xce0,0xce1}, 
+  {0xd02,0xd03}, {0xd05,0xd0c}, {0xd0e,0xd10}, {0xd12,0xd28}, 
+  {0xd2a,0xd39}, {0xd3e,0xd43}, {0xd46,0xd48}, {0xd4a,0xd4d}, 
+  {0xd57,0xd57}, {0xd60,0xd61}, {0xe01,0xe2e}, {0xe30,0xe3a}, 
+  {0xe40,0xe4e}, {0xe81,0xe82}, {0xe84,0xe84}, {0xe87,0xe88}, 
+  {0xe8a,0xe8a}, {0xe8d,0xe8d}, {0xe94,0xe97}, {0xe99,0xe9f}, 
+  {0xea1,0xea3}, {0xea5,0xea5}, {0xea7,0xea7}, {0xeaa,0xeab}, 
+  {0xead,0xeae}, {0xeb0,0xeb9}, {0xebb,0xebd}, {0xec0,0xec4}, 
+  {0xec6,0xec6}, {0xec8,0xecd}, {0xedc,0xedd}, {0xf18,0xf19}, 
+  {0xf35,0xf35}, {0xf37,0xf37}, {0xf39,0xf39}, {0xf40,0xf47}, 
+  {0xf49,0xf69}, {0xf71,0xf84}, {0xf86,0xf87}, {0xf90,0xf95}, 
+  {0xf97,0xf97}, {0xf99,0xfad}, {0xfb1,0xfb7}, {0xfb9,0xfb9}, 
+  {0x10a0,0x10c5}, {0x10d0,0x10f6}, {0x1100,0x1159}, {0x115f,0x11a2}, 
+  {0x11a8,0x11f9}, {0x1820,0x1877}, {0x1880,0x18a9}, {0x1e00,0x1e9b}, 
+  {0x1ea0,0x1ef9}, {0x1f00,0x1f15}, 
+  {0x1f18,0x1f1d}, {0x1f20,0x1f45}, {0x1f48,0x1f4d}, {0x1f50,0x1f57}, 
+  {0x1f59,0x1f59}, {0x1f5b,0x1f5b}, {0x1f5d,0x1f5d}, {0x1f5f,0x1f7d}, 
+  {0x1f80,0x1fb4}, {0x1fb6,0x1fbc}, {0x1fbe,0x1fbe}, {0x1fc2,0x1fc4}, 
+  {0x1fc6,0x1fcc}, {0x1fd0,0x1fd3}, {0x1fd6,0x1fdb}, {0x1fe0,0x1fec}, 
+  {0x1ff2,0x1ff4}, {0x1ff6,0x1ffc}, {0x207f,0x207f}, {0x20d0,0x20e1}, 
+  {0x2102,0x2102}, {0x2107,0x2107}, {0x210a,0x2113}, {0x2115,0x2115}, 
+  {0x2118,0x211d}, {0x2124,0x2124}, {0x2126,0x2126}, {0x2128,0x2128}, 
+  {0x212a,0x2131}, {0x2133,0x2138}, {0x3005,0x3005}, {0x302a,0x302f}, 
+  {0x3031,0x3035}, {0x3041,0x3094}, {0x3099,0x309e}, {0x30a1,0x30fa}, 
+  {0x30fc,0x30fe}, {0x3105,0x312c}, {0x3131,0x318e}, {0x4e00,0x9fa5}, 
+  {0xac00,0xd7a3}, {0xf900,0xfa2d}, {0xfb00,0xfb06}, {0xfb13,0xfb17}, 
+  {0xfb1e,0xfb28}, {0xfb2a,0xfb36}, {0xfb38,0xfb3c}, {0xfb3e,0xfb3e}, 
+  {0xfb40,0xfb41}, {0xfb43,0xfb44}, {0xfb46,0xfbb1}, {0xfbd3,0xfd3d}, 
+  {0xfd50,0xfd8f}, {0xfd92,0xfdc7}, {0xfdf0,0xfdfb}, {0xfe20,0xfe23}, 
+  {0xfe70,0xfe72}, {0xfe74,0xfe74}, {0xfe76,0xfefc}, {0xff21,0xff3a}, 
+  {0xff41,0xff5a}, {0xff66,0xffbe}, {0xffc2,0xffc7}, {0xffca,0xffcf}, 
+  {0xffd2,0xffd7}, {0xffda,0xffdc}
+};
+
+
+/* the digits correspond to unicode characters which
+ * have Nd in their GENERAL CATEGORY */
+
+#define NUM_DIGIT_INFO 17
+static const unirange digit_info[NUM_DIGIT_INFO] = {
+  {0x30,0x39}, {0x660,0x669}, {0x6f0,0x6f9}, {0x966,0x96f}, 
+  {0x9e6,0x9ef}, {0xa66,0xa6f}, {0xae6,0xaef}, {0xb66,0xb6f}, 
+  {0xbe7,0xbef}, {0xc66,0xc6f}, {0xce6,0xcef}, {0xd66,0xd6f}, 
+  {0xe50,0xe59}, {0xed0,0xed9}, {0xf20,0xf29}, {0xff10,0xff19},
+  {0x1810,0x1819}
+};
+
+
+/* the spaces correspond to unicode characters which
+ * have Zs, Zl, or Zp in their GENERAL CATEGORY */
+
+#define NUM_SPACE_INFO 5
+static const unirange space_info[NUM_SPACE_INFO] = {
+  {0x20,0x20}, {0xa0,0xa0}, {0x2000,0x200b}, {0x2028,0x2029}, 
+  {0x3000,0x3000}
+};
+
+
+
+/* parse_utf8_char parses the next utf-8 character, placing its
+ * unicode equivalent in *value. The length of the utf-8 character
+ * is returned */
+int parse_utf8_char(const unsigned char *here,
+		    const unsigned char *end,
+		    unsigned short *value) {
+  unsigned short c1;
+  unsigned short c2;
+  unsigned short c3;
+  
+  *value = 0; /* will be the value for illegal characters */
+  
+  if (here <= end) {
+    c1 = (unsigned short)(*here);
+    
+    if (c1 <= 0x7f) {
+      /* found a one-byte character */
+      *value = c1;
+      return 1;
+      
+    } else if (c1 >= 0xc0 && c1 <= 0xdf && here+1 <= end &&
+	       (c2=(unsigned short)(*(here+1))) >= 0x80) {
+      /* found a two-byte character */
+      *value = ((c1 & 0x1f) << 6) + (c2 & 0x3f);
+      return 2;
+      
+    } else if (c1 >= 0xe0 && c1 <= 0xef && here+2 <= end &&
+	       (c2=(unsigned int)(*(here+1))) >= 0x80 &&
+	       (c3=(unsigned int)(*(here+2))) >= 0x80) {
+      /* found a three-byte character */
+      *value = ((c1 & 0xf) << 12) + ((c2 & 0x3f) << 6) +
+	(c3 & 0x3f);
+      return 3;
+      
+    } else {
+      /* error in encoding, return the length as 1 */
+      return 1;
+    }
+  }
+
+  /* end of string */
+  return 0;
+}
+
+
+/* output_utf8_char encodes a unicode character as a UTF-8 character.
+ * The length of the encoding is returned. If the string was not
+ * long enough to encode the character 0 is returned. */
+int output_utf8_char (unsigned short value,
+		      unsigned char *here,
+		      unsigned char *end) {
+  int len = (int)(end - here + 1); /* end is the last character */
+  if (value < 0x80) {
+    /* will be encoded in one byte */
+    if (len >= 1) {
+      *here = (unsigned char)value;
+      return 1;
+    }
+
+  } else if (value < 0x800) {
+    /* will be encoded in two bytes */
+    if (len >= 2) {
+      *here++ = 0xc0 | (unsigned char)((value >> 6) & 0x1f);
+      *here = 0x80 | (unsigned char)(value & 0x3f);
+
+      return 2;
+    }
+
+  } else {
+    /* will be encoded in three bytes */
+    if (len >= 3) {
+      *here++ = 0xe0 | (unsigned char)((value >> 12) & 0xf);
+      *here++ = 0x80 | (unsigned char)((value >> 6) & 0x3f);
+      *here = 0x80 | (unsigned char)(value & 0x3f);
+      return 3;
+    }
+  }
+
+  return 0;
+}
+
+
+static int lookup_decompose_table (unsigned short value) {
+  int first = 0;
+  int last = NUM_DECOMPOSE_INFO;
+  int here;
+
+  while (first < last) {
+    here = (last-first)/2 + first;
+    if (value < decompose_info[here].ch) {
+      last = here;
+    } else if (value > decompose_info[here].ch) {
+      first = here+1;
+    } else {
+      return here;
+    }
+  }
+
+  return -1;
+}
+
+/* decompose_str will decompose a unicode string into its canonical
+ * equivalents. NULL is returned if the input array was not 
+ * large enough to contain the fully decomposed string (the array
+ * will be in a correct, but partially decomposed state). The input 
+ * must be null-terminated. */
+unsigned short *decompose_str (unsigned short *input,
+			       int max_output_len) {
+  int curpos = 0;
+  int curlen = unicode_strlen (input);
+  int tablepos = 0;
+  int leninc;
+  int i;
+
+  while (input[curpos] != 0) {
+    tablepos = lookup_decompose_table (input[curpos]);
+    if (tablepos >= 0) {
+      /* found a decomposition */
+      leninc = unicode_strnlen (decompose_info[tablepos].str, 3)-1;
+      if (curlen+leninc < max_output_len) {
+	/* enough space for this decomposition */
+
+	if (leninc > 1) {
+	  /* we have to shift the array along */
+	  for (i=curlen-1; i>=curpos; --i) {
+	    input[i+leninc] = input[i];
+	  }
+	  input[curlen+leninc] = 0;
+	  curlen += leninc;
+	}
+
+	/* decompose the character */
+	for (i=0; i<=leninc; ++i) {
+	  input[curpos+i] = decompose_info[tablepos].str[i];
+	}
+
+	/* note: curpos is not incremented because the decomposed */
+	/*       characters might need decomposing */
+
+      } else {
+	/* no space left in string */
+	return NULL;
+      }
+
+    } else {
+      /* the character cannot be decomposed */
+      ++curpos;
+    }
+  }
+
+  return input;
+}
+
+
+
+/* unicode_cat_data is a combination of the letter, digit, and
+ * space information in a form that is quick to look up.
+ * The information about each byte is stored in two bits
+ *
+ * 00 - neither letter, digit or space
+ * 01 - letter
+ * 10 - space
+ * 11 - digit
+ *
+ * You can test for letter | space by looking at the right
+ * column
+ */
+/*unsigned long *unicode_cat_data;*/
+
+void create_unicat_data () {
+  int i=0;
+  int min_start=0;
+  int min_end=0;
+  register unsigned long min_value=0; /* filling the whole byte */
+  
+  const unirange *letter_here = letter_info;
+  const unirange *letter_end = letter_info+NUM_LETTER_INFO;
+  const unirange *digit_here = digit_info;
+  const unirange *digit_end = digit_info+NUM_DIGIT_INFO;
+  const unirange *space_here = space_info;
+  const unirange *space_end = space_info+NUM_SPACE_INFO;
+
+  if (unicode_cat_data != NULL) return;
+  unicode_cat_data = (unsigned long *) malloc (0x10000/4);
+  if (unicode_cat_data == NULL) return;
+  
+  while (i <= 0xffff) {
+    /* decide what to fill with next */
+    min_start = i;
+    min_end = 0xffff;
+    min_value = 0; /* 00 */
+    
+    while (letter_here < letter_end && letter_here->last < i) ++letter_here;
+    if (letter_here < letter_end && letter_here->last <= min_end) {
+      min_start = letter_here->first;
+      min_end = letter_here->last;
+      min_value = 0x55555555; /* 01 */
+    }
+    
+    while (digit_here < digit_end && digit_here->last < i) ++digit_here;
+    if (digit_here < digit_end && digit_here->last <= min_end) {
+      min_start = digit_here->first;
+      min_end = digit_here->last;
+      min_value = 0xffffffff; /* 11 */
+    }
+    
+    while (space_here < space_end && space_here->last < i) ++space_here;
+    if (space_here < space_end && space_here->last <= min_end) {
+      min_start = space_here->first;
+      min_end = space_here->last;
+      min_value = 0xaaaaaaaa; /* 10 */
+    }
+
+    if (min_start < i) min_start = i;
+    else if (min_start > i) {
+      min_end = min_start-1;
+      min_start = i;
+      min_value = 0; /* 00 */
+    }
+
+    /* fill the entries from min_start to min_end with min_value */
+    while (i <= min_end) {
+      /* special version for common case */
+      if (i % 16 == 0) {
+	unicode_cat_data[i/16] = min_value; /* doesn't matter if too long */
+	i += 16;
+	if (i > min_end) {
+	  i = min_end+1;
+	  break;
+	}
+	
+      } else {
+	register unsigned long mask = 3 << ((i % 16) * 2);
+	unicode_cat_data[i/16] = (unicode_cat_data[i/16] & (~mask)) |
+				  (min_value & mask);
+	++i;
+      }
+    }
+  }
+}
+
+/* does a binary search on a range table */
+static int in_unirange (const unirange *info, int num_info,
+			unsigned short value) {
+  int first = 0;
+  int last = num_info;
+  int here;
+
+  while (first < last) {
+    here = (last-first)/2 + first;
+    if (value < info[here].first) {
+      last = here;
+    } else if (value > info[here].last) {
+      first = here+1;
+    } else {
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
+
+
+/* tests to see whether 'value' is a valid Unicode letter */
+int is_unicode_letter (unsigned short value) {
+  if (unicode_cat_data == NULL) create_unicat_data ();
+  if (unicode_cat_data == NULL) {
+    /* use old method */
+    return in_unirange(letter_info, NUM_LETTER_INFO, value);
+  }
+
+  return (((unicode_cat_data[value/16] >> ((value%16)*2)) & 0x3) == 0x1);
+}
+
+/* tests to see whether 'value' is a valid Unicode digit */
+int is_unicode_digit (unsigned short value) {
+  if (unicode_cat_data == NULL) create_unicat_data ();
+  if (unicode_cat_data == NULL) {
+    /* use old method */
+    return in_unirange(digit_info, NUM_DIGIT_INFO, value);
+  }
+
+  return (((unicode_cat_data[value/16] >> ((value%16)*2)) & 0x3) == 0x3);
+}
+
+/* tests to see whether 'value' is a valid Unicode letter or 
+ * digit */
+int is_unicode_letdig (unsigned short value) {
+  if (unicode_cat_data == NULL) create_unicat_data ();
+  if (unicode_cat_data == NULL) {
+    /* use old method */
+    return (in_unirange(letter_info, NUM_LETTER_INFO, value) ||
+	    in_unirange(digit_info, NUM_DIGIT_INFO, value));
+    
+  }
+
+  return ((unicode_cat_data[value/16] >> ((value%16)*2)) & 0x1);
+}
+
+/* tests to see whether 'value' is a valid space
+ * The test includes both "C" spaces and "Unicode" spaces, i.e. 
+ * form-feed, newline, carriage return, horizontal tab,
+ * vertical tab, and the Zs, Zl, and Zp Unicode categorizations */
+int is_unicode_space (unsigned short value) {
+  if (value < 0x80) return isspace (value);
+  if (unicode_cat_data == NULL) create_unicat_data ();
+  if (unicode_cat_data == NULL) {
+    /* use old method */
+    return in_unirange(space_info, NUM_SPACE_INFO, value);
+  }
+
+  return (((unicode_cat_data[value/16] >> ((value%16)*2)) & 0x3) == 0x2);
+}
+
+/* returns the length of the unicode string */
+int unicode_strlen (const unsigned short *str) {
+  int len = 0;
+
+  /* keep going till you find the null-terminator */
+  while (*str != 0) {
+    ++len;
+    ++str;
+  }
+
+  return len;
+}
+
+/* returns the length of the unicode string, up to a maximum */
+int unicode_strnlen (const unsigned short *str, int max_length) {
+  int len = 0;
+
+  /* keep going till you find the null-terminator */
+  while (*str != 0 && len < max_length ) {
+    ++len;
+    ++str;
+  }
+
+  return len;
+}
+
+
+/* Does a binary search on a relate table, returns -1 if it is not
+ * found. */
+static int search_unirelate (const unirelate *info, int num_info,
+			     unsigned short value) {
+  int first = 0;
+  int last = num_info;
+  int here;
+
+  while (first < last) {
+    here = (last-first)/2 + first;
+    if (value < info[here].ch1) {
+      last = here;
+    } else if (value > info[here].ch1) {
+      first = here+1;
+    } else {
+      return here;
+    }
+  }
+
+  return -1;
+}
+
+
+/* returns the upper-case equivalent of value */
+unsigned short unicode_toupper (unsigned short value) {
+  int related = search_unirelate (toupper_info, NUM_TOUPPER_INFO, value);
+  if (related >= 0) {
+    value = toupper_info[related].ch2;
+  }
+  return value;
+}
+
+/* returns the lower-case equivalent of value */
+unsigned short unicode_tolower (unsigned short value) {
+  int related = search_unirelate (tolower_info, NUM_TOLOWER_INFO, value);
+  if (related >= 0) {
+    value = tolower_info[related].ch2;
+  }
+  return value;
+}
+
+/* returns the simplified Chinese character equivalent of 
+ * another Chinese character */
+unsigned short unicode_tosimplified (unsigned short value) {
+  int related = search_unirelate (tosimplified_info, NUM_TOSIMPLIFIED_INFO, value);
+  if (related >= 0) {
+    value = tosimplified_info[related].ch2;
+  }
+  return value;
+}
+
+
+/* converts a utf-8 word (string with length stored in the first byte
+ * to a Unicode array. To handle all situations the output buffer should
+ * be 256 unsigned shorts long. The output will also have the length as
+ * the first entry. */
+unsigned short *utf8_word_to_unicode (const unsigned char *input,
+				      unsigned short *output,
+				      int max_output_length) {
+  int inlen = *input;
+  const unsigned char *inhere = input+1;
+  const unsigned char *inend = &inhere[inlen-1];
+  unsigned short c;
+  int clen;
+  
+  int outlen = 0;
+  unsigned short *outhere = output+1;
+  
+  while (inhere <= inend && inlen < max_output_length-1) {
+    /* decode the character */
+    clen = parse_utf8_char (inhere, inend, &c);
+    inhere += clen;
+
+    if (clen > 0) {
+      /* store the character */
+      *outhere = c;
+      ++outhere;
+      ++outlen;
+    }
+  }
+
+  output[0] = outlen;
+  return output;
+}
+
+
+/* converts a unicode word buffer (with the length stored in the
+ * entry) to a utf8 encoded word output (with the length stored in
+ * the first byte. Only 255 bytes (not characters) can be stored 
+ * in the output. */
+unsigned char *unicode_to_utf8_word (const unsigned short *input,
+				     unsigned char *output,
+				     int max_output_length) {
+  int inlen = *input;
+  const unsigned short *word = input + 1;
+  int in_i = 0;
+  int clen;
+
+  int outlen = 0;
+  unsigned char *outhere = output+1;
+  unsigned char *outend = output+max_output_length;
+
+  while (in_i < inlen) {
+    if ((clen=output_utf8_char(word[in_i], outhere, outend)) == 0) {
+      /* ran out of space to encode the character */
+      break;
+    }
+
+    outhere += clen;
+    outlen += clen;
+    ++in_i;
+  }
+
+  output[0] = outlen;
+
+  return output;
+}
+
Index: /indexers/branches/3.03a/mgpp/lib/unitool.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/unitool.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/unitool.h	(revision 14757)
@@ -0,0 +1,80 @@
+#ifndef UNITOOL_H
+#define UNITOOL_H
+
+/* This module is based on Unicode 2.1 */
+
+
+/* parse_utf8_char parses the next utf-8 character, placing its
+ * unicode equivalent in *value. The length of the utf-8 character
+ * is returned. end is the address of the last character. */
+int parse_utf8_char (const unsigned char *here,
+		     const unsigned char *end,
+		     unsigned short *value);
+
+/* output_utf8_char encodes a unicode character as a UTF-8 character.
+ * The length of the encoding is returned. If the string was not
+ * long enough to encode the character 0 is returned. end is the
+ * address of the last character */
+int output_utf8_char (unsigned short value,
+		      unsigned char *here,
+		      unsigned char *end);
+
+/* decompose_str will decompose a unicode string into its canonical
+ * equivalents. NULL is returned if the input array was not 
+ * large enough to contain the fully decomposed string (the array
+ * will be in a correct, but partially decomposed state). The input 
+ * must be null-terminated. */
+unsigned short *decompose_str (unsigned short *input,
+			       int max_output_len);
+
+/* tests to see whether 'value' is a valid Unicode letter */
+int is_unicode_letter (unsigned short value);
+
+/* tests to see whether 'value' is a valid Unicode digit */
+int is_unicode_digit (unsigned short value);
+
+/* tests to see whether 'value' is a valid Unicode letter or 
+ * digit */
+int is_unicode_letdig (unsigned short value);
+
+/* tests to see whether 'value' is a valid space
+ * The test includes both "C" spaces and "Unicode" spaces, i.e. 
+ * form-feed, newline, carriage return, horizontal tab,
+ * vertical tab, and the Zs, Zl, and Zp Unicode categorizations */
+int is_unicode_space (unsigned short value);
+
+/* returns the length of the unicode string */
+int unicode_strlen (const unsigned short *str);
+
+/* returns the length of the unicode string, up to a maximum */
+int unicode_strnlen (const unsigned short *str, int max_length);
+
+/* returns the upper-case equivalent of value */
+unsigned short unicode_toupper (unsigned short value);
+
+/* returns the lower-case equivalent of value */
+unsigned short unicode_tolower (unsigned short value);
+
+/* returns the simplified Chinese character equivalent of 
+ * another Chinese character */
+unsigned short unicode_tosimplified (unsigned short value);
+
+
+/* converts a utf-8 word (string with length stored in the first byte
+ * to a Unicode array. To handle all situations the output buffer should
+ * be 256 unsigned shorts long. The output will also have the length as
+ * the first entry. */
+unsigned short *utf8_word_to_unicode (const unsigned char *input,
+				      unsigned short *output,
+				      int max_output_length);
+
+/* converts a unicode word buffer (with the length stored in the
+ * entry) to a utf8 encoded word output (with the length stored in
+ * the first byte. Only 255 bytes (not characters) can be stored 
+ * in the output. */
+unsigned char *unicode_to_utf8_word (const unsigned short *input,
+				     unsigned char *output,
+				     int max_output_length);
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/win32in.c
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/win32in.c	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/win32in.c	(revision 14757)
@@ -0,0 +1,85 @@
+/* This module provides an equivalent of <netinet/in.h> on  */
+/* unix systems. */
+#include "win32in.h"
+
+unsigned long htonl(unsigned long x) {
+#if defined (LITTLE_ENDIAN) || defined (_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN)
+	x = ((x >> 24) & 0x000000FF) | ((x >> 8) & 0x0000FF00) |
+		((x << 8) & 0x00FF0000) | ((x << 24) & 0xFF000000);
+#endif
+
+	return x;
+}
+
+mg_ullong ntohll(mg_ullong x)
+{
+#if defined (LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN)
+	x = 
+	  ((x >> 56) & 0x00000000000000FF) | ((x >> 40) & 0x000000000000FF00) |
+	  ((x >> 24) & 0x0000000000FF0000) | ((x >> 8)  & 0x00000000FF000000) |
+	  ((x << 8)  & 0x000000FF00000000) | ((x << 24) & 0x0000FF0000000000) |
+		((x << 40) & 0x00FF000000000000) | ((x << 56) & 0xFF00000000000000);
+#endif
+  return x;
+}
+
+unsigned long ntohl(unsigned long x) {
+#if defined (LITTLE_ENDIAN) || defined (_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN)
+	x = ((x >> 24) & 0x000000FF) | ((x >> 8) & 0x0000FF00) |
+		((x << 8) & 0x00FF0000) | ((x << 24) & 0xFF000000);
+#endif
+	return x;
+}
+
+unsigned short htons(unsigned short x) {
+#if defined (LITTLE_ENDIAN) || defined (_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN)
+	x = ((x >> 8) & 0x00FF) | ((x << 8) & 0xFF00);
+#endif
+	return x;
+}
+
+unsigned short ntohs(unsigned short x) {
+#if defined (LITTLE_ENDIAN) || defined (_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN)
+	x = ((x >> 8) & 0x00FF) | ((x << 8) & 0xFF00);
+#endif
+	return x;
+}
+
+/* just to test stuff
+#include <stdio.h>
+
+main () {
+	long x;
+	short sx;
+
+	x = 0x000000FF;
+	printf ("before %i, ",(int)x);
+	x = htonl (x);
+	printf ("after %i\n",(int)x);
+
+	x = 0x0000FF00;
+	printf ("before %i, ",(int)x);
+	x = htonl (x);
+	printf ("after %i\n",(int)x);
+
+	x = 0x00FF0000;
+	printf ("before %i, ",(int)x);
+	x = htonl (x);
+	printf ("after %i\n",(int)x);
+
+	x = 0xFF000000;
+	printf ("before %i, ",(int)x);
+	x = htonl (x);
+	printf ("after %i\n\n",(int)x);
+
+	sx = 0x00FF;
+	printf ("before %i, ",(int)sx);
+	sx = htons (sx);
+	printf ("after %i\n",(int)sx);
+
+	sx = 0xFF00;
+	printf ("before %i, ",(int)sx);
+	sx = htons (sx);
+	printf ("after %i\n",(int)sx);
+}
+*/
Index: /indexers/branches/3.03a/mgpp/lib/win32in.h
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/win32in.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/win32in.h	(revision 14757)
@@ -0,0 +1,20 @@
+/* This module provides an equivalent of <netinet/in.h> on  */
+/* unix systems. */
+#ifdef __WIN32__
+#define _LITTLE_ENDIAN
+#endif
+
+#include "longlong.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+unsigned long htonl(unsigned long x);
+unsigned long ntohl(unsigned long x);
+mg_ullong ntohll(mg_ullong x);
+unsigned short htons(unsigned short x);
+unsigned short ntohs(unsigned short x);
+
+#ifdef __cplusplus
+}
+#endif
Index: /indexers/branches/3.03a/mgpp/lib/xmalloc.c
===================================================================
--- /indexers/branches/3.03a/mgpp/lib/xmalloc.c	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/lib/xmalloc.c	(revision 14757)
@@ -0,0 +1,111 @@
+/* xmalloc.c -- malloc with out of memory checking
+   Copyright (C) 1990, 91, 92, 93, 94 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 program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# ifdef __WIN32__  /* [RPAP - Feb 97: WIN32 Port] */
+#  include <win32cfg.h>
+# else
+#  include <sysfuncs.h>
+# endif
+#endif
+
+#if __STDC__
+#define VOID void
+#else
+#define VOID char
+#endif
+
+#include <sys/types.h>
+
+#if STDC_HEADERS
+#include <stdlib.h>
+#else
+VOID *malloc ();
+VOID *realloc ();
+void free ();
+#endif
+
+/* This is for other GNU distributions with internationalized messages.
+   The GNU C Library itself does not yet support such messages.  */
+#if HAVE_LIBINTL_H
+# include <libintl.h>
+#else
+# define gettext(msgid) (msgid)
+#endif
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+
+/* Exit value when the requested amount of memory is not available.
+   The caller may set it to some other value.  */
+int xmalloc_exit_failure = EXIT_FAILURE;
+
+#if defined(__WIN32__)
+void error (int, int, const char *, ...);
+#else
+#if __STDC__ && (HAVE_VPRINTF || HAVE_DOPRNT)
+void error (int, int, const char *, ...);
+#else
+void error (int, int, char *, char *, char *, char *, char *, char *, char *, char *, char *);
+#endif
+#endif
+
+static VOID *
+fixup_null_alloc (n)
+     size_t n;
+{
+  VOID *p;
+
+  p = 0;
+  if (n == 0)
+    p = malloc ((size_t) 1);
+  if (p == 0)
+    error (xmalloc_exit_failure, 0, gettext ("Memory exhausted"));
+  return p;
+}
+
+/* Allocate N bytes of memory dynamically, with error checking.  */
+
+VOID *
+xmalloc (n)
+     size_t n;
+{
+  VOID *p;
+
+  p = malloc (n);
+  if (p == 0)
+    p = fixup_null_alloc (n);
+  return p;
+}
+
+/* Change the size of an allocated block of memory P to N bytes,
+   with error checking.
+   If P is NULL, run xmalloc.  */
+
+VOID *
+xrealloc (p, n)
+     VOID *p;
+     size_t n;
+{
+  if (p == 0)
+    return xmalloc (n);
+  p = realloc (p, n);
+  if (p == 0)
+    p = fixup_null_alloc (n);
+  return p;
+}
Index: /indexers/branches/3.03a/mgpp/mkinstalldirs
===================================================================
--- /indexers/branches/3.03a/mgpp/mkinstalldirs	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/mkinstalldirs	(revision 14757)
@@ -0,0 +1,32 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Last modified: 1994-03-25
+# Public domain
+
+errstatus=0
+
+for file in ${1+"$@"} ; do 
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d in ${1+"$@"} ; do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp" 1>&2
+        mkdir "$pathcomp" || errstatus=$?
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
Index: /indexers/branches/3.03a/mgpp/stamp-h.in
===================================================================
--- /indexers/branches/3.03a/mgpp/stamp-h.in	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/stamp-h.in	(revision 14757)
@@ -0,0 +1,1 @@
+timestamp
Index: /indexers/branches/3.03a/mgpp/text/FIvfLevelInfo.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/FIvfLevelInfo.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/FIvfLevelInfo.cpp	(revision 14757)
@@ -0,0 +1,129 @@
+/**************************************************************************
+ *
+ * FIvfLevelInfo.cpp -- File functions for document levels
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "FIvfLevelInfo.h"
+
+
+IvfLevelInfo::IvfLevelInfo () {
+  Clear();
+}
+
+void IvfLevelInfo::Clear () {
+  levelTag.erase (levelTag.begin(), levelTag.end());
+  numEntries = 0;
+  approxWeightsDiskPtr = 0;
+  exactWeightsDiskPtr = 0;
+  workInLevel = false;
+}
+
+bool IvfLevelInfo::Read (FILE *f) {
+  workInLevel = false;
+  return (ReadUCArray (f, levelTag) &&
+	  ReadUL (f, numEntries) &&
+	  ReadUL (f, approxWeightsDiskPtr) &&
+	  ReadUL (f, exactWeightsDiskPtr));
+}
+
+bool IvfLevelInfo::Write (FILE *f) const {
+  return (WriteUCArray (f, levelTag) &&
+	  WriteUL (f, numEntries) &&
+	  WriteUL (f, approxWeightsDiskPtr) &&
+	  WriteUL (f, exactWeightsDiskPtr));
+}
+
+// stream output for debugging purposes
+ostream &operator<<(ostream &s, const IvfLevelInfo &l) {
+  s << "  Tag: \"" << l.levelTag << "\"\n"
+    << "  numEntries: " << l.numEntries << "\n"
+    << "  approxWeightsDiskPtr: " << l.approxWeightsDiskPtr << "\n"
+    << "  exactWeightsDiskPtr: " << l.exactWeightsDiskPtr << "\n"
+    << "  workInLevel: " << ((l.workInLevel) ? "true" : "false") << "\n\n";
+  
+  return s;
+}
+
+
+
+FIvfLevel::FIvfLevel () {
+  Clear ();
+}
+
+void FIvfLevel::Clear () {
+  docTag.erase (docTag.begin(), docTag.end());
+  indexLevel.erase (indexLevel.begin(), indexLevel.end());
+  levelInfo.erase (levelInfo.begin(), levelInfo.end());
+}
+
+bool FIvfLevel::Read (FILE *f) {
+  if (!ReadUCArray (f, docTag) ||
+      !ReadUCArray (f, indexLevel))
+    return false;
+  
+  // read in the array size
+  unsigned long arrSize = 0;
+  if (!ReadVarLenUL (f, arrSize)) return false;
+  
+  IvfLevelInfo thisLevel;
+  while (arrSize > 0) {
+    // read and insert the next level information
+    if (!thisLevel.Read (f)) return false;
+    levelInfo[thisLevel.levelTag] = thisLevel;
+    
+    --arrSize;
+  }
+
+  return true;
+}
+
+bool FIvfLevel::Write (FILE *f) const {
+  if (!WriteUCArray (f, docTag) ||
+      !WriteUCArray (f, indexLevel))
+    return false;
+  
+  // write out the array size
+  if (!WriteVarLenUL (f, levelInfo.size())) return false;
+
+  // write out each level info
+  IvfLevelInfoMap::const_iterator here = levelInfo.begin();
+  IvfLevelInfoMap::const_iterator end = levelInfo.end();
+  while (here != end) {
+    if (!(*here).second.Write (f)) return false;
+    
+    ++here;
+  }
+
+  return true;
+}
+
+// stream output for debugging purposes
+ostream &operator<<(ostream &s, const FIvfLevel &l) {
+  s << "docTag: \"" << l.docTag << "\"\n"
+    << "indexLevel: \"" << l.indexLevel << "\"\n";
+  
+  IvfLevelInfoMap::const_iterator here = l.levelInfo.begin ();
+  IvfLevelInfoMap::const_iterator end = l.levelInfo.end ();
+  while (here != end) {
+    s << (*here).second;
+    ++here;
+  }
+  
+  return s;
+}
Index: /indexers/branches/3.03a/mgpp/text/FIvfLevelInfo.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/FIvfLevelInfo.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/FIvfLevelInfo.h	(revision 14757)
@@ -0,0 +1,77 @@
+/**************************************************************************
+ *
+ * FIvfLevelInfo.h -- File functions for document levels
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef FIVFLEVELINFO_H
+#define FIVFLEVELINFO_H
+
+#if defined(GSDL_USE_OBJECTSPACE)
+#  include <ospace\std\map>
+#elif defined(GSDL_USE_STL_H)
+#  include <map.h>
+#else
+#  include <map>
+#endif
+
+#include <stdio.h>
+#include "UCArray.h"
+
+
+class IvfLevelInfo {
+public:
+  UCArray levelTag;
+  unsigned long numEntries; // N for level
+  unsigned long approxWeightsDiskPtr;
+  unsigned long exactWeightsDiskPtr;
+  bool workInLevel;  // this is just a working variable,
+                     // it is not saved or read from the file
+  
+  IvfLevelInfo ();
+  void Clear ();
+
+  bool Read (FILE *f);
+  bool Write (FILE *f) const;
+};
+
+// stream output for debugging purposes
+ostream &operator<<(ostream &s, const IvfLevelInfo &l);
+
+
+typedef map<UCArray, IvfLevelInfo, LTUCArray> IvfLevelInfoMap;
+
+
+class FIvfLevel {
+public:
+  UCArray docTag;
+  UCArray indexLevel;    // empty for word level index
+  IvfLevelInfoMap levelInfo;
+  
+  FIvfLevel ();
+  void Clear ();
+
+  bool Read (FILE *f);
+  bool Write (FILE *f) const;
+};
+
+// stream output for debugging purposes
+ostream &operator<<(ostream &s, const FIvfLevel &l);
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/FText.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/FText.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/FText.cpp	(revision 14757)
@@ -0,0 +1,249 @@
+/**************************************************************************
+ *
+ * FText.cpp -- File structures for text compression
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "FText.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+
+BitAddr::BitAddr () {
+  Clear ();  
+}
+
+void BitAddr::Clear () {
+  byte = 0;
+  bit = 0;
+}
+
+bool BitAddr::Read (FILE *f) {
+  return (ReadUL (f, byte) && ReadUC (f, bit));
+}
+
+bool BitAddr::Write (FILE *f) const {
+  return (WriteUL (f, byte) && WriteUC (f, bit));
+}
+
+#define BITADDRLEN (sizeof(unsigned long) + sizeof(unsigned char))
+
+  
+TextLevelInfo::TextLevelInfo () {
+  Clear();
+}
+
+void TextLevelInfo::Clear () {
+  levelTag.erase (levelTag.begin(), levelTag.end());
+  textIdxPtr = 0;
+  numEntries = 0;
+}
+
+bool TextLevelInfo::Read (FILE *f) {
+  return (ReadUCArray (f, levelTag) &&
+	  ReadUL (f, textIdxPtr) &&
+	  ReadUL (f, numEntries));
+}
+
+bool TextLevelInfo::Write (FILE *f) const {
+  return (WriteUCArray (f, levelTag) &&
+	  WriteUL (f, textIdxPtr) &&
+	  WriteUL (f, numEntries));
+}
+
+ostream &operator<<(ostream &s, const TextLevelInfo &l) {
+  s << "  Tag: \"" << l.levelTag << "\"\n"
+    << "  textIdxPtr: " << l.textIdxPtr << "\n"
+    << "  numEntries: " << l.numEntries << "\n\n";
+  
+  return s;
+}
+
+
+FTextLevel::FTextLevel () {
+  Clear();
+}
+
+void FTextLevel::Clear () {
+  levelInfo.erase (levelInfo.begin(), levelInfo.end());
+}
+
+bool FTextLevel::Read (FILE *f) {
+  // read in the array size
+  unsigned long arrSize = 0;
+  if (!ReadVarLenUL (f, arrSize)) return false;
+
+  TextLevelInfo thisLevel;
+  while (arrSize > 0) {
+    // read and insert the next level information
+    if (!thisLevel.Read (f)) return false;
+    levelInfo[thisLevel.levelTag] = thisLevel;
+    
+    --arrSize;
+  }
+
+  return true;
+}
+
+bool FTextLevel::Write (FILE *f) const {
+  // write out the array size
+  if (!WriteVarLenUL (f, levelInfo.size())) return false;
+
+  // write out each level info
+  TextLevelInfoMap::const_iterator here = levelInfo.begin();
+  TextLevelInfoMap::const_iterator end = levelInfo.end();
+  while (here != end) {
+    if (!(*here).second.Write (f)) return false;
+    
+    ++here;
+  }
+
+  return true;
+}
+
+ostream &operator<<(ostream &s, const FTextLevel &l) {
+  TextLevelInfoMap::const_iterator here = l.levelInfo.begin ();
+  TextLevelInfoMap::const_iterator end = l.levelInfo.end ();
+  while (here != end) {
+    s << (*here).second;
+    ++here;
+  }
+  
+  return s;
+}
+
+
+TextIdx::TextIdx () {
+  Clear ();
+}
+
+void TextIdx::Clear () {
+  start.Clear();
+  end.Clear();
+  which = 0;
+}
+
+#define TEXTIDXLEN (BITADDRLEN*2 + sizeof(char))
+
+bool TextIdx::Read (FILE *f, const TextLevelInfo &levelInfo,
+		    unsigned long docNum) {
+  if (!SeekTextIdx (f, levelInfo, docNum)) return false;
+  return Read (f);
+}
+
+bool TextIdx::Read (FILE *f) {
+  return (start.Read (f) && end.Read (f) && ReadUC (f, which));
+}
+
+bool TextIdx::Write (FILE *f) const {
+  return (start.Write (f) && end.Write (f) && WriteUC (f, which));
+}
+
+ostream &operator<<(ostream &s, const TextIdx &t) {
+  s << "start byte: " << t.start.byte << "\n";
+  s << "start bit:  " << (int)t.start.bit << "\n";
+  s << "end byte:   " << t.end.byte << "\n";
+  s << "end bit:    " << (int)t.end.bit << "\n";
+  s << "which:      " << (int)t.which << "\n\n";
+  
+  return s;
+}
+
+
+bool SeekTextIdx (FILE *f, const TextLevelInfo &levelInfo,
+		  unsigned long docNum) {
+  if (docNum == 0 || docNum > levelInfo.numEntries) return false;
+  
+  unsigned long seekPos = levelInfo.textIdxPtr + (docNum-1) * TEXTIDXLEN;
+  if (fseek (f, seekPos, SEEK_SET) != 0) return false;
+  
+  return true;
+}
+
+
+bool ReadTextIdxArray (FILE *f, TextIdxArray &a, unsigned long arrSize) {
+  // clear the array
+  a.erase (a.begin(), a.end());
+
+  // read in each element
+  TextIdx idx;
+  while (arrSize > 0) {
+    if (!idx.Read(f)) return false;
+    a.push_back (idx);
+    --arrSize;
+  }
+
+  return true;
+}
+
+bool WriteTextIdxArray (FILE *f, const TextIdxArray &a) {
+  TextIdxArray::const_iterator here = a.begin();
+  TextIdxArray::const_iterator end = a.end();
+  while (here != end) {
+    if (!(*here).Write(f)) return false;
+    ++here;
+  }
+  
+  return true;
+}
+
+
+CompressTextInfo::CompressTextInfo () {
+  Clear();
+}
+
+void CompressTextInfo::Clear () {
+  ResetStart();
+  docPtrs.erase (docPtrs.begin(), docPtrs.end());
+}
+
+void CompressTextInfo::ResetStart () {
+  inDoc = false;
+  start.Clear();
+  which = 0;
+}
+  
+void CompressTextInfo::SetStart (unsigned long startPos,
+				 unsigned char startBit,
+				 unsigned char startWhich) {
+  // place an imaginary end tag if needed
+  // note: the document tag always needs a closing tag
+  if (inDoc) SetEnd (startPos, startBit);
+
+  // remember start of level
+  inDoc = true;
+  start.byte = startPos;
+  start.bit = startBit;
+  which = startWhich;
+}
+
+void CompressTextInfo::SetEnd (unsigned long endPos,
+			       unsigned char endBit) {
+  if (inDoc) {
+    // add completed entry to list of ptrs
+    TextIdx textIdx;
+    textIdx.start = start;
+    textIdx.end.byte = endPos;
+    textIdx.end.bit = endBit;
+    textIdx.which = which;
+    docPtrs.push_back (textIdx);
+    
+    // reset this entry
+    ResetStart();
+  }
+}
+
Index: /indexers/branches/3.03a/mgpp/text/FText.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/FText.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/FText.h	(revision 14757)
@@ -0,0 +1,150 @@
+/**************************************************************************
+ *
+ * FText.h -- File structures for text compression
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef FTEXT_H
+#define FTEXT_H
+
+#if defined(GSDL_USE_OBJECTSPACE)
+#  include <ospace\std\map>
+#elif defined(GSDL_USE_STL_H)
+#  include <map.h>
+#else
+#  include <map>
+#endif
+
+#include <stdio.h>
+#include "UCArray.h"
+
+
+// holds a bit address
+class BitAddr {
+public:
+  unsigned long byte;
+  unsigned char bit;
+
+  BitAddr ();
+  void Clear ();
+
+  bool Read (FILE *f);
+  bool Write (FILE *f) const;
+};
+
+
+class TextLevelInfo {
+public:
+  UCArray levelTag;
+  unsigned long textIdxPtr;
+  unsigned long numEntries;
+
+  TextLevelInfo ();
+  void Clear ();
+
+  bool Read (FILE *f);
+  bool Write (FILE *f) const;
+};
+
+// stream output for debugging purposes
+ostream &operator<<(ostream &s, const TextLevelInfo &l);
+
+
+typedef map<UCArray, TextLevelInfo, LTUCArray> TextLevelInfoMap;
+
+
+class FTextLevel {
+public:
+  TextLevelInfoMap levelInfo;
+  
+  FTextLevel ();
+  void Clear ();
+
+  bool Read (FILE *f);
+  bool Write (FILE *f) const;
+};
+
+// stream output for debugging purposes
+ostream &operator<<(ostream &s, const FTextLevel &l);
+
+
+// the text.idx file points into the compressed text
+class TextIdx {
+public:
+  BitAddr start;       // the first bit of the compressed text
+  BitAddr end;         // the first bit past the end of the text
+  unsigned char which; // 0 = non-word, 1 = word
+  
+  TextIdx ();
+  void Clear ();
+
+  // does a seek and reads the appropriate record
+  bool Read (FILE *f, const TextLevelInfo &levelInfo,
+	     unsigned long docNum);
+
+  bool Read (FILE *f);
+  bool Write (FILE *f) const;
+};
+
+// stream output for debugging purposes
+ostream &operator<<(ostream &s, const TextIdx &t);
+
+
+// note: document numbers start at 1
+
+bool SeekTextIdx (FILE *f, const TextLevelInfo &levelInfo,
+		  unsigned long docNum);
+
+
+// used to store the pointers while compressing the text
+typedef vector<TextIdx> TextIdxArray;
+
+bool ReadTextIdxArray (FILE *f, TextIdxArray &a, unsigned long arrSize);
+bool WriteTextIdxArray (FILE *f, const TextIdxArray &a);
+
+
+// used to store information about a level while compressing the text
+class CompressTextInfo {
+public:
+  bool inDoc;
+  BitAddr start;
+  unsigned char which;
+  TextIdxArray docPtrs;
+
+  CompressTextInfo ();
+  void Clear ();
+
+  // clears inDoc, start, and which (not the docPtrs)
+  void ResetStart ();
+  
+  // set the start of a level (closing off the last opening
+  // tag if needed)
+  void SetStart (unsigned long startPos,
+		 unsigned char startBit,
+		 unsigned char startWhich);
+
+  // if in a document, it will set the end, add the document to the
+  // list of document ptrs, and then call ResetStart
+  void SetEnd (unsigned long endPos,
+	       unsigned char endBit);
+};
+
+typedef map<UCArray, CompressTextInfo, LTUCArray> CompressTextInfoMap;
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/FileBuf.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/FileBuf.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/FileBuf.cpp	(revision 14757)
@@ -0,0 +1,50 @@
+/**************************************************************************
+ *
+ * FileBuf.cpp -- File buffer
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "FileBuf.h"
+#include "sysfuncs.h"
+
+#ifdef __WIN32__
+# include <io.h>
+# define read _read
+#endif
+
+bool FileBuf::NextBuf () {
+  if (fd < 0) return false;
+  int numbytes = read (fd, buf, FILEBUFSIZE);
+  if (numbytes < 0) numbytes = 0;
+  
+  here = buf;
+  end = here + numbytes;
+
+  return (numbytes > 0);
+}
+
+FileBuf::FileBuf () {
+  here = end = buf;
+  fd = -1;
+}
+
+void FileBuf::SetFD (int _fd) {
+  here = end = buf;
+  fd = _fd;
+}
+
Index: /indexers/branches/3.03a/mgpp/text/FileBuf.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/FileBuf.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/FileBuf.h	(revision 14757)
@@ -0,0 +1,73 @@
+/**************************************************************************
+ *
+ * FileBuf.h -- File buffer
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef FILEBUF_H
+#define FILEBUF_H
+
+#define FILEBUFSIZE 65536
+
+// some elderly windows compilers need to include <vector> (or something
+// similar) here so that they know what a "bool" is
+#if defined(GSDL_USE_OBJECTSPACE)
+#  include <ospace\std\vector>
+#elif defined(GSDL_USE_STL_H)
+#  include <vector.h>
+#else
+#  include <vector>
+#endif
+
+
+class FileBuf {
+protected:
+  unsigned char buf[FILEBUFSIZE];
+  unsigned char *here;
+  unsigned char *end;
+
+  int fd;
+
+  // gets a new buffer if need be, returns true if
+  // more could be got. if true is returned the caller
+  // can assume that here != end
+  bool NextBuf ();
+  
+public:
+  FileBuf ();
+
+  void SetFD (int _fd);
+
+  inline bool Get (unsigned char &c) {
+    if (here != end || NextBuf()) { c = *here++; return true; }
+    return false;
+  }
+  
+  inline bool Peek (unsigned char &c) {
+    if (here != end || NextBuf()) { c = *here; return true; }
+    return false;
+  }
+
+  inline bool Next () {
+    if (here != end || NextBuf()) { ++here; return true; }
+    return false;
+  }
+};
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/FragLevelConvert.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/FragLevelConvert.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/FragLevelConvert.cpp	(revision 14757)
@@ -0,0 +1,105 @@
+/**************************************************************************
+ *
+ * FragLevelConvert.cpp -- converting between fragment and document numbers
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "FragLevelConvert.h"
+#include "bitio_m_stdio.h"
+#include "bitio_gen.h"
+
+
+FragLevelConvert::FragLevelConvert () {
+  numFrags = 0;
+  numLevelDocs = 0;
+}
+
+bool FragLevelConvert::Read (FILE *invfFile,
+			     unsigned long levelPtr,
+			     unsigned long _numFrags,
+			     unsigned long _numLevelDocs) {
+  levelStarts.erase (levelStarts.begin(), levelStarts.end());
+  numFrags = _numFrags;
+  numLevelDocs = _numLevelDocs;
+
+  // seek to the appropriate place in the inverted file
+  fseek (invfFile, levelPtr, SEEK_SET);
+
+  stdio_bitio_buffer buffer(invfFile);
+  
+  unsigned long pTag = numLevelDocs*2;
+  unsigned long B = BIO_Bblock_Init (numFrags+pTag, pTag);
+  unsigned long fragNum = 0;
+  unsigned long i;
+  for (i=0; i<numLevelDocs; ++i) {
+    unsigned long delta = buffer.bblock_decode (B, NULL)-1;
+    fragNum += delta;
+
+    levelStarts.push_back (fragNum);
+
+    // ignore end, assume every fragment is in a level
+    delta = buffer.bblock_decode (B, NULL)-1;
+    fragNum += delta;
+  }
+
+  // fragNum would be the starting fragment of the next document
+  // if there was one
+  levelStarts.push_back (fragNum);
+  
+  if (fragNum != _numFrags) {
+    cerr << "last frag num:"<<fragNum<<" != num frags:"<<_numFrags<<endl;
+  } 
+  buffer.done();
+
+  return true;
+}
+
+bool FragLevelConvert::FragToLevel (unsigned long fragNum,
+				    unsigned long &levelDocNum) const {
+  // do binary search for something containing this fragment number
+  unsigned long low = 1, high = numLevelDocs;
+  unsigned long mid;
+
+  while ((mid = (low+high)/2) >= 1 && low <= high) {
+    if (fragNum > levelStarts[mid]) low = mid+1;
+    else if (fragNum <= levelStarts[mid-1]) high = mid-1;
+    else {
+      levelDocNum = mid;
+      return true;
+    }
+  }
+  return false;
+}
+
+
+bool FragLevelConvert::LevelToLevel (FragLevelConvert sectionLevelConvert,
+		 unsigned long levelNum, unsigned long &DocNum) {
+  
+  if (levelNum==1) {
+    DocNum=1;
+    return true;
+  }
+  unsigned long levelfragnum = sectionLevelConvert.levelStarts[levelNum-1]+1;
+
+  if (FragToLevel(levelfragnum, DocNum)) {
+    return true;
+  } 
+  return false;
+  
+
+}
Index: /indexers/branches/3.03a/mgpp/text/FragLevelConvert.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/FragLevelConvert.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/FragLevelConvert.h	(revision 14757)
@@ -0,0 +1,70 @@
+/**************************************************************************
+ *
+ * FragLevelConvert.h -- converting between fragment and document numbers
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef FRAGLEVELCONVERT_H
+#define FRAGLEVELCONVERT_H
+
+#include <stdio.h>
+#include "UCArray.h"
+
+
+/*Notes about levelStarts (kjm18) - this is my interpretation of
+whats going on, feel free to correct this if its wrong.
+
+say you have 5 docs, consisting of fragments:
+1:  1-55
+2: 56-83
+3: 84-106
+4: 107-152
+5: 153-211
+
+then levelStarts would have the values
+0  1  2   3   4   5 
+0  55 83 106 152 211
+
+*/
+class FragLevelConvert {
+protected:
+  // note fragment start is one before before real start
+  vector<unsigned long> levelStarts;
+  unsigned long numFrags;
+  unsigned long numLevelDocs;
+  
+public:
+  FragLevelConvert ();
+
+  bool Read (FILE *invfFile, unsigned long levelPtr,
+	     unsigned long _numFrags, unsigned long _numLevelDocs);
+
+  bool FragToLevel (unsigned long fragNum, unsigned long &levelDocNum) const;
+
+  // this function converts from one level number to another
+  // the FragLevelConvert thats calling the method should be loaded with
+  // the level that you want to convert to, while the sectionLevelConvert
+  // should be loaded with the level converting from.
+  // level Num has the old level, DocNum will be returned with the new
+  // coresponding level
+  bool LevelToLevel (FragLevelConvert sectionLevelConvert,
+		   unsigned long levelNum, unsigned long &DocNum);
+};
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/GSDLQueryLex.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/GSDLQueryLex.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/GSDLQueryLex.cpp	(revision 14757)
@@ -0,0 +1,279 @@
+/**************************************************************************
+ *
+ * GSDLQueryLex.cpp -- Lexical analyser for a simple query language
+ * Copyright (C) 2000  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "GSDLQueryLex.h"
+#include "unitool.h"
+#include "words.h"
+
+inline void AddNChar (UCArray::const_iterator &here,
+		      UCArray &text,
+		      int len) {
+  if (text.capacity() < text.size() + len + 1) {
+    text.reserve(text.size() + len + 1);
+  }
+  while (len > 0) {
+    text.push_back (*here++);
+    --len;
+  }
+}
+
+static bool ParseInteger (UCArray::const_iterator &here,
+			  UCArray::const_iterator end,
+			  LexEl &el) {
+  el.Clear();
+
+  // this version of end is used in unitool
+  //  UCArray::const_iterator endMinus1 = end-1;
+  const unsigned char* endMinus1 = &*(end - 1);
+
+  int charLen;
+  unsigned short c; // one character lookahead
+  charLen = parse_utf8_char (&*here, endMinus1, &c);
+
+  // check for positive or negative
+  bool neg = false;
+  if (c == '+') {
+    AddNChar (here, el.text, charLen);
+    charLen = parse_utf8_char (&*here, endMinus1, &c);
+  } else if (c == '-') {
+    neg = true;
+    AddNChar (here, el.text, charLen);
+    charLen = parse_utf8_char (&*here, endMinus1, &c);
+  }
+
+  // read in number part
+  int numeric=0;
+  el.num = 0;
+  el.lexType = IntegerE;
+  /* stop integers at 4 digits */
+  while (c >= '0' && c <= '9'&& ++numeric<=MAXNUMERIC) {
+    el.num = el.num*10 + c - '0';
+    AddNChar (here, el.text, charLen);
+    charLen = parse_utf8_char (&*here, endMinus1, &c);
+  }
+
+  if (neg) el.num *= -1;
+
+  return (!el.text.empty());
+}
+
+static bool ParsePotentialInteger(UCArray::const_iterator &here,
+				  UCArray::const_iterator end,
+				  LexEl &el) {
+  el.Clear();
+
+  // this version of end is used in unitool
+  //UCArray::const_iterator endMinus1 = end-1;
+  const unsigned char* endMinus1 = &*(end - 1);
+
+  int charLen=0;
+  int length=0;
+  unsigned short c; // one character lookahead
+  charLen = parse_utf8_char (&*here, endMinus1, &c);
+
+  // read in number part
+  int numeric=0;
+  el.num = 0;
+  el.lexType = IntegerE;
+  /* stop integers at 4 digits */
+  while (c >= '0' && c <= '9'&& ++numeric<=MAXNUMERIC) {
+    el.num = el.num*10 + c - '0';
+    AddNChar (here, el.text, charLen);
+    length += charLen;
+    charLen = parse_utf8_char (&*here, endMinus1, &c);
+  }
+  // check the next character -if it is a letter, then have a term, not an integer
+  if (!is_unicode_letter(c)) {
+    // this was just an integer
+    return (!el.text.empty());
+  }
+  // else its a term
+  el.lexType = TermE;
+  el.num = 0;
+  /* this bit taken from ParseIndexWord in words.h*/
+  while (length+charLen<=MAXSTEMLEN && charLen > 0 &&
+	 (is_unicode_letter(c) || (is_unicode_digit(c) &&
+				   ++numeric <= MAXNUMERIC))) {
+    AddNChar (here, el.text, charLen);
+    length += charLen;
+    charLen = parse_utf8_char (&*here, endMinus1, &c);
+  }
+
+  return (!el.text.empty());
+}
+static bool ParseTerm (UCArray::const_iterator &here,
+		       UCArray::const_iterator end,
+		       UCArray &text) {
+  if (here == end)
+    return false;
+
+  //UCArray::const_iterator endMinus1 = end-1;
+  const unsigned char* endMinus1 = &*(end - 1);
+  const unsigned char* new_here = ParseIndexWord (&*here, endMinus1, text);
+  here += (new_here - &*here); // advance iterator by number of chars advanced
+  return !text.empty();
+}
+
+
+bool ParseLexEl (UCArray::const_iterator &here,
+		 UCArray::const_iterator end,
+		 LexEl &el) {
+  el.Clear();
+
+  // strange things can happen if here == end == 0
+  if (here == end)
+    return false;
+  
+  // this version of end is used in unitool
+  //UCArray::const_iterator endMinus1 = end-1;
+  const unsigned char* endMinus1 = &*(end - 1);
+
+  // ignore all white space
+  int charLen;
+  unsigned short c; // one character lookahead
+  charLen = parse_utf8_char (&*here, endMinus1, &c);
+  while (here != end && is_unicode_space (c)) {
+    here += charLen;
+    charLen = parse_utf8_char (&*here, endMinus1, &c);
+  }
+  if (here == end) return false;
+
+  if (c == '(') {
+    el.lexType = OpenBracketE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == ')') {
+    el.lexType = CloseBracketE;
+    AddNChar (here, el.text, charLen);
+    return true;
+
+  } else if (c =='[') {
+    el.lexType = OpenSquareBracketE;
+    AddNChar (here, el.text, charLen);
+    return true;
+  
+  } else if (c ==']') {
+    el.lexType = CloseSquareBracketE;
+    AddNChar (here, el.text, charLen);
+    return true;
+  
+  } else if (c == '\"') {
+    el.lexType = QuoteE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '/') {
+    el.lexType = TermWeightE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '#') {
+    el.lexType = StemMethodE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '*') {
+    el.lexType = StarE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '^') {
+    el.lexType = RangeE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '@') {
+    el.lexType = AtE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == ':') {
+    el.lexType = TagE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c=='&') {
+    el.lexType = AndOpE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '|') {
+    el.lexType = OrOpE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '!') {
+    el.lexType = NotOpE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '+' || c == '-' ) {
+    return  ParseInteger (here, end, el);
+  }
+
+  else if (c >= '0' && c <= '9') {
+    return ParsePotentialInteger (here, end, el);
+  }
+
+  // assume it is a term of some sort
+  if (!ParseTerm (here, end, el.text))  {
+    // parse term returns false if it hasn't parsed anything that is a term
+    // here should be the same as it was before 
+    el.lexType = UnknownE;
+    AddNChar (here, el.text, charLen);
+    return true;
+  }
+  //return false;
+
+  //UCArray AND; SetCStr (AND, "AND");
+  //if (el.text == AND) {
+  if (UCArrayCStrEquals(el.text, "AND")) {
+    el.lexType = AndOpE;
+    return true;
+  }
+  //UCArray OR; SetCStr (OR, "OR");
+  //if (el.text == OR) {
+  if (UCArrayCStrEquals(el.text, "OR")) {
+    el.lexType = OrOpE;
+    return true;
+  }
+  //UCArray NOT; SetCStr (NOT, "NOT");
+  //if (el.text == NOT) {
+  if (UCArrayCStrEquals(el.text, "NOT")) {
+    el.lexType = NotOpE;
+    return true;
+  }
+  UCArray NEAR; SetCStr (NEAR, "NEAR", 4);
+  if (PrefixLen(el.text, NEAR)==4) {
+    el.lexType = NearOpE;
+    return true;
+  }
+  UCArray WITHIN; SetCStr (WITHIN, "WITHIN", 6);
+  if (PrefixLen(el.text, WITHIN)==6) {
+    el.lexType = WithinOpE;
+    return true;
+  }
+  
+  el.lexType = TermE;
+  return true;
+}
+
Index: /indexers/branches/3.03a/mgpp/text/GSDLQueryLex.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/GSDLQueryLex.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/GSDLQueryLex.h	(revision 14757)
@@ -0,0 +1,64 @@
+/**************************************************************************
+ *
+ * GSDLQueryLex.h -- Lexical analyser for a simple query language, for GSDL
+ * Copyright (C) 2000  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef GSDLQUERYLEX_H
+#define GSDLQUERYLEX_H
+
+#include "UCArray.h"
+
+
+// note: white space is ignored
+enum LexType {NoTypeE, OpenBracketE, CloseBracketE, TermE, AndOpE, OrOpE,
+	      NotOpE, NearOpE, WithinOpE, QuoteE, IntegerE, TermWeightE, 
+	      StemMethodE, RangeE, AtE, TagE, OpenSquareBracketE, 
+	      CloseSquareBracketE, StarE, UnknownE};
+
+struct LexEl {
+  LexType lexType;
+  UCArray text;
+  int num; // for IntegerE
+
+  void Clear () {
+    lexType = NoTypeE;
+    UCArrayClear (text);
+    num = 0;
+  }
+  LexEl () { Clear (); }
+};
+
+
+// returns true if another lexical element could be parsed.
+bool ParseLexEl (UCArray::const_iterator &here,
+		 UCArray::const_iterator end,
+		 LexEl &el);
+
+
+#endif
+
+
+
+
+
+
+
+
+
+
Index: /indexers/branches/3.03a/mgpp/text/GSDLQueryParser.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/GSDLQueryParser.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/GSDLQueryParser.cpp	(revision 14757)
@@ -0,0 +1,534 @@
+/**************************************************************************
+ *
+ * QueryParser.cpp -- Query parser for a simple query language
+ * Copyright (C) 2000  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "GSDLQueryParser.h"
+#include "GSDLQueryLex.h"
+#include "words.h"
+
+static QueryNode *ParseExpression (UCArray::const_iterator &here,
+				   UCArray::const_iterator end, 
+				   int defaultBoolCombine,
+				   int defaultStemMethod);
+
+static QueryNode *AndAdd (QueryNode *t1, QueryNode *t2) {
+  if (t1 == NULL) return t2;
+  if (t2 == NULL) return t1;
+
+  AndQueryNode *andNode = new AndQueryNode;
+  andNode->leftNode = t1;
+  andNode->rightNode = t2;
+  return andNode;
+}
+
+static QueryNode *OrAdd (QueryNode *t1, QueryNode *t2) {
+  if (t1 == NULL) return t2;
+  if (t2 == NULL) return t1;
+
+  OrQueryNode *orNode = new OrQueryNode;
+  orNode->leftNode = t1;
+  orNode->rightNode = t2;
+  return orNode;
+}
+
+static QueryNode *NotAdd (QueryNode *t1, QueryNode *t2) {
+  if (t1 == NULL) return t2;
+  if (t2 == NULL) return t1;
+
+  NotQueryNode *notNode = new NotQueryNode;
+  notNode->queryNode = t1;
+  notNode->notNode = t2;
+  return notNode;
+}
+
+// expects the opening bracket to have already been parsed
+// and discarded
+static QueryNode *ParseBracketExpression (UCArray::const_iterator &here,
+					  UCArray::const_iterator end, 
+					  int defaultBoolCombine,
+					  int defaultStemMethod) {
+  // get everything in the expression
+  QueryNode *curTree = ParseExpression (here, end, defaultBoolCombine,
+					defaultStemMethod);
+  
+  // gobble up tokens until a closing bracket is found
+  // or the end of the string
+  LexEl el;
+  while (ParseLexEl (here, end, el)) {
+    if (el.lexType == CloseBracketE) break;
+  }
+
+  return curTree;
+}
+
+static int ParseInt (UCArray::const_iterator &here,
+		     UCArray::const_iterator end) {
+  LexEl el;
+  UCArray::const_iterator oldHere = here;
+  if (ParseLexEl (here, end, el) && el.lexType == IntegerE)
+    return el.num;
+  
+  here = oldHere; // not an integer
+  return 0;
+}
+
+// default is within 20 words
+static void SetRangeValues (TermNode &termNode,
+			    UCArray &nearby,
+			    bool reverse) {
+  UCArray NEARBY; SetCStr(NEARBY, "NEAR", 4);
+  UCArray WITHIN; SetCStr(WITHIN, "WITHIN", 6);
+  
+  if (nearby == NEARBY) { // no modifier
+    termNode.startRange = (NEAR_DEFAULT+1)*-1;
+    termNode.endRange = NEAR_DEFAULT;
+
+  } else if (nearby == WITHIN) { // no modifier
+    if (reverse) {
+      termNode.startRange = (NEAR_DEFAULT+1)*-1;
+      termNode.endRange = -1;
+    } else {
+      termNode.startRange = NEAR_DEFAULT;
+      termNode.endRange = 0;
+    }
+  }
+  else { // extract number
+    UCArray::const_iterator here;
+    bool within = false;
+    if (PrefixLen(nearby, WITHIN)==6) {
+      within=true;
+      here = nearby.begin()+6;
+    } else {
+      here = nearby.begin()+4;
+    }
+    UCArray::const_iterator end = nearby.end();
+    int size=0;
+    while (here != end) {
+      size = size*10 + (*here-'0');
+      ++here;
+    }
+    if (within) {
+      if (reverse) {
+	termNode.startRange = size;
+	termNode.endRange = 0;
+      } else {
+	termNode.startRange = -1 * (size+1);
+	termNode.endRange = -1;
+      }
+    } else {
+      termNode.startRange = -1 * (size+1);
+      termNode.endRange = size;
+    }
+  }
+}
+
+static unsigned long GetStemMethod(LexEl &el, int defaultStemMethod) {
+  // here expect el to contain some of c,s,i,u,f,a -- see mg_files.h CHAR_FLAG_STEM_* constants
+  unsigned long stem = (unsigned long)defaultStemMethod;
+      
+  UCArray::const_iterator here = el.text.begin();
+  UCArray::const_iterator end = el.text.end();
+
+  /* [JFG - Mar 06: Accent folding patch] */
+  /* Changed to use CHAR_FLAG_STEM* constants from mg_files.h */
+  while(here != end) {
+    unsigned char ch = *here; 
+    if (strchr (CHAR_FLAG_STEM_Validator, ch) == NULL)
+      return STEM_INVALID; // incorrect format
+    
+    switch(ch) {
+    case CHAR_FLAG_STEM_CaseFold:		// ignore case (fold)
+      stem |= STEM_CaseFolding;
+      break;
+    case CHAR_FLAG_STEM_NoCaseFold:		// case sensitive 
+      stem &= (~STEM_CaseFolding);
+      break;
+    case CHAR_FLAG_STEM_Stemming:		// stem words
+      stem |= STEM_Stemming;
+      break;
+    case CHAR_FLAG_STEM_NoStemming:		// do not stem words
+      stem &= (~STEM_Stemming);
+      break;
+#ifdef ENABLE_ACCENTFOLD 
+   case CHAR_FLAG_STEM_AccentFold:		// accent fold
+      stem |= STEM_AccentFolding;
+      break;
+    case CHAR_FLAG_STEM_NoAccentFold:	// do no accent folding
+      stem &= (~STEM_AccentFolding);
+      break;
+#endif
+    };
+    
+    ++here;	    
+  }
+  return stem;
+}
+  
+
+static void ParseTermModifiers (UCArray::const_iterator &here,
+				UCArray::const_iterator end,
+				TermNode &termNode,
+				int defaultStemMethod) {
+ 
+  termNode.stemMethod = defaultStemMethod;
+  bool partial_match = false;
+  LexEl el;
+  UCArray::const_iterator oldHere = here;
+  while (ParseLexEl (here, end, el)) {
+    if (el.lexType == TermWeightE) {
+      termNode.termWeight = ParseInt (here, end);
+      
+    } else if (el.lexType == StemMethodE) {
+      oldHere = here;
+      LexEl stem;
+      if (ParseLexEl (here, end, stem) && stem.lexType == TermE) {
+	termNode.stemMethod = GetStemMethod(stem, defaultStemMethod);
+    /* [JFG - Mar 06: Accent folding patch] */
+    /* use STEM_INVALID instead of hardcoded 4 */
+	if (termNode.stemMethod == STEM_INVALID) { // error so backtrack
+	  here = oldHere;
+	  termNode.stemMethod = (unsigned long)defaultStemMethod;
+	} 
+      } else here = oldHere; //ignore - wrong syntax
+
+    } else if (el.lexType == RangeE) {
+      termNode.startRange = ParseInt (here, end);
+      termNode.endRange = ParseInt (here, end);
+      
+    } else if (el.lexType == AtE) {
+      termNode.startRange = termNode.endRange = ParseInt (here, end);
+    } else if (el.lexType == StarE) {
+      partial_match = true;
+    } else {
+      // no term modifiers
+      here = oldHere;
+      break;
+    }
+    
+    if (partial_match) {
+      /* [JFG - Mar 06: Accent folding patch] */
+      /* use STEM_PARTIAL_MATCH flag */
+      termNode.stemMethod |= STEM_PARTIAL_MATCH; // set partial match flag
+      termNode.stemMethod &= (~STEM_Stemming); // we dont have stemming on if doing partial matching.
+      termNode.stemMethod &= (~STEM_AccentFolding); // we dont have accentfolding on if doing partial matching.
+    }
+    oldHere = here;
+  }  
+}
+
+static void ParseProxModifiers (UCArray::const_iterator &here,
+				UCArray::const_iterator end,
+				ProxMatchQueryNode *proxNode) {
+  // so far only have one - the tag stuff
+  LexEl el;
+  UCArray::const_iterator oldHere = here;
+  while (ParseLexEl (here, end, el)) {
+    if (el.lexType == TagE) {
+      oldHere = here; // don't backtrack past here
+      if (ParseLexEl (here, end, el) && el.lexType == TermE) {
+	proxNode->tagNodePtr = new TagNode;
+	proxNode->tagNodePtr->tagName = el.text;
+	
+      }
+      else { // error in tag
+	here = oldHere;
+      }
+    } // TagE
+    // add in other cases here
+    else {
+      // no modifiers
+      here = oldHere;
+      break;
+    }
+    oldHere = here;
+  }//while
+
+
+}
+
+// expects starting brackets to have been parsed
+// sets error to true if something has gone wrong
+static ProxMatchQueryNode *ParseSquareBrackets(UCArray::const_iterator &here,
+				UCArray::const_iterator end,
+				/*ProxMatchQueryNode *proxNode,*/
+				int defaultStemMethod,
+				bool & error) {
+
+  ProxMatchQueryNode *proxNode = new ProxMatchQueryNode;
+  LexEl el;
+  bool phrase=false;
+  bool first=true;
+  bool prox = false;
+  UCArray near_string;
+  while (ParseLexEl (here, end, el)) {
+    // cant have AND, OR, NOT in square brackets, so assume they are words
+    if (el.lexType == TermE || el.lexType == IntegerE || el.lexType == AndOpE || el.lexType == OrOpE || el.lexType == NotOpE) {
+      TermNode termNode;
+      termNode.term = el.text;
+      ParseTermModifiers (here, end, termNode, defaultStemMethod);
+      if (phrase) {
+        if (first) first=false;
+        else {
+          termNode.startRange = -2;
+          termNode.endRange = -1;
+        }
+      } else if (prox) {
+	SetRangeValues(termNode, near_string, false);
+	prox = false;
+      }
+      proxNode->terms.push_back(termNode);
+    }
+    else if (el.lexType == CloseSquareBracketE) {
+      break;
+    }
+    else if (el.lexType == QuoteE) {
+      // phrase inside square brackets
+      if (phrase) { // end of phrase
+	phrase=false;
+	first = true;
+      } else {
+	phrase=true; // start of phrase
+      }
+    } else if (el.lexType == NearOpE || el.lexType == WithinOpE) {
+      if (phrase) {
+	// cant have proximity  op in a phrase - just assume its an actual word
+	TermNode termNode;
+	termNode.term = el.text;
+	ParseTermModifiers (here, end, termNode, defaultStemMethod);
+	proxNode->terms.push_back(termNode);
+      } else {
+	// its a NEAR or within op
+	prox = true;
+	near_string = el.text;
+      }
+	  
+    } 
+    else if (el.lexType == UnknownE) {
+      // just ignore it 
+    }
+    else {
+      //error - we set the proxNode to NULL,
+      cerr <<"GSDLQueryParser: bad syntax inside []\n";
+      error = true;
+      return NULL;
+    }
+  } // while
+  return proxNode;
+}
+// expects the starting quote to have been parsed
+// and discarded
+// now phrases use the case and stem preference options
+// ie can search for a phrase ignoring case
+static void ParsePhrase (UCArray::const_iterator &here,
+			 UCArray::const_iterator end,
+			 ProxMatchQueryNode &proxNode, 
+			 int defaultStemMethod,
+			 bool &error) {
+  LexEl el;
+  bool first = true;
+  while (ParseLexEl (here, end, el)) {
+    if (el.lexType == TermE || el.lexType == IntegerE) {
+      TermNode termNode;
+      termNode.term = el.text;
+      //termNode.stemMethod = defaultStemMethod;
+      ParseTermModifiers (here, end, termNode, defaultStemMethod);
+      if (first) {
+	first = false;
+      }
+      else {
+	termNode.startRange = -2;
+	termNode.endRange = -1;
+      }
+      proxNode.terms.push_back (termNode);
+      
+    } else if (el.lexType == QuoteE) {
+      break;
+      
+    } else if (el.lexType == UnknownE) {
+      // just ignore it
+    } else {
+      // error 
+      error = true;
+      return;
+    }
+  }
+}
+
+static QueryNode *ParseTerm (UCArray::const_iterator &here,
+			     UCArray::const_iterator end,
+			     int defaultBoolCombine,
+			     int defaultStemMethod) {
+  LexEl el;
+
+  UCArray::const_iterator oldHere = here;
+  if (!ParseLexEl (here, end, el)) return NULL;
+
+  if (el.lexType == OpenBracketE)
+    return ParseBracketExpression (here, end, defaultBoolCombine,
+				   defaultStemMethod);
+
+  ProxMatchQueryNode *proxNode = new ProxMatchQueryNode;
+
+  if (el.lexType == TermE || el.lexType == IntegerE) {
+    TermNode termNode;
+    termNode.term = el.text;
+    ParseTermModifiers (here, end, termNode, defaultStemMethod);
+    oldHere = here;  // dont backtrack past here
+    if (ParseLexEl(here, end, el) && (el.lexType == NearOpE || el.lexType == WithinOpE )) {
+	delete proxNode;
+	oldHere = here;
+      // this is calling ParseTerm again, but only a subset of the things accepted by ParseTerm are appropriate here. add in some hacks to avoid segmentation faults - kjdon, 04/2003
+      
+      // if the next element is a '(' have a syntax error, return NULL 
+      LexEl temp_el;
+      if (ParseLexEl(here, end, temp_el) && temp_el.lexType == OpenBracketE) {
+	cerr << "GSDLQueryParser: NEAR/WITHIN cannot be followed by a '('\n";
+	return NULL;
+      }
+      here = oldHere; // else backtrack
+	
+      proxNode = (ProxMatchQueryNode *)ParseTerm(here, end, defaultBoolCombine,
+						 defaultStemMethod);
+      SetRangeValues(termNode, el.text, true);
+      proxNode->terms.push_back (termNode);
+      return proxNode;
+      
+    } else {
+      here = oldHere; // backtrack
+      proxNode->terms.push_back (termNode);
+      ParseProxModifiers(here, end, proxNode);
+      return proxNode;
+    }
+  } else if (el.lexType == QuoteE) {
+    bool error = false;
+    ParsePhrase (here, end, *proxNode, defaultStemMethod, error);
+    if (error) {
+      delete proxNode;
+      return NULL;
+    }
+    return proxNode;
+  }
+  else if (el.lexType == OpenSquareBracketE) {
+    bool error = false;
+    proxNode = ParseSquareBrackets (here, end, /*proxNode, */defaultStemMethod, error);
+    if (error) {
+      delete proxNode;
+      return NULL;
+    }
+    ParseProxModifiers (here, end, proxNode);
+    return proxNode;
+  }
+
+  // not a term
+  here = oldHere;
+  delete proxNode;
+  return NULL;
+}
+
+
+static QueryNode *ParseExpression (UCArray::const_iterator &here,
+				   UCArray::const_iterator end,
+				   int defaultBoolCombine,
+				   int defaultStemMethod) {
+  LexEl el;
+  QueryNode *curTree = NULL;
+  UCArray::const_iterator oldHere = here;
+  while (ParseLexEl (here, end, el)) {
+    if (el.lexType == CloseBracketE) {
+      // parsebracketexpression is waiting for the last bracket, so put it back
+      here = oldHere;
+      break;
+      
+    } else if (el.lexType == OpenSquareBracketE ||
+	       el.lexType == OpenBracketE ||
+	       el.lexType == TermE ||
+	       el.lexType == QuoteE ||
+	       el.lexType == IntegerE ) { 
+      
+      // some type of term, back track and parse it
+      here = oldHere;
+
+      //  parse the term
+      QueryNode * newTerm = ParseTerm (here, end, defaultBoolCombine, 
+				       defaultStemMethod);
+      if (newTerm == NULL) {
+	delete curTree;
+	return NULL;
+      }
+
+      // if default==1, AND, else if==0, OR
+      if (defaultBoolCombine) {
+	curTree = AndAdd (curTree, newTerm);
+      }
+      else {
+	curTree = OrAdd (curTree, newTerm); 
+      }
+      
+    } else if (el.lexType == AndOpE) {
+      QueryNode * newTerm = ParseTerm (here, end, defaultBoolCombine,
+				       defaultStemMethod);
+      if (newTerm == NULL) {
+	delete curTree;
+	return NULL;
+      }
+      curTree = AndAdd (curTree, newTerm);
+      
+    } else if (el.lexType == OrOpE) {
+      QueryNode * newTerm = ParseTerm (here, end, defaultBoolCombine,
+				       defaultStemMethod);
+      if (newTerm == NULL) {
+	delete curTree;
+	return NULL;
+      }
+      curTree = OrAdd (curTree, newTerm);
+      
+    } else if (el.lexType == NotOpE) {
+      QueryNode * newTerm = ParseTerm (here, end, defaultBoolCombine,
+				       defaultStemMethod);
+      if (newTerm == NULL) {
+	delete curTree;
+	return NULL;
+      }
+      curTree = NotAdd (curTree, newTerm); 
+      
+    } else if (el.lexType == UnknownE) {
+      // just ignore it 
+    } else {
+
+      // syntax error, return NUll
+      delete curTree;
+      return NULL;
+    }
+
+    oldHere = here;
+  }
+
+  return curTree;
+}
+
+QueryNode *ParseQuery (const UCArray &queryStr, int defaultBoolCombine,
+		       int defaultStemMethod, int maxnumeric) {
+  if (4 < maxnumeric && maxnumeric < 512) {
+    MAXNUMERIC = maxnumeric;
+  }
+  UCArray::const_iterator here = queryStr.begin();
+  UCArray::const_iterator end = queryStr.end();
+  return ParseExpression (here, end, defaultBoolCombine, defaultStemMethod);
+}
Index: /indexers/branches/3.03a/mgpp/text/GSDLQueryParser.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/GSDLQueryParser.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/GSDLQueryParser.h	(revision 14757)
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * QueryParser.h -- Query parser for a simple query language
+ * Copyright (C) 2000  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef GSDLQUERYPARSER_H
+#define GSDLQUERYPARSER_H
+
+#include "UCArray.h"
+#include "MGQuery.h"
+
+#define NEAR_DEFAULT 20
+
+// returns NULL if the query could not be parsed
+// defaultBoolCOmbine determines if individual terms are combined using
+// AND or OR in the absence of specified operators.
+// defaultStemMethod used to set stemming and casefolding for terms where
+// its not set explicitly in the query string. THe defaultStemMethod value
+// should be set using the values from the preferences page
+QueryNode *ParseQuery (const UCArray &queryStr, int defaultBoolCombine,
+		       int defaultStemMethod, int maxnumeric);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/IndexData.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/IndexData.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/IndexData.cpp	(revision 14757)
@@ -0,0 +1,204 @@
+/**************************************************************************
+ *
+ * IndexData.cpp -- Information needed for querying
+ * Copyright (C) 1999 Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "IndexData.h"
+#include "string.h"
+#include "mg_files.h"
+
+IndexData::IndexData () {
+  basePath[0] = '\0';
+  filename[0] = '\0';
+
+  dictFile = NULL;
+
+  /* [JFG - Mar 06: Accent folding patch] */
+  for(int i=STEM_MIN;i <= STEM_MAX;i++) 
+    stemFile[i-1] = NULL;
+
+  invfFile = NULL;
+
+  approxWeightsFile = NULL;
+  exactWeightsFile = NULL;
+
+  curLevelNum = 0;
+}
+
+IndexData::~IndexData () {
+  UnloadData ();
+}
+
+bool IndexData::LoadData (const char *_basePath, const char *_filename) {
+  if (_filename[0] == '\0') return false;
+  
+  // make sure this data has not already been loaded
+  if (strcmp (_basePath, basePath) == 0 &&
+      strcmp (_filename, filename) == 0) return true;
+  
+  // make sure there is nothing else loaded
+  UnloadData ();
+
+  strcpy (basePath, _basePath);
+  strcpy (filename, _filename);
+
+  set_basepath (basePath);
+
+  // load in the level information
+  FILE *ivfLevelFile;
+  ivfLevelFile = open_file (filename, INVF_LEVEL_SUFFIX, "rb",
+			    MAGIC_INVF_LEVELS, MG_ABORT);
+  levels.Read (ivfLevelFile);
+  fclose (ivfLevelFile);
+
+  // blocked dictionary
+  dictFile = open_file (filename, INVF_DICT_BLOCKED_SUFFIX, "rb",
+			MAGIC_STEM, MG_ABORT);
+  if (!bdh.Read (dictFile)) { UnloadData (); return false; }
+
+  fseek (dictFile, bdh.wblk_idx_start, SEEK_SET);
+  if (!ReadBlockIdx (dictFile, biWords)) { UnloadData (); return false; }
+
+  fseek (dictFile, bdh.tblk_idx_start, SEEK_SET);
+  if (!ReadBlockIdx (dictFile, biTags)) { UnloadData (); return false; }
+
+  /* [JFG - Mar 06: Accent folding patch] */
+  // read stem indexes
+  // [KJD - optional stemming patch]
+  // allow no stem indexes
+  for(int stem = STEM_MIN; stem <= STEM_MAX; stem++) { 
+    char *suffix = make_suffix (INVF_DICT_BLOCKED_SUFFIX_PAT, stem, NULL);
+    stemFile[stem-1] = open_file (filename, suffix,
+				  "rb", MAGIC_STEM_GEN(stem + '0'), MG_MESSAGE);
+    if (stemFile[stem-1]!= NULL) {
+      if (!sih[stem-1].Read (stemFile[stem-1])) { 
+	fclose (stemFile[stem-1]);
+	stemFile[stem-1] = NULL;
+	//UnloadData (); return false; 
+      }
+      
+      fseek (stemFile[stem-1], sih[stem-1].block_idx_start, SEEK_SET);
+      if (!ReadBlockIdx (stemFile[stem-1], sii[stem-1])) { 
+	fclose (stemFile[stem-1]);
+	stemFile[stem-1] = NULL;
+	//UnloadData (); return false; 
+      }
+    }
+  }
+  
+  
+  // inverted file
+  invfFile = open_file (filename, INVF_SUFFIX, "rb",
+			MAGIC_INVF, MG_ABORT);
+  ifh.Read (invfFile);
+
+  // weights
+  approxWeightsFile = open_file (filename, APPROX_WEIGHTS_SUFFIX, "rb",
+				 MAGIC_WGHT_APPROX, MG_ABORT);
+  exactWeightsFile = open_file (filename, WEIGHTS_SUFFIX, "rb",
+				MAGIC_WGHT, MG_ABORT);
+
+  return true;
+}
+
+bool IndexData::UnloadData () {
+  basePath[0] = '\0';
+  filename[0] = '\0';
+
+  if (dictFile != NULL) {
+    fclose (dictFile); dictFile = NULL;
+  }
+
+  for(int i=STEM_MIN;i <= STEM_MAX;i++) {
+    if (stemFile[i-1] != NULL) {
+      fclose (stemFile[i-1]); stemFile[i-1] = NULL;
+    }
+  }
+
+  if (invfFile != NULL) {
+    fclose (invfFile); invfFile = NULL;
+  }
+
+  if (approxWeightsFile != NULL) {
+    fclose (approxWeightsFile); approxWeightsFile = NULL;
+  }
+  if (exactWeightsFile != NULL) {
+    fclose (exactWeightsFile); exactWeightsFile = NULL;
+  }
+
+  UnloadLevel();
+  
+  return true;
+}
+
+
+bool IndexData::LoadLevel (const UCArray &level) {
+  // make sure this level is not already loaded
+  if (level == curLevel) return true;
+
+  // unload any levels currently loaded
+  UnloadLevel();
+
+  // make sure the required files are open
+  if (dictFile == NULL || invfFile == NULL ||
+      approxWeightsFile == NULL || exactWeightsFile == NULL)
+    return false;
+  
+  // read in the information from the dictionary
+  block_dict_el tagEl;
+  unsigned long tagElNum;
+  if (!SearchBlockDictEl (dictFile, biTags, bdh.entries_per_tblk,
+			  bdh.tag_dict_size, level, tagEl, tagElNum))
+    return false;
+
+  // read in the level conversion information
+  if (!levelConverter.Read (invfFile, tagEl.invf_ptr,
+			    bdh.num_frags, tagEl.frag_occur))
+    return false;
+
+  // read in the approximate weights
+  if (!weightData.Read (approxWeightsFile,
+			levels.levelInfo[level].approxWeightsDiskPtr,
+			levels.levelInfo[level].numEntries))
+    return false;
+  
+  // find the level number
+  curLevelNum = 0;
+  IvfLevelInfoMap::const_iterator levelHere, levelEnd;
+  for (levelHere=levels.levelInfo.begin(), levelEnd=levels.levelInfo.end();
+       levelHere!=levelEnd && (*levelHere).first != level; ++levelHere)
+    ++curLevelNum;
+
+  // make sure we found the level
+  if (levelHere == levelEnd) return false;
+
+  curLevel = level;
+
+  return true;
+}
+
+bool IndexData::UnloadLevel () {
+  curLevel.erase (curLevel.begin(), curLevel.end());
+  curLevelNum = 0;
+  
+  weightData.Free ();
+    
+  return true;
+}
+
Index: /indexers/branches/3.03a/mgpp/text/IndexData.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/IndexData.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/IndexData.h	(revision 14757)
@@ -0,0 +1,77 @@
+/**************************************************************************
+ *
+ * IndexData.h -- Information needed for querying
+ * Copyright (C) 1999 Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef INDEXDATA_H
+#define INDEXDATA_H
+
+#include <stdio.h>
+#include "invf.h"
+#include "FIvfLevelInfo.h"
+#include "FragLevelConvert.h"
+#include "Weights.h"
+#include "stemmer.h" 
+
+class IndexData {
+public:
+  // general information
+  char basePath[FILENAME_MAX];
+  char filename[FILENAME_MAX];
+  FIvfLevel levels;
+  
+  // blocked dictionary
+  FILE *dictFile;
+  block_dict_header bdh;
+  block_idx biWords;
+  block_idx biTags;
+
+  /* [JFG - Mar 06: Accent folding patch] */
+  // stem indexes
+  FILE *stemFile[STEM_MAX]; 
+  stem_idx_header sih[STEM_MAX];
+  block_idx sii[STEM_MAX];
+ 
+  // inverted file
+  FILE *invfFile;
+  invf_file_header ifh;
+
+  // weights
+  FILE *approxWeightsFile;
+  FILE *exactWeightsFile;
+
+  // level specific information
+  UCArray curLevel; // last level that was loaded
+  unsigned long curLevelNum;
+  FragLevelConvert levelConverter;
+  ApproxWeightsData weightData;
+  
+  IndexData ();
+  ~IndexData ();
+
+  // LoadData will only load the data if it has not been loaded before
+  bool LoadData (const char *_basePath, const char *_filename);
+  bool UnloadData ();
+
+  bool LoadLevel (const UCArray &level);
+  bool UnloadLevel ();
+};
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/MGQuery.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/MGQuery.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/MGQuery.cpp	(revision 14757)
@@ -0,0 +1,760 @@
+/**************************************************************************
+ *
+ * MGQuery.cpp -- Query related functions
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "MGQuery.h"
+#include "bitio_m_stdio.h"
+#include "bitio_gen.h"
+#include "Terms.h"
+#include "QueryResultsSort.h"
+#include <assert.h>
+
+
+void PrintIndent (ostream &s, int indent) {
+  while (indent-- > 0) s << " ";
+}
+
+
+void PrintIndentText (ostream &s, char *text, int indent) {
+  PrintIndent (s, indent);
+  s << text;
+}
+
+void PrintNode (ostream &s, QueryNode *node, int indent) {
+  if (node == NULL) {
+    PrintIndentText (s, "NULL\n", indent);
+  } else {
+    node->Print (s, indent+2);
+  }
+}
+
+  
+
+QueryNode::QueryNode () {
+}
+
+QueryNode::~QueryNode () {
+}
+
+void QueryNode::Calculate (IndexData &/*indexData*/,
+			   const QueryInfo &/*queryInfo*/,
+			   QueryResult &result) const {
+  result.Clear();
+}
+
+void QueryNode::Free () {
+}
+
+void QueryNode::Print (ostream &/*s*/, int /*indent*/) const {
+}
+
+
+
+AndQueryNode::AndQueryNode () {
+  leftNode = NULL;
+  rightNode = NULL;
+}
+
+AndQueryNode::~AndQueryNode () {
+  Free ();
+}
+
+void AndQueryNode::Calculate (IndexData &indexData, const QueryInfo &queryInfo,
+			      QueryResult &result) const {
+  result.Clear();
+
+  // an And between nothing and something is nothing...
+  if (leftNode == NULL || rightNode == NULL) return;
+  
+  // calculate the result from the left tree and the result
+  // from the right tree
+  QueryResult rightResult;
+  leftNode->Calculate (indexData, queryInfo, result);
+  rightNode->Calculate (indexData, queryInfo, rightResult);
+
+  // merge the results, this can be done in place as the results
+  // will always shrink with an And
+
+  bool haveAccum = (queryInfo.sortByRank || queryInfo.needRankInfo);
+  if (haveAccum && (result.ranks.size() != result.docs.size() ||
+		    rightResult.ranks.size() != rightResult.docs.size())) {
+    // shouldn't ever get here
+    haveAccum = false;
+    assert (0);
+  }
+
+  // combine document numbers and corresponding ranks
+  unsigned long leftI = 0;
+  unsigned long rightI = 0;
+  unsigned long outI = 0;
+  while (leftI < result.docs.size() &&
+	 rightI < rightResult.docs.size()) {
+    if (result.docs[leftI] < rightResult.docs[rightI]) {
+      ++leftI;
+    } else if (result.docs[leftI] > rightResult.docs[rightI]) {
+      ++rightI;
+    } else {
+      // the documents are equal
+      result.docs[outI] = result.docs[leftI];
+      if (haveAccum)
+	result.ranks[outI] = result.ranks[leftI] + rightResult.ranks[rightI];
+      ++leftI;
+      ++rightI;
+      ++outI;
+    }
+  }
+
+  // erase unused document numbers and ranks
+  result.docs.erase(result.docs.begin()+outI, result.docs.end());
+  if (haveAccum)
+    result.ranks.erase(result.ranks.begin()+outI, result.ranks.end());
+    
+  // combine term frequency information
+  if (queryInfo.needTermFreqs)
+    result.termFreqs.insert (result.termFreqs.end(),
+			     rightResult.termFreqs.begin(),
+			     rightResult.termFreqs.end());
+}
+
+void AndQueryNode::Free () {
+  if (leftNode != NULL) {
+    delete leftNode;
+    leftNode = NULL;
+  }
+  if (rightNode != NULL) {
+    delete rightNode;
+    rightNode = NULL;
+  }
+}
+
+void AndQueryNode::Print (ostream &s, int indent) const {
+  PrintIndentText (s, "leftNode:\n", indent);
+  PrintNode (s, leftNode, indent+2);
+  PrintIndentText (s, "AND\n", indent);
+  PrintIndentText (s, "rightNode:\n", indent);
+  PrintNode (s, rightNode, indent+2);
+}
+
+
+OrQueryNode::OrQueryNode () {
+  leftNode = NULL;
+  rightNode = NULL;
+}
+
+OrQueryNode::~OrQueryNode () {
+  Free ();
+}
+
+void OrQueryNode::Calculate (IndexData &indexData, const QueryInfo &queryInfo,
+			      QueryResult &result) const {
+  result.Clear();
+  
+  // calculate the result from the left tree and the result
+  // from the right tree
+  QueryResult leftResult;
+  QueryResult rightResult;
+  if (leftNode != NULL)
+    leftNode->Calculate (indexData, queryInfo, leftResult);
+  if (rightNode != NULL)
+    rightNode->Calculate (indexData, queryInfo, rightResult);
+
+  // merge the results
+  
+  bool haveAccum = (queryInfo.sortByRank || queryInfo.needRankInfo);
+  if (haveAccum && (leftResult.ranks.size() != leftResult.docs.size() ||
+		    rightResult.ranks.size() != rightResult.docs.size())) {
+    // shouldn't ever get here
+    haveAccum = false;
+    assert (0);
+  }
+
+  // combine document numbers and corresponding ranks
+  unsigned long leftSize = leftResult.docs.size();
+  unsigned long rightSize = rightResult.docs.size();
+  unsigned long leftI = 0;
+  unsigned long rightI = 0;
+  unsigned long leftDocNum = 0;
+  unsigned long rightDocNum = 0;
+  while (leftI < leftSize || rightI < rightSize) {
+    // check leftI
+    if (leftI < leftResult.docs.size())
+      leftDocNum = leftResult.docs[leftI];
+    else leftDocNum = ULONG_MAX;
+    
+    // check rightI
+    if (rightI < rightResult.docs.size())
+      rightDocNum = rightResult.docs[rightI];
+    else rightDocNum = ULONG_MAX;
+    
+    // combine
+    if (leftDocNum < rightDocNum) {
+      result.docs.push_back (leftDocNum);
+      if (haveAccum)
+	result.ranks.push_back (leftResult.ranks[leftI]);
+      ++leftI;
+      
+    } else if (leftDocNum > rightDocNum) {
+      result.docs.push_back (rightDocNum);
+      if (haveAccum)
+	result.ranks.push_back (rightResult.ranks[rightI]);
+      ++rightI;
+      
+    } else { // equal
+      result.docs.push_back (leftDocNum);
+      if (haveAccum)
+	result.ranks.push_back (leftResult.ranks[leftI] +
+				rightResult.ranks[rightI]);
+      ++leftI;
+      ++rightI;
+    }
+  }
+
+  // combine term frequency information
+  if (queryInfo.needTermFreqs) {
+    result.termFreqs.insert (result.termFreqs.end(),
+			     leftResult.termFreqs.begin(),
+			     leftResult.termFreqs.end());
+    result.termFreqs.insert (result.termFreqs.end(),
+			     rightResult.termFreqs.begin(),
+			     rightResult.termFreqs.end());
+  }
+}
+
+void OrQueryNode::Free () {
+  if (leftNode != NULL) {
+    delete leftNode;
+    leftNode = NULL;
+  }
+  if (rightNode != NULL) {
+    delete rightNode;
+    rightNode = NULL;
+  }
+}
+
+void OrQueryNode::Print (ostream &s, int indent) const {
+  PrintIndentText (s, "leftNode:\n", indent);
+  PrintNode (s, leftNode, indent+2);
+  PrintIndentText (s, "OR\n", indent);
+  PrintIndentText (s, "rightNode:\n", indent);
+  PrintNode (s, rightNode, indent+2);
+}
+
+
+
+NotQueryNode::NotQueryNode () {
+  queryNode = NULL;
+  notNode = NULL;
+}
+
+NotQueryNode::~NotQueryNode () {
+  Free ();
+}
+
+void NotQueryNode::Calculate (IndexData &indexData, const QueryInfo &queryInfo,
+			      QueryResult &result) const {
+  result.Clear();
+
+  // check for nothing
+  if (queryNode == NULL) return;
+  if (notNode == NULL) {
+    queryNode->Calculate (indexData, queryInfo, result);
+    return;
+  }
+  
+  // calculate the result from the query tree and the result
+  // from the not tree
+  QueryResult notResult;
+  queryNode->Calculate (indexData, queryInfo, result);
+  notNode->Calculate (indexData, queryInfo, notResult);
+
+  // merge the results, this can be done in place as the results
+  // will always shrink with a Not
+
+  bool haveAccum = (queryInfo.sortByRank || queryInfo.needRankInfo);
+  if (haveAccum && (result.ranks.size() != result.docs.size() ||
+		    notResult.ranks.size() != notResult.docs.size())) {
+    // shouldn't ever get here
+    haveAccum = false;
+    assert (0);
+  }
+
+  // combine document numbers and corresponding ranks
+  unsigned long queryI = 0;
+  unsigned long notI = 0;
+  unsigned long outI = 0;
+  while (queryI < result.docs.size() &&
+	 notI < notResult.docs.size()) {
+    if (result.docs[queryI] < notResult.docs[notI]) {
+      // found a document not in the notResults
+      result.docs[outI] = result.docs[queryI];
+      if (haveAccum)
+	result.ranks[outI] = result.ranks[queryI];
+      ++queryI;
+      ++outI;
+    } else if (result.docs[queryI] > notResult.docs[notI]) {
+      ++notI;
+    } else {
+      // the documents are equal, ignore both
+      ++queryI;
+      ++notI;
+    }
+  }
+
+  // erase unused document numbers and ranks
+  result.docs.erase(result.docs.begin()+outI, result.docs.end());
+  if (haveAccum)
+    result.ranks.erase(result.ranks.begin()+outI, result.ranks.end());
+  
+  // combine term frequency information
+  if (queryInfo.needTermFreqs)
+    result.termFreqs.insert (result.termFreqs.end(),
+			     notResult.termFreqs.begin(),
+			     notResult.termFreqs.end());
+}
+
+void NotQueryNode::Free () {
+  if (queryNode != NULL) {
+    delete queryNode;
+    queryNode = NULL;
+  }
+  if (notNode != NULL) {
+    delete notNode;
+    notNode = NULL;
+  }
+}
+
+void NotQueryNode::Print (ostream &s, int indent) const {
+  PrintIndentText (s, "queryNode:\n", indent);
+  PrintNode (s, queryNode, indent+2);
+  PrintIndentText (s, "NOT\n", indent);
+  PrintIndentText (s, "notNode:\n", indent);
+  PrintNode (s, notNode, indent+2);
+}
+
+
+void TagNode::Clear () {
+  UCArrayClear (tagName);
+}
+
+void TagNode::Calculate (IndexData &indexData,
+			 FragRangeArray &fragRange) const {
+  fragRange.erase (fragRange.begin(), fragRange.end());
+  if (tagName.empty()) return;
+
+  // get information about this tag
+  block_dict_el tagEl;
+  unsigned long tagElNum;
+  if (!SearchBlockDictEl (indexData.dictFile, indexData.biTags,
+			  indexData.bdh.entries_per_tblk,
+			  indexData.bdh.tag_dict_size,
+			  tagName, tagEl, tagElNum))
+    return;
+
+  // seek to the appropriate place in the inverted file
+  fseek (indexData.invfFile, tagEl.invf_ptr, SEEK_SET);
+
+  stdio_bitio_buffer buffer(indexData.invfFile);
+  
+  unsigned long pTag = tagEl.frag_occur*2;
+  unsigned long B = BIO_Bblock_Init (indexData.bdh.num_frags+pTag, pTag);
+  unsigned long fragNum = 0;
+  unsigned long i;
+  FragRange thisFrag;
+  for (i=0; i<tagEl.frag_occur; ++i) {
+    // get start
+    unsigned long delta = buffer.bblock_decode (B, NULL)-1;
+    fragNum += delta;
+
+    thisFrag.rangeStart = fragNum;
+
+    // get end
+    delta = buffer.bblock_decode (B, NULL)-1;
+    fragNum += delta;
+
+    thisFrag.rangeEnd = fragNum;
+    fragRange.push_back (thisFrag);
+  }
+
+  buffer.done();
+}
+
+void TagNode::Free () {
+  Clear ();
+}
+
+void TagNode::Print (ostream &s, int indent) const {
+  PrintIndent (s, indent);
+  s << "TAG: \"" << tagName << "\"\n";
+}
+
+
+void TermNode::Clear () {
+  UCArrayClear (term);
+  termWeight = 1;
+  stemMethod = 0;
+  startRange = NO_TERM_RANGE_START;
+  endRange = NO_TERM_RANGE_END;
+}
+
+TermNode::TermNode () {
+  Clear ();
+}
+
+void TermNode::Calculate (IndexData &indexData,
+			  bool needFragFreqs,
+			  FragRangeArray *fragLimits,
+			  FragData &fragData,
+			  UCArrayVector &equivTerms) const {
+  fragData.Clear ();
+  equivTerms.erase(equivTerms.begin(), equivTerms.end());
+
+  // get a list of term numbers
+  vector<unsigned long> equivNums;
+  FindWordNumbers (indexData, term, stemMethod, equivNums);
+
+  // get the information for each word and merge it with
+  // previous results
+  FragData tempFragData1;
+  FragData tempFragData2;
+  UCArray equivWord;
+  vector<unsigned long>::iterator here = equivNums.begin();
+  vector<unsigned long>::iterator end = equivNums.end();
+  while (here != end) {
+    // get the information for this word
+    ReadTermFragData (indexData, needFragFreqs, *here,
+		      tempFragData1, fragLimits, equivWord);
+    equivTerms.push_back(equivWord);
+    // combine with last results
+    tempFragData2 = fragData;
+    CombineFragData (needFragFreqs, tempFragData1, tempFragData2, fragData);
+    
+    ++here;
+  }
+}
+
+void TermNode::Free () {
+  Clear ();
+}
+
+void TermNode::Print (ostream &s, int indent) const {
+  PrintIndent (s, indent);
+  s << "TERM: \"" << term << "\"\n";
+  PrintIndent (s, indent+2);
+  s << "termWeight: " << termWeight << "\n";
+  PrintIndent (s, indent+2);
+  s << "stemMethod: " << stemMethod << "\n";
+  PrintIndent (s, indent+2);
+  s << "startRange: " << startRange << "\n";
+  PrintIndent (s, indent+2);
+  s << "endRange: " << endRange << "\n";
+}
+
+
+ProxMatchQueryNode::ProxMatchQueryNode () {
+  tagNodePtr = NULL;
+}
+
+ProxMatchQueryNode::~ProxMatchQueryNode () {
+  Free ();
+}
+
+void ProxMatchQueryNode::Calculate (IndexData &indexData,
+				    const QueryInfo &queryInfo,
+				    QueryResult &result) const {
+  result.Clear ();
+
+  bool needFragFreqs = (queryInfo.sortByRank || queryInfo.needRankInfo);
+
+  // read in the tag if needed
+  FragRangeArray fragLimits;
+  FragRangeArray *fragLimitsPtr = NULL;
+  if (tagNodePtr == NULL && terms.size() > 1) {
+    // multiple terms must be compared relative to some tag
+    // otherwise phrase matches could span documents
+    TagNode tempTagNode;
+    tempTagNode.tagName = indexData.curLevel;
+    tempTagNode.Calculate (indexData, fragLimits);
+    fragLimitsPtr = &fragLimits;
+    
+  } else if (tagNodePtr != NULL) {
+    (*tagNodePtr).Calculate (indexData, fragLimits);
+    fragLimitsPtr = &fragLimits;
+  }
+
+  UCArray tagOrLevel = indexData.curLevel;
+  if (tagNodePtr != NULL) tagOrLevel = (*tagNodePtr).tagName;
+
+  // read in the first term
+  FragData termData;
+  UCArrayVector equivTerms;
+  TermNodeArray::const_iterator termHere=terms.begin(), termEnd = terms.end();
+  if (termHere != termEnd) {
+    (*termHere).Calculate (indexData, needFragFreqs, fragLimitsPtr, 
+			   termData, equivTerms);
+
+    // convert initial fragment information
+    FragsToQueryResult (indexData,
+			queryInfo,
+			termData,
+			tagOrLevel,
+			(*termHere).term,
+			(*termHere).stemMethod,
+			(*termHere).termWeight,
+			equivTerms,
+			result);
+  
+    ++termHere;
+
+    if (termHere == termEnd) return; // nothing more to do
+  }
+
+  // read and combine the rest of the terms
+  FragData comTermData;
+  while (termHere != termEnd) {
+    (*termHere).Calculate (indexData, needFragFreqs,
+			   fragLimitsPtr, comTermData, equivTerms);
+
+    AndFragsToQueryResult (indexData,
+			   queryInfo,
+			   comTermData,
+			   tagOrLevel,
+			   (*termHere).term,
+			   (*termHere).stemMethod,
+			   (*termHere).termWeight,
+			   equivTerms,
+			   result);
+    
+    AndCombineFragData (needFragFreqs, termData, comTermData,
+			(*termHere).startRange,
+			(*termHere).endRange,
+			fragLimitsPtr);
+    ++termHere;
+  }
+
+  // remove unwanted document numbers
+  RemoveUnwantedResults (indexData,
+			 queryInfo,
+			 termData,
+			 result);
+}
+
+void ProxMatchQueryNode::Free () {
+  if (tagNodePtr != NULL) {
+    delete tagNodePtr;
+    tagNodePtr = NULL;
+  }
+  terms.erase (terms.begin(), terms.end());
+}
+
+void ProxMatchQueryNode::Print (ostream &s, int indent) const {
+  PrintIndentText (s, "PROXMATCH\n", indent);
+  if (tagNodePtr != NULL) tagNodePtr->Print (s, indent+2);
+  
+  TermNodeArray::const_iterator here = terms.begin();
+  TermNodeArray::const_iterator end = terms.end();
+  while (here != end) {
+    (*here).Print (s, indent+2);
+    ++here;
+  }
+}
+
+
+void BrowseQueryNode::Clear () {
+  UCArrayClear(term);
+}
+
+void BrowseQueryNode::Calculate (IndexData &indexData, BrowseQueryResult &result) const {
+
+  unsigned long number=0;
+  FindNearestWordNumber(indexData, term, number);
+  if (number + startPosition > 0 ) {
+    number = number+startPosition;
+  }
+  else {
+    number = 1;
+  }
+
+  GetTermList (indexData, number, numTerms, result.termFreqs);
+
+}
+
+
+
+void BrowseQueryNode::Free () {
+  Clear();
+}
+
+
+void BrowseQueryNode::Print (ostream &s, int indent) const {
+  PrintIndentText(s, "BROWSEQUERYNODE\n", indent);
+  PrintIndent (s, indent+2);
+  s << "TERM:"<<term<<"\n";
+  PrintIndent (s, indent+2);
+  s << "Start position: "<< startPosition<<", Num terms: "<< numTerms<<"\n";
+
+
+}
+
+
+
+void MGQuery (IndexData &indexData,
+	      const QueryInfo &queryInfo,
+	      const QueryNode *queryTree,
+	      QueryResult &result) {
+  result.Clear ();
+
+  // make sure level is current
+  if (!indexData.LoadLevel (queryInfo.docLevel)) {
+    return;
+  }
+  // do query
+  if (queryTree == NULL) return;
+  
+  (*queryTree).Calculate (indexData, queryInfo, result);
+
+  // make weights into ranks if needed
+  unsigned long i;
+  if (queryInfo.sortByRank || queryInfo.needRankInfo) {
+    for (i=0; i<result.ranks.size(); ++i) {
+      result.ranks[i] /=
+	indexData.weightData.GetLowerApproxDocWeight (result.docs[i]);
+    }
+  }
+  
+  unsigned long resultsSize = queryInfo.maxDocs;
+  if (resultsSize == 0 || resultsSize > result.docs.size())
+    resultsSize = result.docs.size();
+
+  result.actualNumDocs = result.docs.size(); // the total number of docs 
+                                   //returned, before pruning based on maxDocs
+
+  // sort results by rank if needed
+  GTRank gtRank;
+  if (queryInfo.sortByRank) {
+    // need in ascending order for SelectAddHeap
+    MakeHeap (result.docs.begin(), result.ranks.begin(),
+	      resultsSize, gtRank);
+    SelectAddHeap (result.docs.begin(), result.ranks.begin(), resultsSize,
+		   result.docs.begin()+resultsSize,
+		   result.ranks.begin()+resultsSize,
+		   (unsigned long) result.ranks.size()-resultsSize,
+		   gtRank);
+
+    // sort into descending order
+    SortHeap (result.docs.begin(), result.ranks.begin(), resultsSize, gtRank);
+  }
+  
+  // get exact weights if needed
+  if (queryInfo.exactWeights &&
+      (queryInfo.sortByRank || queryInfo.needRankInfo)) {
+    unsigned long exactDiskPtr =
+      indexData.levels.levelInfo[indexData.curLevel].exactWeightsDiskPtr;
+    
+    for (i=0; i<resultsSize; ++i) {
+      result.ranks[i] =  result.ranks[i] *
+	indexData.weightData.GetLowerApproxDocWeight (result.docs[i]) /
+	GetExactDocWeight (indexData.exactWeightsFile, exactDiskPtr,
+			   result.docs[i]);
+    }
+
+    // re-sort top candidates based on exact weights
+    if (queryInfo.sortByRank) {
+      MakeHeap (result.docs.begin(), result.ranks.begin(),
+		resultsSize, gtRank);
+      SortHeap (result.docs.begin(), result.ranks.begin(),
+		resultsSize, gtRank);
+    }
+  }
+
+  // get rid of unwanted ranking results
+  if (result.ranks.empty()) {
+    // do nothing
+  } else if (!queryInfo.needRankInfo) {
+    result.ranks.erase(result.ranks.begin(), result.ranks.end());
+  } else {
+    result.ranks.erase(result.ranks.begin()+resultsSize, result.ranks.end());
+  }
+
+  // remove extra docs that are unwanted
+  result.docs.erase(result.docs.begin()+resultsSize, result.docs.end());
+}
+
+// new MGQuery to retrieve doc and section nums
+// this will return doc nums for the level queried at (set in queryInfo)
+// in QueryResult.docs and if a second level is specified, 
+// it will return corresponding docnums for that level in QueryResult.levels
+// If there is no level specified, or that level is invalid, the query
+// level is used
+void MGQuery (IndexData &indexData,
+	      const QueryInfo &queryInfo,
+	      const QueryNode *queryTree,
+	      ExtQueryResult &realresult, UCArray &level) {
+  realresult.Clear ();
+  QueryResult result; // temp result
+
+  // do the normal query
+  MGQuery (indexData, queryInfo, queryTree, result);
+
+  // now that have the final result stuff, convert to ExtQueryResult,
+  // add in level nums if needed
+
+  realresult.docs = result.docs;
+  realresult.ranks = result.ranks;
+  realresult.termFreqs = result.termFreqs;
+  realresult.actualNumDocs = result.actualNumDocs;
+
+  if (queryInfo.docLevel == level || level.empty()) {
+    realresult.levels = result.docs;
+    return;
+  }
+
+  // else need to convert from queryInfo.docLevel to level
+
+  // the original level info
+  FragLevelConvert sectionLevelConverter = indexData.levelConverter;
+
+  // the new level info
+  if (!indexData.LoadLevel(level)) {
+    realresult.levels = result.docs;
+    return;
+  }
+  
+  unsigned long DocNum = 0;
+  
+  for (unsigned long i=0; i<realresult.docs.size(); ++i) {
+
+    // do an if ! here????
+    indexData.levelConverter.LevelToLevel(sectionLevelConverter, realresult.docs[i], DocNum);
+    realresult.levels.push_back(DocNum);
+  }
+  
+}
+
+
+
+// new function for full text browsing, 
+void MGBrowseQuery (IndexData &indexData, UCArray &level,
+		  const BrowseQueryNode &node,
+		  BrowseQueryResult &result) {
+
+  indexData.LoadLevel(level);
+  node.Calculate(indexData, result); 
+
+}
Index: /indexers/branches/3.03a/mgpp/text/MGQuery.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/MGQuery.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/MGQuery.h	(revision 14757)
@@ -0,0 +1,197 @@
+/**************************************************************************
+ *
+ * MGQuery.h -- Query related functions
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef MGQUERY_H
+#define MGQUERY_H
+
+#include "IndexData.h"
+#include <limits.h>
+#include "Terms.h"
+
+// forms base for defining and calculating the boolean
+// part of a query
+class QueryNode {
+public:
+  QueryNode ();
+  virtual ~QueryNode ();
+
+  virtual void Calculate (IndexData &indexData, const QueryInfo &queryInfo,
+			  QueryResult &result) const;
+  virtual void Free ();
+  virtual void Print (ostream &s, int indent=0) const;
+};
+
+
+
+void PrintIndent (ostream &s, int indent);
+void PrintIndentText (ostream &s, char *text, int indent);
+void PrintNode (ostream &s, QueryNode *node, int indent=0);
+
+
+
+// basic boolean nodes
+
+class AndQueryNode : public QueryNode {
+public:
+  QueryNode *leftNode;
+  QueryNode *rightNode;
+  
+  AndQueryNode ();
+  ~AndQueryNode ();
+
+  void Calculate (IndexData &indexData, const QueryInfo &queryInfo,
+		  QueryResult &result) const;
+  void Free ();
+  void Print (ostream &s, int indent=0) const;
+};
+
+class OrQueryNode : public QueryNode {
+public:
+  QueryNode *leftNode;
+  QueryNode *rightNode;
+  
+  OrQueryNode ();
+  ~OrQueryNode ();
+
+  void Calculate (IndexData &indexData, const QueryInfo &queryInfo,
+		  QueryResult &result) const;
+  void Free ();
+  void Print (ostream &s, int indent=0) const;
+};
+
+class NotQueryNode : public QueryNode {
+public:
+  QueryNode *queryNode;
+  QueryNode *notNode;
+  
+  NotQueryNode ();
+  ~NotQueryNode ();
+
+  void Calculate (IndexData &indexData, const QueryInfo &queryInfo,
+		  QueryResult &result) const;
+  void Free ();
+  void Print (ostream &s, int indent=0) const;
+};
+
+
+
+class TagNode {
+public:
+  UCArray tagName;
+
+  void Clear ();
+  TagNode () { Clear (); }
+
+  void Calculate (IndexData &indexData, FragRangeArray &fragRange) const;
+  void Free ();
+  void Print (ostream &s, int indent=0) const;
+};
+
+
+#define NO_TERM_RANGE_START (LONG_MIN/2)
+#define NO_TERM_RANGE_END   (LONG_MAX/2)
+
+/* NOTE: range stuff - the range values are for the previous term relative
+to the current term. So if searching for the phrase "the cat", 'the' doesn't 
+need range limits, but 'cat' has a range of -2 to -1. ie, if have found 'cat'
+then 'the' has to be at position between -2 and -1 relative to 'cat'.
+"the cat" could also be searched for by 'cat' with no range limits, then 'the' with range 0 to 1.
+range values are relative to the gaps between words:
+   x   y   z   X   a   b   c
+    -3   -2  -1  0   1   2   3
+
+ */
+class TermNode {
+public:
+  UCArray term;
+  unsigned long termWeight;
+  unsigned long stemMethod;
+  signed long startRange; // range relative to last term
+  signed long endRange;
+  
+  void Clear ();
+  TermNode ();
+
+  // fragLimits can be NULL if not neede
+  void Calculate (IndexData &indexData,
+		  bool needFragFreqs,
+		  FragRangeArray *fragLimits,
+		  FragData &fragData,
+		  UCArrayVector &equivTerms) const;
+  void Free ();
+  void Print (ostream &s, int indent=0) const;
+};
+
+typedef vector<TermNode> TermNodeArray;
+
+
+class ProxMatchQueryNode : public QueryNode {
+public:
+  TagNode *tagNodePtr; // optional field
+  TermNodeArray terms;
+  
+  ProxMatchQueryNode ();
+  ~ProxMatchQueryNode ();
+
+  void Calculate (IndexData &indexData, const QueryInfo &queryInfo,
+		  QueryResult &result) const;
+  void Free ();
+  void Print (ostream &s, int indent=0) const;
+};
+
+class BrowseQueryNode :public QueryNode {
+ public:
+  UCArray term;
+  signed long startPosition;
+  unsigned long numTerms;
+
+  void Clear();
+  BrowseQueryNode () { Clear(); }
+  //  ~BrowseQueryNode ();
+
+  void Calculate (IndexData &indexData, BrowseQueryResult &result) const;
+  void Free ();
+  void Print (ostream &s, int indent=0) const;
+
+
+
+
+};
+
+void MGQuery (IndexData &indexData,
+	      const QueryInfo &queryInfo,
+	      const QueryNode *queryTree,
+	      QueryResult &result);
+
+// this function for retrieving results with both section doc nums
+// and Document docnums
+void MGQuery (IndexData &indexData,
+	      const QueryInfo &queryInfo,
+	      const QueryNode *queryTree,
+	      ExtQueryResult &result, UCArray &level);
+
+
+// new function for full text browsing, 
+void MGBrowseQuery (IndexData &indexData, UCArray &level,
+		  const BrowseQueryNode &node,
+		  BrowseQueryResult &result);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/Makefile.in
===================================================================
--- /indexers/branches/3.03a/mgpp/text/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/Makefile.in	(revision 14757)
@@ -0,0 +1,331 @@
+###########################################################################
+#
+# Makefile.in -- Makefile for the MGPP system
+# Copyright (C) 1994  Neil Sharman;  1995 Tim Shimmin
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#       @(#)Makefile.in	1.10 22 Mar 1994
+#
+###########################################################################
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+UNAC_DIR = @UNAC_DIR@
+
+ENABLE_ACCENTFOLD = @ENABLE_ACCENTFOLD@
+ifeq ($(ENABLE_ACCENTFOLD), 1)
+AFLIBS = $(UNAC_DIR)/libunac.a 
+AFINCLUDES = -I$(UNAC_DIR)
+AFFLAGS = -DENABLE_ACCENTFOLD
+else
+AFLIBS = 
+AFINCLUDES =
+AFFLAGS = 
+endif
+
+
+SHELL = /bin/sh
+VPATH = @srcdir@
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+bindir = @bindir@
+srcdir = @srcdir@
+libdir = @libdir@
+subdir = text
+top_srcdir = @top_srcdir@
+transform = @program_transform_name@
+
+AR = ar
+CC = @CC@
+CXX = @CXX@
+CFLAGS = @CFLAGS@ -ansi -fPIC -DSILENT -DSHORT_SUFFIX $(AFFLAGS)
+CXXFLAGS = @CXXFLAGS@ -fPIC -DSILENT -DSHORT_SUFFIX $(AFFLAGS)
+DEFS = @DEFS@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBS = ../lib/libmgpplib.a $(AFLIBS) -lstdc++ @LIBS@
+TOUCH = echo timestamp >
+AWK = @AWK@
+GSDLOS = @gsdlos@
+
+datadir = $(prefix)/share
+libexecdir = $(exec_prefix)/libexec
+localedir = $(datadir)/locale
+mandir = $(prefix)/man/man1
+
+COMPILE = $(CC) -c $(DEFS) $(TREC_MODE) $(READLINE) $(INCLUDES) $(CFLAGS)
+CXXCOMPILE = $(CXX) -c $(DEFS) $(TREC_MODE) $(READLINE) $(INCLUDES) $(CXXFLAGS)
+LINK = $(CC) $(LDFLAGS) -o $@
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+	$(COMPILE) $<
+
+.SUFFIXES: .cpp .o
+.cpp.o:
+	$(CXXCOMPILE) $<
+
+
+ANSI2KNR = @ANSI2KNR@
+o = .@U@o
+
+.SUFFIXES: ._c ._o
+.c._c:
+	./ansi2knr $< > $*.tmp && mv $*.tmp $@
+._c._o:
+	@echo $(COMPILE) $<
+	@rm -f _$*.c
+	@ln $< _$*.c && $(COMPILE) _$*.c && mv _$*.o $@ && rm _$*.c
+.c._o:
+	./ansi2knr $< > $*.tmp && mv $*.tmp $*._c
+	@echo $(COMPILE) $*._c
+	@rm -f _$*.c
+	@ln $*._c _$*.c && $(COMPILE) _$*.c && mv _$*.o $@ && rm _$*.c
+
+INCLUDES = -I.. -I../lib -I. $(AFINCLUDES)
+
+#############################################################################
+#
+# Uncomment (and possibly edit) the following lines if you wish
+# to use the GNU readline library for the input in mgquery
+# 
+#READLINE = -DGNU_READLINE -I/opt/gnu/include/readline -L/opt/gnu/lib
+#READLINE_LIBS = -lreadline -ltermcap
+#
+#
+#############################################################################
+
+SOURCES = \
+  FIvfLevelInfo.cpp        ivf.pass1.cpp            mgpp_invf_dump.cpp       \
+  FText.cpp                ivf.pass2.cpp            mgpp_passes.cpp          \
+  FileBuf.cpp              locallib.cpp             mgpp_perf_hash_build.cpp \
+  FragLevelConvert.cpp     mg.special.cpp           mgpp_stem_idx.cpp        \
+  IndexData.cpp            mgpp_compression_dict.cpp  mgpp_weights_build.cpp   \
+  TagInfo.cpp              mgpp_decompress_text.cpp   stemmer.cpp            \
+  TextEl.cpp               mg_errors.cpp            text.cpp               \
+  TextGet.cpp              mgpp_fast_comp_dict.cpp    text.pass1.cpp         \
+  UCArray.cpp              mg_files.cpp             text.pass2.cpp         \
+  comp_dict.cpp            mgpp_invf_dict.cpp         words.cpp              \
+  invf.cpp                 mgpp_invf_dict_dump.cpp    Weights.cpp            \
+  MGQuery.cpp              Terms.cpp                QueryTester.cpp        \
+  QueryLex.cpp             QueryParser.cpp         \
+  GSDLQueryLex.cpp	   GSDLQueryParser.cpp      Queryer.cpp \
+	mgpp_passes_4jni.cpp
+
+
+HEADERS = \
+  FIvfLevelInfo.h     TextEl.h            hash.h              stemmer.h  \
+  FText.h             TextGet.h           invf.h              text.h     \
+  FileBuf.h           UCArray.h           locallib.h          words.h    \
+  FragLevelConvert.h  WordData.h          mg.h                           \
+  IndexData.h         build.h             mg_errors.h                    \
+  TagInfo.h           comp_dict.h         mg_files.h          Weights.h  \
+  MGQuery.h           Terms.h             QueryLex.h          QueryParser.h \
+  GSDLQueryLex.h	GSDLQueryParser.h  mgpp_passes_4jni.h
+
+
+MISC          = Makefile.in 
+
+ALLFILES      =	$(SOURCES) $(HEADERS) $(MISC) $(MAN)
+
+DISTFILES     = $(ALLFILES) 
+
+EXEC          = mgpp_passes mgpp_decompress_text mgpp_perf_hash_build \
+                mgpp_invf_dump mgpp_weights_build mgpp_invf_dict mgpp_stem_idx \
+                mgpp_invf_dict_dump mgpp_compression_dict mgpp_fast_comp_dict \
+                QueryTester Queryer
+
+MAN           =  mgpp_weights_build.1  mgpp_invf_dict.1 \
+                 mgpp_passes.1 mgpp_perf_hash_build.1 \
+                 mgpp_compression_dict.1  mgpp_fast_comp_dict.1 \
+                 mgpp_stem_idx.1
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+all:	$(EXEC) libmgpptext.a libmgpppass.a
+
+depend:
+	makedepend -Y -- $(DEFS) $(INCLUDES) $(CXXFLAGS) $(CFLAGS) -- $(SOURCES)
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+PASSES_OBJS = \
+	mgpp_passes$o text.pass1$o comp_dict$o \
+	text.pass2$o locallib$o \
+	ivf.pass1$o ivf.pass2$o mg.special$o mg_files$o \
+	words$o invf$o FileBuf$o TextEl$o UCArray$o TagInfo$o \
+        FText$o text$o FIvfLevelInfo$o
+
+mgpp_passes: $(PASSES_OBJS)
+	$(LINK) $(PASSES_OBJS) $(LIBS)
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+QUERYER_OBJS = Queryer$o mg_files$o mg_errors$o locallib$o invf$o UCArray$o \
+               FIvfLevelInfo$o FragLevelConvert$o Terms$o MGQuery$o \
+               IndexData$o stemmer$o Weights$o TextGet$o text$o FText$o \
+               GSDLQueryParser$o GSDLQueryLex$o words$o
+
+Queryer: $(QUERYER_OBJS)
+	$(LINK) $(QUERYER_OBJS) $(LIBS)
+
+QUERY_TESTER_OBJS = QueryTester$o mg_files$o invf$o UCArray$o \
+                    FIvfLevelInfo$o FragLevelConvert$o Terms$o MGQuery$o \
+                    IndexData$o stemmer$o Weights$o
+
+QueryTester: $(QUERY_TESTER_OBJS)
+	$(LINK) $(QUERY_TESTER_OBJS) $(LIBS)
+
+WEIGHTS_BUILD_OBJS = mgpp_weights_build$o mg_files$o invf$o UCArray$o \
+                     FIvfLevelInfo$o FragLevelConvert$o
+
+mgpp_weights_build: $(WEIGHTS_BUILD_OBJS)
+	$(LINK) $(WEIGHTS_BUILD_OBJS) $(LIBS)
+
+COMP_DICT_OBJS = mgpp_compression_dict$o mg_files$o locallib$o
+
+mgpp_compression_dict: $(COMP_DICT_OBJS)
+	$(LINK) $(COMP_DICT_OBJS) $(LIBS)
+
+FAST_COMP_OBJS = mgpp_fast_comp_dict$o mg_files$o locallib$o
+
+mgpp_fast_comp_dict: $(FAST_COMP_OBJS)
+	$(LINK) $(FAST_COMP_OBJS) $(LIBS)
+
+INVF_DUMP_OBJS = mgpp_invf_dump$o locallib$o mg_files$o invf$o UCArray$o
+
+mgpp_invf_dump: $(INVF_DUMP_OBJS)
+	$(LINK) $(INVF_DUMP_OBJS) $(LIBS)
+
+INVF_DICT_OBJS = mgpp_invf_dict$o mg_files$o invf$o UCArray$o
+
+mgpp_invf_dict: $(INVF_DICT_OBJS)
+	$(LINK) $(INVF_DICT_OBJS) $(LIBS)
+
+INVF_DICT_DUMP_OBJS = mgpp_invf_dict_dump$o mg_files$o invf$o UCArray$o
+
+mgpp_invf_dict_dump: $(INVF_DICT_DUMP_OBJS)
+	$(LINK) $(INVF_DICT_DUMP_OBJS) $(LIBS)
+
+PERF_HASH_OBJS = mgpp_perf_hash_build$o mg_files$o invf$o UCArray$o
+
+mgpp_perf_hash_build: $(PERF_HASH_OBJS)
+	$(LINK) $(PERF_HASH_OBJS) $(LIBS)
+
+STEM_IDX_OBJS = mgpp_stem_idx$o mg_files$o stemmer$o \
+                invf$o UCArray$o
+
+mgpp_stem_idx: $(STEM_IDX_OBJS)
+	$(LINK) $(STEM_IDX_OBJS) $(LIBS)
+
+DECOMPRESS_TEXT_OBJS = \
+                mgpp_decompress_text$o mg_files$o mg_errors$o \
+                locallib$o text$o UCArray$o TextGet$o FText$o
+
+mgpp_decompress_text: $(DECOMPRESS_TEXT_OBJS)
+	$(LINK) $(DECOMPRESS_TEXT_OBJS) $(LIBS)
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ansi2knr: ansi2knr.o
+	$(LINK) ansi2knr.o $(LIBS)
+
+install: execinstall
+uninstall: execuninstall
+
+execinstall: $(EXEC)
+	../mkinstalldirs $(bindir); \
+	for name in $(EXEC); do \
+	  $(INSTALL_PROGRAM) $$name \
+	  $(bindir)/`echo $$name | sed '$(transform)'`; \
+	done 
+
+execuninstall:
+	for name in $(EXEC); do \
+	 rm -f $(bindir)/`echo $$name | sed '$(transform)'`; \
+	done
+
+maninstall: $(MAN)
+	$(top_srcdir)/mkinstalldirs $(mandir); \
+	for f in $(MAN); do \
+	  $(INSTALL_DATA) $$f $(mandir)/$$f ;\
+	done
+
+manuninstall: $(MAN)
+	for f in $(MAN); do \
+	  rm -f $(mandir)/$$f ;\
+	done
+
+LIB_OBJS = mg_files$o  mg_errors$o locallib$o invf$o UCArray$o \
+           FIvfLevelInfo$o FragLevelConvert$o Terms$o MGQuery$o \
+           IndexData$o stemmer$o Weights$o TextGet$o text$o FText$o \
+           GSDLQueryParser$o GSDLQueryLex$o words$o
+
+libmgpptext.a: $(LIB_OBJS)
+	rm -f libmgpptext.a
+	$(AR) cru libmgpptext.a $(LIB_OBJS)
+	$(RANLIB) libmgpptext.a
+
+JNI_LIB_OBJS = \
+	mgpp_passes_4jni$o text.pass1$o comp_dict$o \
+	text.pass2$o locallib$o \
+	ivf.pass1$o ivf.pass2$o mg.special$o mg_files$o \
+	words$o invf$o FileBuf$o TextEl$o UCArray$o TagInfo$o \
+        FText$o text$o FIvfLevelInfo$o
+
+libmgpppass.a: $(JNI_LIB_OBJS)
+	rm -f libmgpppass.a
+	$(AR) cru libmgpppass.a $(JNI_LIB_OBJS)
+	$(RANLIB) libmgpppass.a
+
+mostlyclean:
+	rm -f *$o _*.c _*.o *._c *._o core core.*
+
+clean: mostlyclean
+	rm -f $(EXEC) libmgpptext.a libmgpppass.a
+
+distclean: clean
+	rm -f ansi2knr
+	rm -f Makefile
+
+maintainer-clean: distclean
+	@echo "This command is intended only for maintainers to use;"
+	@echo "rebuilding the deleted files may require special tools."
+
+dist: $(DISTFILES)
+	for file in $(DISTFILES); do \
+	  ln $(srcdir)/$$file $(distdir) 2> /dev/null \
+	  || cp -p $(srcdir)/$$file $(distdir); \
+	done
+
+movclean:
+	for file in $(SOURCES); do \
+          test = $$file; \
+          echo $("test.c"##*.c); \
+        done 
+
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exc
+
+
Index: /indexers/branches/3.03a/mgpp/text/QueryLex.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/QueryLex.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/QueryLex.cpp	(revision 14757)
@@ -0,0 +1,175 @@
+/**************************************************************************
+ *
+ * QueryLex.cpp -- Lexical analyser for a simple query language
+ * Copyright (C) 2000  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "QueryLex.h"
+#include "unitool.h"
+#include "words.h"
+
+inline void AddNChar (UCArray::const_iterator &here,
+		      UCArray &text,
+		      int len) {
+  if (text.capacity() < text.size() + len + 1) {
+    text.reserve(text.size + len + 1);
+  }
+  while (len > 0) {
+    text.push_back (*here++);
+    --len;
+  }
+}
+
+static bool ParseInteger (UCArray::const_iterator &here,
+			  UCArray::const_iterator end,
+			  LexEl &el) {
+  el.Clear();
+
+  // this version of end is used in unitool
+  UCArray::const_iterator endMinus1 = end-1;
+
+  int charLen;
+  unsigned short c; // one character lookahead
+  charLen = parse_utf8_char (here, endMinus1, &c);
+
+  // check for positive or negative
+  bool neg = false;
+  if (c == '+') {
+    AddNChar (here, el.text, charLen);
+    charLen = parse_utf8_char (here, endMinus1, &c);
+  } else if (c == '-') {
+    neg = true;
+    AddNChar (here, el.text, charLen);
+    charLen = parse_utf8_char (here, endMinus1, &c);
+  }
+
+  // read in number part
+  el.num = 0;
+  el.lexType = IntegerE;
+  while (c >= '0' && c <= '9') {
+    el.num = el.num*10 + c - '0';
+    AddNChar (here, el.text, charLen);
+    charLen = parse_utf8_char (here, endMinus1, &c);
+  }
+
+  if (neg) el.num *= -1;
+
+  return (!el.text.empty());
+}
+
+static bool ParseTerm (UCArray::const_iterator &here,
+		       UCArray::const_iterator end,
+		       UCArray &text) {
+  UCArray::const_iterator endMinus1 = end-1;
+  here = ParseIndexWord (here, endMinus1, text);
+  return !text.empty();
+}
+
+
+bool ParseLexEl (UCArray::const_iterator &here,
+		 UCArray::const_iterator end,
+		 LexEl &el) {
+  el.Clear();
+
+  // strange things can happen if here == end == 0
+  if (here == end) return false;
+  
+  // this version of end is used in unitool
+  UCArray::const_iterator endMinus1 = end-1;
+  
+  // ignore all white space
+  int charLen;
+  unsigned short c; // one character lookahead
+  charLen = parse_utf8_char (here, endMinus1, &c);
+  while (here != end && is_unicode_space (c)) {
+    here += charLen;
+    charLen = parse_utf8_char (here, endMinus1, &c);
+  }
+  if (here == end) return false;
+
+  if (c == '(') {
+    el.lexType = OpenBracketE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == ')') {
+    el.lexType = CloseBracketE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '\"') {
+    el.lexType = QuoteE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '#') {
+    el.lexType = TermWeightE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '$') {
+    el.lexType = StemMethodE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '^') {
+    el.lexType = RangeE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '@') {
+    el.lexType = AtE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == ':') {
+    el.lexType = TagE;
+    AddNChar (here, el.text, charLen);
+    return true;
+    
+  } else if (c == '+' || c == '-' ||
+	     (c >= '0' && c <= '9')) {
+    return ParseInteger (here, end, el);
+  }
+
+  // assume it is a term of some sort
+  if (!ParseTerm (here, end, el.text)) return false;
+
+  //UCArray AND; SetCStr (AND, "AND");
+  //if (el.text == AND) {
+  if (UCArrayCStrEquals(el.text, "AND")) {  
+    el.lexType = AndOpE;
+    return true;
+  }
+  //UCArray OR; SetCStr (OR, "OR");
+  //if (el.text == OR) {
+  if (UCArrayCStrEquals(el.text, "OR")) {
+    el.lexType = OrOpE;
+    return true;
+  }
+  //UCArray NOT; SetCStr (NOT, "NOT");
+  //if (el.text == NOT) {
+  if (UCArrayCStrEquals(el.text, "NOT")) {
+    el.lexType = NotOpE;
+    return true;
+  }
+
+  el.lexType = TermE;
+  return true;
+}
+
Index: /indexers/branches/3.03a/mgpp/text/QueryLex.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/QueryLex.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/QueryLex.h	(revision 14757)
@@ -0,0 +1,53 @@
+/**************************************************************************
+ *
+ * QueryLex.h -- Lexical analyser for a simple query language
+ * Copyright (C) 2000  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef QUERYLEX_H
+#define QUERYLEX_H
+
+#include "UCArray.h"
+
+
+// note: white space is ignored
+enum LexType {NoTypeE, OpenBracketE, CloseBracketE, TermE, AndOpE, OrOpE,
+	      NotOpE, QuoteE, IntegerE, TermWeightE, StemMethodE,
+	      RangeE, AtE, TagE};
+
+struct LexEl {
+  LexType lexType;
+  UCArray text;
+  int num; // for IntegerE
+
+  void Clear () {
+    lexType = NoTypeE;
+    UCArrayClear (text);
+    num = 0;
+  }
+  LexEl () { Clear (); }
+};
+
+
+// returns true if another lexical element could be parsed.
+bool ParseLexEl (UCArray::const_iterator &here,
+		 UCArray::const_iterator end,
+		 LexEl &el);
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/QueryParser.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/QueryParser.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/QueryParser.cpp	(revision 14757)
@@ -0,0 +1,219 @@
+/**************************************************************************
+ *
+ * QueryParser.cpp -- Query parser for a simple query language
+ * Copyright (C) 2000  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "QueryParser.h"
+#include "QueryLex.h"
+
+
+static QueryNode *ParseExpression (UCArray::const_iterator &here,
+				   UCArray::const_iterator end);
+
+static QueryNode *AndAdd (QueryNode *t1, QueryNode *t2) {
+  if (t1 == NULL) return t2;
+  if (t2 == NULL) return t1;
+
+  AndQueryNode *andNode = new AndQueryNode;
+  andNode->leftNode = t1;
+  andNode->rightNode = t2;
+  return andNode;
+}
+
+static QueryNode *OrAdd (QueryNode *t1, QueryNode *t2) {
+  if (t1 == NULL) return t2;
+  if (t2 == NULL) return t1;
+
+  OrQueryNode *orNode = new OrQueryNode;
+  orNode->leftNode = t1;
+  orNode->rightNode = t2;
+  return orNode;
+}
+
+static QueryNode *NotAdd (QueryNode *t1, QueryNode *t2) {
+  if (t1 == NULL) return t2;
+  if (t2 == NULL) return t1;
+
+  NotQueryNode *notNode = new NotQueryNode;
+  notNode->queryNode = t1;
+  notNode->notNode = t2;
+  return notNode;
+}
+
+// expects the opening bracket to have already been parsed
+// and discarded
+static QueryNode *ParseBracketExpression (UCArray::const_iterator &here,
+					  UCArray::const_iterator end) {
+  // get everything in the expression
+  QueryNode *curTree = ParseExpression (here, end);
+  
+  // gobble up tokens until a closing bracket is found
+  // or the end of the string
+  LexEl el;
+  while (ParseLexEl (here, end, el)) {
+    if (el.lexType == CloseBracketE) break;
+  }
+
+  return curTree;
+}
+
+static int ParseInt (UCArray::const_iterator &here,
+		     UCArray::const_iterator end) {
+  LexEl el;
+  UCArray::const_iterator oldHere = here;
+  if (ParseLexEl (here, end, el) && el.lexType == IntegerE)
+    return el.num;
+  
+  here = oldHere; // not an integer
+  return 0;
+}
+
+
+static void ParseTermModifiers (UCArray::const_iterator &here,
+				UCArray::const_iterator end,
+				TermNode &termNode) {
+  LexEl el;
+  UCArray::const_iterator oldHere = here;
+  while (ParseLexEl (here, end, el)) {
+    if (el.lexType == TermWeightE) {
+      termNode.termWeight = ParseInt (here, end);
+      
+    } else if (el.lexType == StemMethodE) {
+      termNode.stemMethod = ParseInt (here, end);
+      
+    } else if (el.lexType == RangeE) {
+      termNode.startRange = ParseInt (here, end);
+      termNode.endRange = ParseInt (here, end);
+      
+    } else if (el.lexType == AtE) {
+      termNode.startRange = termNode.endRange = ParseInt (here, end);
+      
+    } else {
+      // no term modifiers
+      here = oldHere;
+      break;
+    }
+    
+    oldHere = here;
+  }  
+}
+
+// expects the starting quote to have been parsed
+// and discarded
+static void ParsePhrase (UCArray::const_iterator &here,
+			 UCArray::const_iterator end,
+			 ProxMatchQueryNode &proxNode) {
+  LexEl el;
+  while (ParseLexEl (here, end, el)) {
+    if (el.lexType == TermE || el.lexType == IntegerE) {
+      TermNode termNode;
+      termNode.term = el.text;
+      ParseTermModifiers (here, end, termNode);
+      proxNode.terms.push_back (termNode);
+      
+    } else if (el.lexType == QuoteE) {
+      break;
+      
+    } else {
+      // error
+      break;
+    }
+  }
+}
+
+static QueryNode *ParseTerm (UCArray::const_iterator &here,
+			     UCArray::const_iterator end) {
+  LexEl el;
+
+  UCArray::const_iterator oldHere = here;
+  if (!ParseLexEl (here, end, el)) return NULL;
+
+  if (el.lexType == OpenBracketE)
+    return ParseBracketExpression (here, end);
+
+  ProxMatchQueryNode *proxNode = new ProxMatchQueryNode;
+
+  // check for a tag
+  if (el.lexType == TagE) {
+    oldHere = here; // don't backtrack past here
+    if (!ParseLexEl (here, end, el)) return NULL;
+    if (el.lexType == TermE) {
+      proxNode->tagNodePtr = new TagNode;
+      proxNode->tagNodePtr->tagName = el.text;
+      if (!ParseLexEl (here, end, el)) return NULL;
+    }
+  }
+  
+  if (el.lexType == TermE || el.lexType == IntegerE) {
+    TermNode termNode;
+    termNode.term = el.text;
+    ParseTermModifiers (here, end, termNode);
+    proxNode->terms.push_back (termNode);
+    return proxNode;
+    
+  } else if (el.lexType == QuoteE) {
+    ParsePhrase (here, end, *proxNode);
+    return proxNode;
+  }
+
+  // not a term
+  here = oldHere;
+  delete proxNode;
+  return NULL;
+}
+
+
+static QueryNode *ParseExpression (UCArray::const_iterator &here,
+				   UCArray::const_iterator end) {
+  LexEl el;
+  QueryNode *curTree = NULL;
+
+  UCArray::const_iterator oldHere = here;
+  while (ParseLexEl (here, end, el)) {
+    if (el.lexType == OpenBracketE ||
+	el.lexType == TermE ||
+	el.lexType == QuoteE ||
+	el.lexType == IntegerE ||
+	el.lexType == TagE) {
+      // some type of term, back track and parse it
+      here = oldHere;
+      curTree = OrAdd (curTree, ParseTerm (here, end));
+      
+    } else if (el.lexType == AndOpE) {
+      curTree = AndAdd (curTree, ParseTerm (here, end));
+      
+    } else if (el.lexType == OrOpE) {
+      curTree = OrAdd (curTree, ParseTerm (here, end));
+      
+    } else if (el.lexType == NotOpE) {
+      curTree = NotAdd (curTree, ParseTerm (here, end));
+      
+    } else break;
+    
+    oldHere = here;
+  }
+
+  return curTree;
+}
+
+QueryNode *ParseQuery (const UCArray &queryStr) {
+  UCArray::const_iterator here = queryStr.begin();
+  UCArray::const_iterator end = queryStr.end();
+  return ParseExpression (here, end);
+}
Index: /indexers/branches/3.03a/mgpp/text/QueryParser.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/QueryParser.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/QueryParser.h	(revision 14757)
@@ -0,0 +1,31 @@
+/**************************************************************************
+ *
+ * QueryParser.h -- Query parser for a simple query language
+ * Copyright (C) 2000  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef QUERYPARSER_H
+#define QUERYPARSER_H
+
+#include "UCArray.h"
+#include "MGQuery.h"
+
+// returns NULL if the query could not be parsed
+QueryNode *ParseQuery (const UCArray &queryStr);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/QueryResultsSort.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/QueryResultsSort.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/QueryResultsSort.h	(revision 14757)
@@ -0,0 +1,140 @@
+/**************************************************************************
+ *
+ * QueryResultsSort.h -- Functions to sort query results and parallel data
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef QUERYRESULTSSORT_H
+#define QUERYRESULTSSORT_H
+
+#include "Terms.h"
+
+
+struct LTRank {
+  bool operator()(const float &f1, const float &f2) const
+    { return (f1 < f2); }
+};
+
+struct GTRank {
+  bool operator()(const float &f1, const float &f2) const
+    { return (f1 > f2); }
+};
+
+
+
+// assumes the rank vector is the same size as the document
+// number vector. assumes the value to be pushed is in
+// docNumHeap + heapSize - 1 and rankHeap + heapSize - 1
+// topIndex can be set
+template <class RandomAccessIterator, class Compare>
+void PushHeap (DocNumArray::iterator docNumHeap,
+	       RandomAccessIterator parallelHeap,
+	       unsigned long heapSize,
+	       const Compare &comp) {
+  unsigned long holeIndex = heapSize-1;
+  unsigned long parent = (holeIndex - 1) / 2;
+  while (holeIndex > 0 && comp (*(parallelHeap+parent),
+				*(parallelHeap+holeIndex))) {
+    swap (*(parallelHeap+holeIndex), *(parallelHeap+parent));
+    swap (*(docNumHeap+holeIndex), *(docNumHeap+parent));
+    holeIndex = parent;
+    parent = (holeIndex - 1) / 2;
+  }
+}
+
+// AdjustHeap is used to add a element to a heap after one
+// element in the heap has been replaced with a new one
+template <class RandomAccessIterator, class Compare>
+void AdjustHeap (DocNumArray::iterator docNumHeap,
+		     RandomAccessIterator parallelHeap,
+		     unsigned long holeIndex,
+		     unsigned long heapSize,
+		     const Compare &comp) {
+  unsigned long secondChild = 2 * holeIndex + 2;
+  while (secondChild < heapSize) {
+    if (comp(*(parallelHeap + secondChild),
+	     *(parallelHeap + (secondChild - 1))))
+      --secondChild;
+    swap (*(parallelHeap+holeIndex), *(parallelHeap+secondChild));
+    swap (*(docNumHeap+holeIndex), *(docNumHeap+secondChild));
+    holeIndex = secondChild;
+    secondChild = 2 * secondChild + 2;
+  }
+  if (secondChild == heapSize) {
+    swap (*(parallelHeap+holeIndex), *(parallelHeap+(secondChild-1)));
+    swap (*(docNumHeap+holeIndex), *(docNumHeap+(secondChild-1)));
+    holeIndex = secondChild - 1;
+  }
+  PushHeap (docNumHeap, parallelHeap, holeIndex+1, comp);
+}
+
+template <class RandomAccessIterator, class Compare>
+void PopHeap (DocNumArray::iterator docNumHeap,
+	      RandomAccessIterator parallelHeap,
+	      unsigned long heapSize,
+	      const Compare &comp) {
+  swap (*(parallelHeap), *(parallelHeap+heapSize-1));
+  swap (*(docNumHeap), *(docNumHeap+heapSize-1));
+  AdjustHeap (docNumHeap, parallelHeap, (unsigned long)0, heapSize-1, comp);
+}
+
+template <class RandomAccessIterator, class Compare>
+void MakeHeap (DocNumArray::iterator docNumHeap,
+	       RandomAccessIterator parallelHeap,
+	       unsigned long size,
+	       const Compare &comp) {
+  if (size < 2) return;
+  
+  unsigned long i = 0;
+  for (i=1; i<=size; ++i)
+    PushHeap (docNumHeap, parallelHeap, i, comp);
+}
+
+ 
+template <class RandomAccessIterator, class Compare>
+void SortHeap (DocNumArray::iterator docNumHeap,
+	       RandomAccessIterator parallelHeap,
+	       unsigned long size,
+	       const Compare &comp) {
+  if (size < 2) return;
+
+  unsigned long i;
+  for (i=size; i>1; --i)
+    PopHeap (docNumHeap, parallelHeap, i, comp);
+}
+
+// uses the heap to get the top "size" elements
+template <class RandomAccessIterator, class Compare>
+void SelectAddHeap (DocNumArray::iterator docNumHeap,
+		    RandomAccessIterator parallelHeap,
+		    unsigned long heapSize,
+		    DocNumArray::iterator docNumAdd,
+		    RandomAccessIterator parallelAdd,
+		    unsigned long addSize,
+		    const Compare &comp) {
+  unsigned long i;
+  for (i=0; i<addSize; ++i) {
+    if (comp(*(parallelAdd+i), *(parallelHeap))) {
+      swap (*(docNumHeap), *(docNumAdd+i));
+      swap (*(parallelHeap), *(parallelAdd+i));
+      AdjustHeap (docNumHeap, parallelHeap, (unsigned long)0, heapSize, comp);
+    }
+  }
+}
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/QueryTester.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/QueryTester.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/QueryTester.cpp	(revision 14757)
@@ -0,0 +1,447 @@
+/**************************************************************************
+ *
+ * QueryTester.cpp -- 
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "MGQuery.h"
+
+
+class SetQueryNode : public QueryNode {
+public:
+  QueryResult queryResult;
+  
+  SetQueryNode () {}
+  ~SetQueryNode () {}
+
+  void Calculate (IndexData &/*indexData*/, const QueryInfo &queryInfo,
+		  QueryResult &result) const {
+    result = queryResult;
+    if (!queryInfo.sortByRank && !queryInfo.needRankInfo)
+      result.ranks.erase (result.ranks.begin(), result.ranks.end());
+    if (!queryInfo.needTermFreqs)
+      result.termFreqs.erase (result.termFreqs.begin(),
+			      result.termFreqs.end());
+  }
+  void Free () { queryResult.Clear(); }
+};
+
+
+bool Test1 () {
+  AndQueryNode andNode;
+
+  SetQueryNode *setNode1 = new SetQueryNode;
+  DocNumArray &docSet1 = setNode1->queryResult.docs;
+  RankArray &rankSet1 = setNode1->queryResult.ranks;
+  docSet1.push_back (1);  rankSet1.push_back (0.1f);
+  docSet1.push_back (10); rankSet1.push_back (0.2f);
+  docSet1.push_back (15); rankSet1.push_back (0.2f);
+  docSet1.push_back (18); rankSet1.push_back (0.4f);
+  docSet1.push_back (19); rankSet1.push_back (0.5f);
+
+  SetQueryNode *setNode2 = new SetQueryNode;
+  DocNumArray &docSet2 = setNode2->queryResult.docs;
+  RankArray &rankSet2 = setNode2->queryResult.ranks;
+  docSet2.push_back (2);  rankSet2.push_back (0.1f);
+  docSet2.push_back (11); rankSet2.push_back (0.2f);
+  docSet2.push_back (12); rankSet2.push_back (0.3f);
+  docSet2.push_back (13); rankSet2.push_back (0.4f);
+  docSet2.push_back (14); rankSet2.push_back (0.5f);
+  docSet2.push_back (15); rankSet2.push_back (0.6f);
+  docSet2.push_back (16); rankSet2.push_back (0.7f);
+  docSet2.push_back (17); rankSet2.push_back (0.8f);
+  docSet2.push_back (19); rankSet2.push_back (0.9f);
+  docSet2.push_back (20); rankSet2.push_back (0.1f);
+  docSet2.push_back (21); rankSet2.push_back (0.2f);
+
+  cout << "\n" << setNode1->queryResult << "AND\n\n"
+       << setNode2->queryResult;
+  
+
+  andNode.leftNode = setNode1;
+  andNode.rightNode = setNode2;
+
+  IndexData indexData; // this will not be used anywhere
+  QueryInfo queryInfo;
+  queryInfo.maxDocs = 0;
+  queryInfo.sortByRank = true;
+  queryInfo.needRankInfo = true;
+  queryInfo.needTermFreqs = true;
+  
+  QueryResult result;
+
+  andNode.Calculate(indexData, queryInfo, result);
+
+  cout << "EQUALS\n\n" << result << "\n";
+
+  QueryResult resultCompare;
+  DocNumArray &rcDocSet = resultCompare.docs;
+  RankArray &rcRankSet = resultCompare.ranks;
+  rcDocSet.push_back (15);  rcRankSet.push_back (0.2+0.6);
+  rcDocSet.push_back (19);  rcRankSet.push_back (1.4);
+
+  if (!(result == resultCompare)) {
+    cout << "Test failed!!!\n";
+    cout << resultCompare;
+    return false;
+  }
+
+  return true;
+}
+
+bool Test1b () {
+  AndQueryNode andNode;
+
+  SetQueryNode *setNode1 = new SetQueryNode;
+  DocNumArray &docSet1 = setNode1->queryResult.docs;
+  docSet1.push_back (1); 
+  docSet1.push_back (10);
+  docSet1.push_back (15);
+  docSet1.push_back (18);
+  docSet1.push_back (19);
+
+  SetQueryNode *setNode2 = new SetQueryNode;
+  DocNumArray &docSet2 = setNode2->queryResult.docs;
+  docSet2.push_back (2); 
+  docSet2.push_back (11);
+  docSet2.push_back (12);
+  docSet2.push_back (13);
+  docSet2.push_back (14);
+  docSet2.push_back (15);
+  docSet2.push_back (16);
+  docSet2.push_back (17);
+  docSet2.push_back (19);
+  docSet2.push_back (20);
+  docSet2.push_back (21);
+
+  cout << "\n" << setNode1->queryResult << "AND\n\n"
+       << setNode2->queryResult;
+  
+
+  andNode.leftNode = setNode1;
+  andNode.rightNode = setNode2;
+
+  IndexData indexData; // this will not be used anywhere
+  QueryInfo queryInfo;
+  queryInfo.maxDocs = 0;
+  queryInfo.sortByRank = false;
+  queryInfo.needRankInfo = false;
+  queryInfo.needTermFreqs = true;
+  
+  QueryResult result;
+
+  andNode.Calculate(indexData, queryInfo, result);
+
+  cout << "EQUALS\n\n" << result << "\n";
+
+  QueryResult resultCompare;
+  DocNumArray &rcDocSet = resultCompare.docs;
+  rcDocSet.push_back (15); 
+  rcDocSet.push_back (19); 
+
+  if (!(result == resultCompare)) {
+    cout << "Test failed!!!\n";
+    cout << resultCompare;
+    return false;
+  }
+
+  return true;
+}
+
+bool Test2 () {
+  OrQueryNode orNode;
+
+  SetQueryNode *setNode1 = new SetQueryNode;
+  DocNumArray &docSet1 = setNode1->queryResult.docs;
+  RankArray &rankSet1 = setNode1->queryResult.ranks;
+  docSet1.push_back (1);  rankSet1.push_back (0.1f);
+  docSet1.push_back (10); rankSet1.push_back (0.2f);
+  docSet1.push_back (15); rankSet1.push_back (0.2f);
+  docSet1.push_back (18); rankSet1.push_back (0.4f);
+  docSet1.push_back (19); rankSet1.push_back (0.5f);
+
+  SetQueryNode *setNode2 = new SetQueryNode;
+  DocNumArray &docSet2 = setNode2->queryResult.docs;
+  RankArray &rankSet2 = setNode2->queryResult.ranks;
+  docSet2.push_back (2);  rankSet2.push_back (0.1f);
+  docSet2.push_back (11); rankSet2.push_back (0.2f);
+  docSet2.push_back (12); rankSet2.push_back (0.3f);
+  docSet2.push_back (13); rankSet2.push_back (0.4f);
+  docSet2.push_back (14); rankSet2.push_back (0.5f);
+  docSet2.push_back (15); rankSet2.push_back (0.6f);
+  docSet2.push_back (16); rankSet2.push_back (0.7f);
+  docSet2.push_back (17); rankSet2.push_back (0.8f);
+  docSet2.push_back (19); rankSet2.push_back (0.9f);
+  docSet2.push_back (20); rankSet2.push_back (0.1f);
+  docSet2.push_back (21); rankSet2.push_back (0.2f);
+
+  cout << "\n" << setNode1->queryResult << "OR\n\n"
+       << setNode2->queryResult;
+  
+
+  orNode.leftNode = setNode1;
+  orNode.rightNode = setNode2;
+
+  IndexData indexData; // this will not be used anywhere
+  QueryInfo queryInfo;
+  queryInfo.maxDocs = 0;
+  queryInfo.sortByRank = true;
+  queryInfo.needRankInfo = true;
+  queryInfo.needTermFreqs = true;
+  
+  QueryResult result;
+
+  orNode.Calculate(indexData, queryInfo, result);
+
+  cout << "EQUALS\n\n" << result << "\n";
+
+  QueryResult resultCompare;
+  DocNumArray &rcDocSet = resultCompare.docs;
+  RankArray &rcRankSet = resultCompare.ranks;
+  rcDocSet.push_back (1);  rcRankSet.push_back (0.1f);
+  rcDocSet.push_back (2);  rcRankSet.push_back (0.1f);
+  rcDocSet.push_back (10); rcRankSet.push_back (0.2f);
+  rcDocSet.push_back (11); rcRankSet.push_back (0.2f);
+  rcDocSet.push_back (12); rcRankSet.push_back (0.3f);
+  rcDocSet.push_back (13); rcRankSet.push_back (0.4f);
+  rcDocSet.push_back (14); rcRankSet.push_back (0.5f);
+  rcDocSet.push_back (15); rcRankSet.push_back (0.2f+0.6f);
+  rcDocSet.push_back (16); rcRankSet.push_back (0.7f);
+  rcDocSet.push_back (17); rcRankSet.push_back (0.8f);
+  rcDocSet.push_back (18); rcRankSet.push_back (0.4f);
+  rcDocSet.push_back (19); rcRankSet.push_back (0.9f+0.5f);
+  rcDocSet.push_back (20); rcRankSet.push_back (0.1f);
+  rcDocSet.push_back (21); rcRankSet.push_back (0.2f);
+  
+
+  if (!(result == resultCompare)) {
+    cout << "Test failed!!!\n";
+    cout << resultCompare;
+    return false;
+  }
+
+  return true;
+}
+
+bool Test2b () {
+  OrQueryNode orNode;
+
+  SetQueryNode *setNode1 = new SetQueryNode;
+  DocNumArray &docSet1 = setNode1->queryResult.docs;
+  docSet1.push_back (1); 
+  docSet1.push_back (10);
+  docSet1.push_back (15);
+  docSet1.push_back (18);
+  docSet1.push_back (19);
+
+  SetQueryNode *setNode2 = new SetQueryNode;
+  DocNumArray &docSet2 = setNode2->queryResult.docs;
+  docSet2.push_back (2);
+  docSet2.push_back (11);
+  docSet2.push_back (12);
+  docSet2.push_back (13);
+  docSet2.push_back (14);
+  docSet2.push_back (15);
+  docSet2.push_back (16);
+  docSet2.push_back (17);
+  docSet2.push_back (19);
+  docSet2.push_back (20);
+  docSet2.push_back (21);
+
+  cout << "\n" << setNode1->queryResult << "OR\n\n"
+       << setNode2->queryResult;
+  
+
+  orNode.leftNode = setNode1;
+  orNode.rightNode = setNode2;
+
+  IndexData indexData; // this will not be used anywhere
+  QueryInfo queryInfo;
+  queryInfo.maxDocs = 0;
+  queryInfo.sortByRank = false;
+  queryInfo.needRankInfo = false;
+  queryInfo.needTermFreqs = true;
+  
+  QueryResult result;
+
+  orNode.Calculate(indexData, queryInfo, result);
+
+  cout << "EQUALS\n\n" << result << "\n";
+
+  QueryResult resultCompare;
+  DocNumArray &rcDocSet = resultCompare.docs;
+  rcDocSet.push_back (1);
+  rcDocSet.push_back (2); 
+  rcDocSet.push_back (10);
+  rcDocSet.push_back (11);
+  rcDocSet.push_back (12);
+  rcDocSet.push_back (13);
+  rcDocSet.push_back (14);
+  rcDocSet.push_back (15);
+  rcDocSet.push_back (16);
+  rcDocSet.push_back (17);
+  rcDocSet.push_back (18);
+  rcDocSet.push_back (19);
+  rcDocSet.push_back (20);
+  rcDocSet.push_back (21);
+  
+
+  if (!(result == resultCompare)) {
+    cout << "Test failed!!!\n";
+    cout << resultCompare;
+    return false;
+  }
+
+  return true;
+}
+
+bool Test3 () {
+  NotQueryNode notNode;
+
+  SetQueryNode *setNode1 = new SetQueryNode;
+  DocNumArray &docSet1 = setNode1->queryResult.docs;
+  RankArray &rankSet1 = setNode1->queryResult.ranks;
+  docSet1.push_back (1);  rankSet1.push_back (0.1f);
+  docSet1.push_back (10); rankSet1.push_back (0.2f);
+  docSet1.push_back (15); rankSet1.push_back (0.2f);
+  docSet1.push_back (18); rankSet1.push_back (0.4f);
+  docSet1.push_back (19); rankSet1.push_back (0.5f);
+
+  SetQueryNode *setNode2 = new SetQueryNode;
+  DocNumArray &docSet2 = setNode2->queryResult.docs;
+  RankArray &rankSet2 = setNode2->queryResult.ranks;
+  docSet2.push_back (2);  rankSet2.push_back (0.1f);
+  docSet2.push_back (11); rankSet2.push_back (0.2f);
+  docSet2.push_back (12); rankSet2.push_back (0.3f);
+  docSet2.push_back (13); rankSet2.push_back (0.4f);
+  docSet2.push_back (14); rankSet2.push_back (0.5f);
+  docSet2.push_back (15); rankSet2.push_back (0.6f);
+  docSet2.push_back (16); rankSet2.push_back (0.7f);
+  docSet2.push_back (17); rankSet2.push_back (0.8f);
+  docSet2.push_back (19); rankSet2.push_back (0.9f);
+  docSet2.push_back (20); rankSet2.push_back (0.1f);
+  docSet2.push_back (21); rankSet2.push_back (0.2f);
+
+  cout << "\n" << setNode1->queryResult << "NOT\n\n"
+       << setNode2->queryResult;
+  
+
+  notNode.queryNode = setNode1;
+  notNode.notNode = setNode2;
+
+  IndexData indexData; // this will not be used anywhere
+  QueryInfo queryInfo;
+  queryInfo.maxDocs = 0;
+  queryInfo.sortByRank = true;
+  queryInfo.needRankInfo = true;
+  queryInfo.needTermFreqs = true;
+  
+  QueryResult result;
+
+  notNode.Calculate(indexData, queryInfo, result);
+
+  cout << "EQUALS\n\n" << result << "\n";
+
+  QueryResult resultCompare;
+  DocNumArray &rcDocSet = resultCompare.docs;
+  RankArray &rcRankSet = resultCompare.ranks;
+  rcDocSet.push_back (1);  rcRankSet.push_back (0.1);
+  rcDocSet.push_back (10); rcRankSet.push_back (0.2);
+  rcDocSet.push_back (18); rcRankSet.push_back (0.4);
+  
+
+  if (!(result == resultCompare)) {
+    cout << "Test failed!!!\n";
+    cout << resultCompare;
+    return false;
+  }
+
+  return true;
+}
+
+bool Test3b () {
+  NotQueryNode notNode;
+
+  SetQueryNode *setNode1 = new SetQueryNode;
+  DocNumArray &docSet1 = setNode1->queryResult.docs;
+  docSet1.push_back (1); 
+  docSet1.push_back (10);
+  docSet1.push_back (15);
+  docSet1.push_back (18);
+  docSet1.push_back (19);
+
+  SetQueryNode *setNode2 = new SetQueryNode;
+  DocNumArray &docSet2 = setNode2->queryResult.docs;
+  docSet2.push_back (2); 
+  docSet2.push_back (11);
+  docSet2.push_back (12);
+  docSet2.push_back (13);
+  docSet2.push_back (14);
+  docSet2.push_back (15);
+  docSet2.push_back (16);
+  docSet2.push_back (17);
+  docSet2.push_back (19);
+  docSet2.push_back (20);
+  docSet2.push_back (21);
+
+  cout << "\n" << setNode1->queryResult << "NOT\n\n"
+       << setNode2->queryResult;
+  
+
+  notNode.queryNode = setNode1;
+  notNode.notNode = setNode2;
+
+  IndexData indexData; // this will not be used anywhere
+  QueryInfo queryInfo;
+  queryInfo.maxDocs = 0;
+  queryInfo.sortByRank = false;
+  queryInfo.needRankInfo = false;
+  queryInfo.needTermFreqs = true;
+  
+  QueryResult result;
+
+  notNode.Calculate(indexData, queryInfo, result);
+
+  cout << "EQUALS\n\n" << result << "\n";
+
+  QueryResult resultCompare;
+  DocNumArray &rcDocSet = resultCompare.docs;
+  rcDocSet.push_back (1); 
+  rcDocSet.push_back (10);
+  rcDocSet.push_back (18);
+  
+
+  if (!(result == resultCompare)) {
+    cout << "Test failed!!!\n";
+    cout << resultCompare;
+    return false;
+  }
+
+  return true;
+}
+
+
+int main () {
+  if (!Test1 () ||
+      !Test2 () ||
+      !Test2b () ||
+      !Test3 () ||
+      !Test3b ()) return 1;
+  
+  return 0;
+}
Index: /indexers/branches/3.03a/mgpp/text/Queryer.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/Queryer.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/Queryer.cpp	(revision 14757)
@@ -0,0 +1,294 @@
+/**************************************************************************
+ *
+ * Queryer.cpp -- simple interactive query program
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+/* getopt is in posix.2, so cygwin should have it in unistd, but doesn't */
+#if defined (__WIN32__) || defined (__CYGWIN__)
+# include "getopt_old.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "MGQuery.h"
+#include "TextGet.h"
+
+#include "messages.h"
+#include "mg_files.h"
+
+#include "GSDLQueryParser.h"
+
+void printHelp() {
+
+  cout << "commands available are:\n"
+       << "\t.q\t\tquit\n"
+       << "\t.h\t\tprint the help message\n"
+       << "\t.i\t\tchange the search level (enter the new level at the prompt)\n"
+       << "\t.l\t\tchange the result level ( \"\"   \"\"  )\n"
+       << "\t.b\t\tfull text browse (enter a word or fragment at the prompt)\n"
+       << "\t.r0/.r1\t\tranking off/on\n"
+       << "\t.t0/.t1\t\tquery type some/all\n"
+       << "\t.c0/.c1\t\tcasefolding off/on\n"
+       << "\t.s0/.s1\t\tstemming off/on\n"
+#ifdef ENABLE_ACCENTFOLD
+       << "\t.a0/.a1\t\taccentfolding off/on\n"
+#endif
+       << "\t.o0/.o1\t\tshort output off/on\n"
+       << "\t.m\t\tset maxnumeric (enter the number at the prompt)\n\n"
+       << "\t.p\t\tprint a document (enter the docnum at the prompt)\n"
+       << "otherwise just enter a query\n\n";
+
+}
+
+int main (int argc, char **argv) {
+  int ch;
+  char *textfilename = "";
+  char *indexfilename = "";
+  char *basePath = "";
+  
+  opterr = 0;
+  msg_prefix = argv[0];
+  
+  // process the command line arguments
+  while ((ch = getopt (argc, argv, "f:t:d:h")) != -1) {
+    switch (ch) {
+    case 'f':		/* input file */
+      indexfilename = optarg;
+      break;
+    case 't':
+      textfilename = optarg;
+      break;
+    case 'd':
+      basePath = optarg;
+      set_basepath (basePath);
+      break;
+    case 'h':
+    case '?':
+      fprintf (stderr, "usage: %s [-h] [-d directory] -f indexname -t textname\n", argv[0]);
+      exit (1);
+    }
+  }
+
+  if (textfilename[0] == '\0' || indexfilename[0] == '\0') {
+    FatalError (1, "Index and text file names must be specified with -f and -t \n");
+  }
+  
+  // init the text system
+  TextData textData;
+  if (!textData.LoadData (basePath, textfilename)) {
+    FatalError (1, "Couldn't load text information for \"%s\"", textfilename);
+  }
+  
+  // init the query system
+  IndexData indexData;
+  if (!indexData.LoadData (basePath, indexfilename)) {
+    FatalError (1, "Couldn't load index information for \"%s\"", indexfilename);
+  }
+
+  int maxnumeric = 4;
+
+  // debug output
+  cerr << "num docs: "<<indexData.bdh.num_docs       
+       << "\nnum frags: "<<indexData.bdh.num_frags
+       << "\nnum words: "<<indexData.bdh.num_words
+       << "\ntotal bytes: "<<indexData.bdh.total_bytes
+       << "\nindex string bytes: "<<indexData.bdh.index_string_bytes
+       << "\nnum levels: "<<indexData.bdh.num_levels<<endl;
+  
+  // do querying
+  QueryInfo queryInfo;
+  SetCStr (queryInfo.docLevel, "Doc", 3);
+  queryInfo.maxDocs = 50;
+  queryInfo.sortByRank = true;
+  queryInfo.exactWeights = false;
+  queryInfo.needRankInfo = true;
+  queryInfo.needTermFreqs = true;
+  
+  ExtQueryResult queryResult;
+  char query[2048];
+  UCArray queryArray;
+  QueryNode *queryTree = NULL;
+
+
+  UCArray docLevel;
+  SetCStr(docLevel, "Doc", 3);
+
+  UCArray level;
+  UCArrayClear(level);
+  //SetCStr(level, "");
+   
+  int defaultStemMethod = 0; // uncasefolded, unstemmed, unaccentfolded
+  int defaultBoolCombine = 0; // OR
+  bool shortOutput = false;
+  BrowseQueryNode browseNode;
+  browseNode.startPosition = -10;
+  browseNode.numTerms = 40;
+
+  BrowseQueryResult browseResult;
+
+  while (true) {
+    cout << "> ";
+    cin.getline(query, 2048, '\n');
+    SetCStr (queryArray, query, strlen(query));
+
+    // check for commands
+    if (queryArray.size() >= 2 && queryArray[0] == '.') {
+      if (queryArray[1] == 'q') break;  // quit
+
+      if (queryArray[1] == 'h') { // help
+	printHelp();
+      } else if (queryArray[1] == 'i') {
+	cout << "current index="<< queryInfo.docLevel << "\nchange to index:";
+	cin >> query;
+	UCArrayClear(queryInfo.docLevel);
+	SetCStr(queryInfo.docLevel, query, strlen(query));
+	cout << "index set to " << queryInfo.docLevel <<"\n";
+	cin.getline(query, 2048, '\n');
+      } else if (queryArray[1] == 'l') {
+	cout << "current level="<< level << "\nchange to level:";
+	cin >> query;
+	UCArrayClear(level);
+	SetCStr(level, query, strlen(query));
+	cout << "level set to " << level <<"\n";
+	cin.getline(query, 2048, '\n');
+      }
+
+      else if (queryArray[1] == 'm') {
+	// maxnumeric
+	int m = 0;
+	cin >> m;
+	cin.getline(query, 2048, '\n'); // eat up return
+	if (4 < m < 512) {
+	  maxnumeric = m;
+	}
+      }
+      else if (queryArray[1] == 'p') {
+	// print
+	UCArray docText;
+	unsigned long docNum = 0;
+	cin >> docNum;
+	cin.getline(query, 2048, '\n'); // eat up return
+	
+	if (!GetDocText (textData, queryInfo.docLevel, docNum, docText)) {
+	  FatalError (1, "Error while trying to get document %u", docNum);
+	}
+	
+	cout << docText << "\n";
+      }
+      else if (queryArray[1] == 't') { // query type - all/some
+	if (queryArray[2] == '1') defaultBoolCombine = 1;
+	else if (queryArray[2] == '0') defaultBoolCombine = 0;
+	else {
+	  cout << "Error: please enter .t0 (some) or .t1 (all)\n";
+	}
+      }
+      else if (queryArray[1] == 'r') { // ranking - on/off
+	if (queryArray[2] == '1') queryInfo.sortByRank = true;
+	else if (queryArray[2] == '0') queryInfo.sortByRank = false;
+	else {
+	  cout << "Error: please enter .r0 (non-ranked) or .r1 (ranked)\n";
+	}
+      }
+      else if (queryArray[1] == 'c') { // casefolding - on/off
+	if (queryArray[2] == '1') defaultStemMethod |= STEM_CaseFolding;
+	else if (queryArray[2] == '0') defaultStemMethod &= (~STEM_CaseFolding);
+	else {
+	  cout << "Error: please enter .c0 (case sensitive) or .c1 (casefolded)\n";
+	}
+      }
+      else if (queryArray[1] == 's') { // stemming - on/off
+	if (queryArray[2] == '1') defaultStemMethod |= STEM_Stemming;
+	else if (queryArray[2] == '0') defaultStemMethod &= (~STEM_Stemming);
+	else {
+	  cout << "Error: please enter .s0 (unstemmed) or .s1 (stemmed)\n";
+	}
+      }      
+#ifdef ENABLE_ACCENTFOLD
+      else if (queryArray[1] == 'a') { // accentfolding - on/off
+	if (queryArray[2] == '1') defaultStemMethod |= STEM_AccentFolding;
+	else if (queryArray[2] == '0') defaultStemMethod &= (~STEM_AccentFolding);
+	else {
+	  cout << "Error: please enter .a0 (accent sensitive) or .a1 (accentfolded)\n";
+	}
+      }
+#endif
+      else if (queryArray[1] == 'o') { // output - short/long
+	if (queryArray[2] == '1') shortOutput = true;
+	else if (queryArray[2] == '0') shortOutput = false;
+	else {
+	  cout << "Error: please enter .o0 (long output) or .o1 (short output)\n";
+	}
+      }
+      else if (queryArray[1] == 'b') {
+	// full text browse
+	cout<<"enter a few letters to start browsing from:";
+	cin>>query;
+	UCArrayClear(browseNode.term);
+	SetCStr(browseNode.term, query, strlen(query));
+	cin.getline(query, 2048, '\n'); // get rest of line
+
+	// print the query
+	PrintNode (cout, &browseNode);
+
+	MGBrowseQuery(indexData, docLevel, browseNode, browseResult);
+	cout << browseResult;
+	cout << "\n";
+
+      }
+      else { // bad option
+	cout << "bad command\n\n";
+	printHelp();
+      }
+    } // if a .x query
+    else {
+      // regular query
+      queryTree = ParseQuery (queryArray, defaultBoolCombine, defaultStemMethod, maxnumeric);
+      if (queryTree == NULL) {
+	cout << "invalid syntax\n";
+      } else {
+	// print the query
+	PrintNode (cout, queryTree);
+	
+	MGQuery (indexData, queryInfo, queryTree, queryResult, level);
+	if (shortOutput) {
+	  queryResult.printShort(cout);
+	  cout << "\n";
+	} else {
+	  cout << queryResult;
+	  cout << "\n";
+	}
+	// delete the query
+	delete queryTree;
+	queryTree = NULL;
+      }
+    }
+  }
+
+
+  // clean up, everybody clean up
+  textData.UnloadData ();
+  indexData.UnloadData ();
+
+  return (0);
+}
+
+
Index: /indexers/branches/3.03a/mgpp/text/TagInfo.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/TagInfo.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/TagInfo.cpp	(revision 14757)
@@ -0,0 +1,74 @@
+/**************************************************************************
+ *
+ * TagInfo.cpp -- 
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "TagInfo.h"
+
+
+void TagInfo::SetDocTag (const char *cStr) {
+  SetCStr (docTag, cStr, strlen(cStr));
+}
+
+void TagInfo::SetIndexLevel (const char *cStr) {
+  SetCStr (indexLevel, cStr, strlen(cStr));
+}
+void TagInfo::AddLevelTag (const char *cStr) {
+  // convert the string
+  UCArray cArr;
+  SetCStr (cArr, cStr, strlen(cStr));
+
+  // insert the tag
+  levelTags.insert (cArr);
+}
+
+
+TagInfo::TagInfo () {
+  Clear ();
+}
+
+void TagInfo::Clear () {
+  docTag.erase (docTag.begin(), docTag.end());
+  indexLevel.erase (indexLevel.begin(), indexLevel.end());
+  levelTags.erase (levelTags.begin(), levelTags.end());
+}
+
+ostream &operator<<(ostream &s, const TagInfo &t) {
+  // output docTag
+  s << "docTag: \"" << t.docTag << "\"\n";
+
+  // output indexLevel
+  s << "indexLevel: \"" << t.indexLevel << "\"\n";
+
+  // output levelTags
+  s << "levelTags: ";
+
+  UCArraySet::const_iterator here = t.levelTags.begin();
+  UCArraySet::const_iterator end = t.levelTags.end();
+  while (here != end) {
+    s << "\"" << (*here) << "\"";
+    ++here;
+    if (here != end) s << ", ";
+  }
+
+  s << "\n";
+  
+  return s;
+}
+
Index: /indexers/branches/3.03a/mgpp/text/TagInfo.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/TagInfo.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/TagInfo.h	(revision 14757)
@@ -0,0 +1,46 @@
+/**************************************************************************
+ *
+ * TagInfo.h -- 
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef TAGINFO_H
+#define TAGINFO_H
+
+#include "UCArray.h"
+
+
+class TagInfo {
+public:
+  UCArray docTag;
+  UCArray indexLevel;    // empty for word level index
+  UCArraySet levelTags;
+
+  void SetDocTag (const char *cStr);
+  void SetIndexLevel (const char *cStr);
+  void AddLevelTag (const char *cStr);
+  
+  TagInfo ();
+  void Clear ();
+};
+
+// stream operator to print TagInfo
+ostream &operator<<(ostream &s, const TagInfo &t);
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/Terms.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/Terms.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/Terms.cpp	(revision 14757)
@@ -0,0 +1,791 @@
+/**************************************************************************
+ *
+ * Terms.cpp -- Query related functions
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "Terms.h"
+#include "words.h"
+#include "stemmer.h"
+#include "bitio_gen.h"
+#include "bitio_m_stdio.h"
+
+void QueryInfo::Clear () {
+  UCArrayClear (docLevel);
+  maxDocs = 0;
+  sortByRank = true;
+  exactWeights = false;
+  needRankInfo = false;
+  needTermFreqs = false;
+}
+
+
+
+void TermFreqData::Clear () {
+  UCArrayClear (tag);
+  UCArrayClear (term);
+  equivTerms.erase(equivTerms.begin(), equivTerms.end());
+  stemMethod = 0;
+  matchDocs = 0;
+  termFreq = 0;
+}
+
+ostream &operator<< (ostream &s, const TermFreqData &t) {
+  s << "<" << t.tag << ">\"" << t.term << "\"stem("
+    << t.stemMethod << ")equiv terms(";
+  
+  unsigned long i;
+  for (i=0; i<t.equivTerms.size(); ++i) {
+    s << t.equivTerms[i] << ", ";
+  }
+  s <<")docs(" << t.matchDocs << ")"
+    << "count("<<t.termFreq<<")";
+  return s;
+}
+
+bool operator== (const TermFreqData &t1, const TermFreqData &t2) {
+  return ((t1.tag == t2.tag) &&
+	  (t1.term == t2.term) &&
+	  (t1.stemMethod == t2.stemMethod) &&
+	  (t1.equivTerms == t2.equivTerms) &&
+	  (t1.matchDocs == t2.matchDocs) &&
+	  (t1.termFreq == t2.termFreq));
+}
+
+
+void QueryResult::Clear () {
+  docs.erase (docs.begin(), docs.end());
+  ranks.erase (ranks.begin(), ranks.end());
+  termFreqs.erase (termFreqs.begin(), termFreqs.end());
+  actualNumDocs = 0;
+}
+
+QueryResult::QueryResult () {
+  Clear ();
+}
+
+void QueryResult::printShort(ostream &s) {
+
+  s << "termFreqs: ";
+  for (unsigned long i=0; i<termFreqs.size(); ++i)
+    s << termFreqs[i] << ", ";
+  
+  s << "\nactual number of docs found: " << actualNumDocs;
+  s << "\n\n";
+
+}
+
+
+ostream &operator<< (ostream &s, const QueryResult &r) {
+  s << "docs: ";
+  unsigned long i;
+  for (i=0; i<r.docs.size(); ++i)
+    s << r.docs[i] << ", ";
+  
+  s << "\nranks: ";
+  for (i=0; i<r.ranks.size(); ++i)
+    s << r.ranks[i] << ", ";
+
+  s << "\ntermFreqs: ";
+  for (i=0; i<r.termFreqs.size(); ++i)
+    s << r.termFreqs[i] << ", ";
+
+  s << "\nactual number of docs found: " << r.actualNumDocs;
+  s << "\n\n";
+
+  return s;
+}
+
+
+bool operator== (const QueryResult &r1, const QueryResult &r2) {
+  return ((r1.docs == r2.docs) &&
+	  (r1.ranks == r2.ranks) &&
+	  (r1.termFreqs == r2.termFreqs) &&
+	  (r1.actualNumDocs == r2.actualNumDocs));
+}
+
+//---------------------------------------------------
+// new ExtQueryResult stuff
+void ExtQueryResult::Clear () {
+  docs.erase (docs.begin(), docs.end());
+  levels.erase (levels.begin(), levels.end());
+  ranks.erase (ranks.begin(), ranks.end());
+  termFreqs.erase (termFreqs.begin(), termFreqs.end());
+  actualNumDocs = 0;
+}
+
+ExtQueryResult::ExtQueryResult () {
+  Clear ();
+}
+
+ostream &operator<< (ostream &s, const ExtQueryResult &r) {
+  s << "docs: ";
+  unsigned long i;
+  for (i=0; i<r.docs.size(); ++i)
+    s << r.docs[i] << ", ";
+
+  s << "\nlevels: ";
+  for (i=0; i<r.levels.size(); ++i)
+    s << r.levels[i] << ", ";
+
+  
+  s << "\nranks: ";
+  for (i=0; i<r.ranks.size(); ++i)
+    s << r.ranks[i] << ", ";
+
+  s << "\ntermFreqs: ";
+  for (i=0; i<r.termFreqs.size(); ++i)
+    s << r.termFreqs[i] << ", ";
+  s << "\nactual number of docs found: " << r.actualNumDocs;
+  s << "\n\n";
+
+  return s;
+}
+
+
+bool operator== (const ExtQueryResult &r1, const ExtQueryResult &r2) {
+  return ((r1.docs == r2.docs) &&
+	  (r1.levels == r2.levels) &&
+	  (r1.ranks == r2.ranks) &&
+	  (r1.termFreqs == r2.termFreqs) &&
+	  (r1.actualNumDocs == r2.actualNumDocs));
+}
+
+//-------------------------------------------------------
+// new BrowseQueryResult stuff
+void BrowseQueryResult::Clear () {
+  termFreqs.erase (termFreqs.begin(), termFreqs.end());
+}
+
+BrowseQueryResult::BrowseQueryResult () {
+  Clear ();
+}
+
+
+
+ostream &operator<< (ostream &s, const BrowseQueryResult &r) {
+  s << "terms: ";
+  unsigned long i;
+  for (i=0; i<r.termFreqs.size(); ++i)
+    s << r.termFreqs[i] << ", ";
+    s << "\n\n";
+  return s;
+}
+
+
+bool operator== (const BrowseQueryResult &r1, const BrowseQueryResult &r2) {
+  return ((r1.termFreqs == r2.termFreqs));
+	 
+}
+
+
+
+
+//--------------------------------------
+void FragData::Clear () {
+  matchDocs = 0;
+  fragNums.erase (fragNums.begin(), fragNums.end());
+  fragFreqs.erase (fragFreqs.begin(), fragFreqs.end());
+}
+
+
+void FindWordNumbers (IndexData &indexData,
+		      const UCArray &term,
+		      unsigned long stemMethod,
+		      vector<unsigned long> &equivWords) {
+  equivWords.erase (equivWords.begin(), equivWords.end());
+
+  // if the stem method specified is not a valid one (i.e. there was no appropriate stem index, then we set it to 0)
+  // unless we have partial matching, in which case we are not doing stem indexes anyway.
+  if (!(stemMethod & STEM_PARTIAL_MATCH) && indexData.stemFile[stemMethod-1] == NULL) {
+    cerr << "Stem index for method "<<stemMethod<< " was not built, so not doing stemming\n";
+    stemMethod = 0;
+  }
+  /* [JFG - Mar 06: Accent folding patch] */
+  /* use flag PARTIAL_MATCH */  
+  if (stemMethod == 0 || (stemMethod & STEM_PARTIAL_MATCH)) {
+    // don't need to stem the word,
+    // find the word number(s) for this term
+    unsigned long wordElNum = 0;
+    unsigned long numLevels = indexData.bdh.num_levels;
+    word_block_dict_el wordDictEl;
+    wordDictEl.SetNumLevels (numLevels);
+    if (stemMethod == 0) {
+      if (SearchWordBlockDictEl (indexData.dictFile, indexData.biWords,
+				 indexData.bdh.entries_per_wblk,
+				 indexData.bdh.word_dict_size,
+				 numLevels, term, wordDictEl, wordElNum))
+	equivWords.push_back (wordElNum);
+      
+      return;
+    } else {
+      // partial matching,
+      PartialMatchSearchWordBlockDictEl (indexData.dictFile, indexData.biWords, indexData.bdh.entries_per_wblk, indexData.bdh.word_dict_size, numLevels, term, wordDictEl, equivWords, (stemMethod & STEM_CaseFolding)? true : false);
+      // TODO: Accent Folding is not handled here!!
+      return;
+    }
+  }
+		      
+  // need to stem this word and find it in the blocked stem index
+  unsigned char mgWord[MAXSTEMLEN + 1];
+  UCArray stemTerm;
+  unsigned long stemmerNum = 0;
+
+  /* [JFG - Mar 06: Accent folding patch] */
+  if(stemMethod > STEM_MAX) {
+    return;
+    //TODO: throw an error here
+  }
+
+  stemmerNum = indexData.sih[stemMethod-1].stemmer_num;
+  
+  // convert the word to an "mg word"
+  mgWord[0] = term.size();
+  memcpy ((char *)&mgWord[1], &(term[0]), term.size());
+  
+  // stem the word
+  mgpp_stemmer (stemMethod, stemmerNum, mgWord);
+  // convert the result back to a UCArray
+  stemTerm.insert (stemTerm.end(), &mgWord[1], &mgWord[1] + mgWord[0]);
+
+  // need to look up this term in the appropriate dictionary
+  stem_block_dict_el stemDictEl;
+  unsigned long stemElNum;
+  bool result = false;
+  
+  /* [JFG - Mar 06: Accent folding patch] */
+  result = SearchStemBlockDictEl (indexData.stemFile[stemMethod-1],
+			   indexData.sii[stemMethod-1],
+			   indexData.sih[stemMethod-1].entries_per_block,
+			   indexData.sih[stemMethod-1].dict_size,
+			   stemTerm,
+			   stemDictEl,
+			   stemElNum);
+  
+  if (result) {
+    equivWords = stemDictEl.equivWords;  
+  }
+}
+
+
+
+void ReadTermFragData (IndexData &indexData,
+		       bool needFragFreqs,
+		       unsigned long termNum,
+		       FragData &fragData,
+		       FragRangeArray *fragLimits,
+		       UCArray & termWord) {
+  fragData.Clear();
+
+  // look up the word in the dictionary
+  unsigned long numLevels = indexData.bdh.num_levels;
+  word_block_dict_el wordDictEl;
+  wordDictEl.SetNumLevels (numLevels);
+  if (!SearchWordBlockDictElNum (indexData.dictFile,
+				 indexData.biWords,
+				 indexData.bdh.entries_per_wblk,
+				 indexData.bdh.word_dict_size,
+				 numLevels,
+				 termNum, wordDictEl))
+    return; // nothing more to do
+
+  fragData.matchDocs = wordDictEl.levelFreqs[indexData.curLevelNum];
+  termWord = wordDictEl.el;
+  // seek to the appropriate place in the inverted file
+  fseek (indexData.invfFile, wordDictEl.invf_ptr, SEEK_SET);
+  stdio_bitio_buffer buffer (indexData.invfFile);
+    
+  unsigned long B = BIO_Bblock_Init (indexData.bdh.num_frags,
+				     wordDictEl.frag_occur);
+  unsigned long fragNum = 0;
+  unsigned long termFreq = 0;
+
+  unsigned long fragLimitI = 0;
+  unsigned long i;
+  for (i=0; i<wordDictEl.frag_occur; ++i) {
+    fragNum += buffer.bblock_decode (B, NULL);
+    if (!indexData.ifh.word_level_index) termFreq = buffer.gamma_decode (NULL);
+    else termFreq = 1;
+
+    // get the right fragment range
+    if (fragLimits != NULL) {
+      while (fragLimitI+1 < (*fragLimits).size() &&
+	     fragNum > (*fragLimits)[fragLimitI+1].rangeStart) {
+	++fragLimitI;
+      }
+    }
+
+    // add the entry if it is within the limits
+    if ((fragLimits == NULL) ||
+	(fragLimitI < (*fragLimits).size() &&
+	 fragNum > (*fragLimits)[fragLimitI].rangeStart &&
+	 fragNum <= (*fragLimits)[fragLimitI].rangeEnd)) {
+      fragData.fragNums.push_back (fragNum);
+      if (needFragFreqs)
+	fragData.fragFreqs.push_back (termFreq);
+    }
+  }
+
+  buffer.done();
+}
+
+
+void CombineFragData (bool needFragFreqs,
+		      const FragData &f1,
+		      const FragData &f2,
+		      FragData &outFragData) {
+  outFragData.Clear();
+
+  // the new number of matching documents is the maximum
+  // of the two input matching number of documents -- it
+  // is assumed that these are at the same document level
+  outFragData.matchDocs = (f1.matchDocs > f2.matchDocs) ?
+    f1.matchDocs : f2.matchDocs;
+
+  // do or
+  unsigned long f1I = 0, f1Size = f1.fragNums.size();
+  unsigned long f2I = 0, f2Size = f2.fragNums.size();
+  while (f1I < f1Size || f2I < f2Size) {
+    if (f2I < f2Size &&
+	(f1I >= f1Size ||
+	 f1.fragNums[f1I] > f2.fragNums[f2I])) {
+      // output f2I
+      outFragData.fragNums.push_back (f2.fragNums[f2I]);
+      if (needFragFreqs)
+	outFragData.fragFreqs.push_back (f2.fragFreqs[f2I]);
+      ++f2I;
+      
+    } else if (f1I < f1Size &&
+	       (f2I >= f2Size ||
+		f1.fragNums[f1I] < f2.fragNums[f2I])) {
+      // output f1I
+      outFragData.fragNums.push_back (f1.fragNums[f1I]);
+      if (needFragFreqs)
+	outFragData.fragFreqs.push_back (f1.fragFreqs[f1I]);
+      ++f1I;
+      
+    } else {
+      // must be equal combine f1I and f2I
+      outFragData.fragNums.push_back (f1.fragNums[f1I]);
+      if (needFragFreqs)
+	outFragData.fragFreqs.push_back (f1.fragFreqs[f1I]+f2.fragFreqs[f2I]);
+      ++f1I;
+      ++f2I;
+    }
+  }
+}
+
+
+void AndCombineFragData (bool needFragFreqs,
+			 FragData &fragData,
+			 const FragData &comFragData,
+			 signed long startRange,
+			 signed long endRange,
+			 const FragRangeArray *fragLimits) {
+  // sanity check on range
+  if (startRange > endRange) {
+    signed long temp = endRange;
+    endRange = startRange;
+    startRange = temp;
+  }
+
+  // get min matchdocs
+  if (comFragData.matchDocs < fragData.matchDocs)
+    fragData.matchDocs = comFragData.matchDocs;
+  
+  unsigned long fragDataI = 0;
+  unsigned long fragDataSize = fragData.fragNums.size();
+  unsigned long comFragDataI = 0;
+  unsigned long comFragDataSize = comFragData.fragNums.size();
+  unsigned long fragLimitI = 0;
+  unsigned long fragLimitSize = (fragLimits==NULL) ? 0 : (*fragLimits).size();
+  unsigned long outI = 0;
+
+  while (fragDataI < fragDataSize &&
+	 comFragDataI < comFragDataSize) {
+    signed long fragNum = (signed long)fragData.fragNums[fragDataI];
+    signed long comFragNum = (signed long)comFragData.fragNums[comFragDataI];
+    
+    // go to the right fragment limit (for the com frag)
+    if (fragLimits != NULL) {
+      while (fragLimitI+1 < fragLimitSize &&
+	     comFragNum > (signed long)(*fragLimits)[fragLimitI+1].rangeStart) {
+	++fragLimitI;
+      }
+    }
+
+    if (fragNum <= comFragNum+startRange ||
+	(fragLimits!=NULL &&
+	 fragNum<=(signed long)(*fragLimits)[fragLimitI].rangeStart)) {
+      ++fragDataI;
+      
+    } else if (fragNum > comFragNum+endRange ||
+	       (fragLimits!=NULL &&
+		fragNum>(signed long)(*fragLimits)[fragLimitI].rangeEnd)) {
+      ++comFragDataI;
+      
+    } else {
+      // equal and within tag
+      fragData.fragNums[outI] = comFragNum;
+      if (needFragFreqs) {
+	fragData.fragFreqs[outI] =
+	  (fragData.fragFreqs[fragDataI] < comFragData.fragFreqs[comFragDataI]) ?
+	  fragData.fragFreqs[fragDataI] : comFragData.fragFreqs[comFragDataI];
+      }
+      ++fragDataI;
+      ++comFragDataI;
+      ++outI;
+    }
+  }
+
+  // erase unused part of fragData
+  fragData.fragNums.erase (fragData.fragNums.begin()+outI,
+			   fragData.fragNums.end());
+  if (needFragFreqs)
+    fragData.fragFreqs.erase (fragData.fragFreqs.begin()+outI,
+			      fragData.fragFreqs.end());
+  else
+    fragData.fragFreqs.erase (fragData.fragFreqs.begin(),
+			      fragData.fragFreqs.end());
+}
+
+
+void FragsToQueryResult (IndexData &indexData,
+			 const QueryInfo &queryInfo,
+			 const FragData &termData,
+			 const UCArray &tag,
+			 const UCArray &term,
+			 unsigned long stemMethod,
+			 unsigned long termWeight,
+			 UCArrayVector &equivTerms,
+			 QueryResult &result) {
+  bool needRanks = (queryInfo.sortByRank || queryInfo.needRankInfo);
+  
+  result.Clear();
+
+  // log (N / ft)
+  unsigned long N = indexData.levels.levelInfo[indexData.curLevel].numEntries;
+  float wordLog = log((double)N / (double)termData.matchDocs);
+
+  // Wqt = fqt * log (N / ft)
+  // note: terms are allowed to have a weight of zero so
+  // they can be excluded from the ranking
+  float Wqt = termWeight * wordLog;
+
+  // Wdt = fdt * log (N / ft)
+  float Wdt;
+  
+  unsigned long termDataI = 0;
+  unsigned long termDataSize = termData.fragNums.size();
+  unsigned long levelDocNum = 0;
+  
+  unsigned long termDocFreq = 0;
+  unsigned long lastLevelDocNum = 0;
+  unsigned long overallwordfreq = 0;
+  
+  while (termDataI < termDataSize) {
+    if (indexData.levelConverter.FragToLevel (termData.fragNums[termDataI],
+					      levelDocNum)) {
+      if (levelDocNum != lastLevelDocNum) {
+	if (lastLevelDocNum > 0) {
+	  // add this doc information
+	  if (needRanks) {
+	    Wdt = termDocFreq * wordLog;
+	    result.ranks.push_back (Wqt * Wdt);
+	  }
+	  result.docs.push_back (lastLevelDocNum);
+	}
+	
+	lastLevelDocNum = levelDocNum;
+	termDocFreq = 0;
+      }
+
+      if (needRanks){
+	termDocFreq += termData.fragFreqs[termDataI];
+	overallwordfreq += termData.fragFreqs[termDataI];
+      }
+    }
+    ++termDataI;
+  }
+
+  if (lastLevelDocNum > 0) {
+    // add the last document information
+    if (needRanks) {
+      Wdt = termDocFreq * wordLog;
+      result.ranks.push_back (Wqt * Wdt);
+    }
+    result.docs.push_back (lastLevelDocNum);
+  }
+
+  // add the term frequency information
+  if (queryInfo.needTermFreqs) {
+    TermFreqData termFreqData;
+    termFreqData.tag = tag;
+    termFreqData.term = term;
+    termFreqData.stemMethod = stemMethod;
+    termFreqData.equivTerms = equivTerms;
+    termFreqData.matchDocs = termData.matchDocs;
+    termFreqData.termFreq = overallwordfreq; // will be zero if needRankInfo 
+                                              //not true
+    result.termFreqs.push_back (termFreqData);
+  }
+}
+
+void AndFragsToQueryResult (IndexData &indexData,
+			    const QueryInfo &queryInfo,
+			    const FragData &termData,
+			    const UCArray &tag,
+			    const UCArray &term,
+			    unsigned long stemMethod,
+			    unsigned long termWeight,
+			    UCArrayVector &equivTerms,
+			    QueryResult &result) {
+  bool needRanks = (queryInfo.sortByRank || queryInfo.needRankInfo);
+  
+  // log (N / ft)
+  float wordLog =
+    log((double)indexData.levels.levelInfo[indexData.curLevel].numEntries/
+	(double)termData.matchDocs);
+
+  // Wqt = fqt * log (N / ft)
+  // note: terms are allowed to have a weight of zero so
+  // they can be excluded from the ranking
+  float Wqt = termWeight * wordLog;
+
+  // Wdt = fdt * log (N / ft)
+  float Wdt;
+  
+  unsigned long termDataI = 0;
+  unsigned long termDataSize = termData.fragNums.size();
+  unsigned long levelDocNum = 0;
+  
+  unsigned long termDocFreq = 0;
+  unsigned long lastLevelDocNum = 0;
+  unsigned long overallwordfreq = 0;
+  unsigned long resultI = 0;
+  unsigned long resultSize = result.docs.size();
+  unsigned long resultOutI = 0;
+  
+  
+  while (termDataI < termDataSize) {
+    if (indexData.levelConverter.FragToLevel (termData.fragNums[termDataI],
+					      levelDocNum)) {
+      if (levelDocNum != lastLevelDocNum) {
+	if (lastLevelDocNum > 0) {
+	  // add this doc information
+	  Wdt = termDocFreq * wordLog;
+	  
+	  // find this document number
+	  while (resultI < resultSize &&
+		 result.docs[resultI] < lastLevelDocNum)
+	    ++resultI;
+	  
+	  // store the result
+	  if (resultI < resultSize && result.docs[resultI] == lastLevelDocNum) {
+	    result.docs[resultOutI] = lastLevelDocNum;
+	    if (needRanks)
+	      result.ranks[resultOutI] = result.ranks[resultI] + Wqt * Wdt;
+	    ++resultI;
+	    ++resultOutI;
+	  }
+	}
+	
+	lastLevelDocNum = levelDocNum;
+	termDocFreq = 0;
+      }
+
+      if (needRanks)
+	termDocFreq += termData.fragFreqs[termDataI];
+     overallwordfreq += termData.fragFreqs[termDataI]; 
+    }
+    
+    ++termDataI;
+  } // while
+
+  if (lastLevelDocNum > 0) {
+    // add the last document information
+    Wdt = termDocFreq * wordLog;
+
+    // find this document number
+    while (resultI < resultSize &&
+	   result.docs[resultI] < lastLevelDocNum)
+      ++resultI;
+    
+    // store the result
+    if (resultI < resultSize && result.docs[resultI] == lastLevelDocNum) {
+      result.docs[resultOutI] = lastLevelDocNum;
+      if (needRanks)
+	result.ranks[resultOutI] = result.ranks[resultI] + Wqt * Wdt;
+      ++resultI;
+      ++resultOutI;
+    }
+  }
+
+  // remove unneeded entries
+  result.docs.erase (result.docs.begin()+resultOutI, result.docs.end());
+  if (needRanks)
+    result.ranks.erase (result.ranks.begin()+resultOutI, result.ranks.end());
+  else
+    result.ranks.erase (result.ranks.begin(), result.ranks.end());
+  
+  // add the term frequency information
+  if (queryInfo.needTermFreqs) {
+    TermFreqData termFreqData;
+    termFreqData.tag = tag;
+    termFreqData.term = term;
+    termFreqData.stemMethod = stemMethod;
+    termFreqData.equivTerms = equivTerms;
+    termFreqData.matchDocs = termData.matchDocs;
+    termFreqData.termFreq = overallwordfreq;
+    result.termFreqs.push_back (termFreqData);
+  }
+}
+
+
+void RemoveUnwantedResults (IndexData &indexData,
+			    const QueryInfo &queryInfo,
+			    const FragData &termData,
+			    QueryResult &result) {
+  bool needRanks = (queryInfo.sortByRank || queryInfo.needRankInfo);
+
+  unsigned long termDataI = 0;
+  unsigned long termDataSize = termData.fragNums.size();
+  unsigned long levelDocNum = 0;
+  
+  unsigned long lastLevelDocNum = 0;
+
+  unsigned long resultI = 0;
+  unsigned long resultSize = result.docs.size();
+  unsigned long resultOutI = 0;
+  
+  while (termDataI < termDataSize) {
+    if (indexData.levelConverter.FragToLevel (termData.fragNums[termDataI],
+					      levelDocNum)) {
+      if (levelDocNum != lastLevelDocNum) {
+	if (lastLevelDocNum > 0) {
+	  // find this document number
+	  while (resultI < resultSize &&
+		 result.docs[resultI] < lastLevelDocNum)
+	    ++resultI;
+	  
+	  // store the result
+	  if (resultI < resultSize && result.docs[resultI] == lastLevelDocNum) {
+	    result.docs[resultOutI] = lastLevelDocNum;
+	    if (needRanks)
+	      result.ranks[resultOutI] = result.ranks[resultI];
+	    ++resultI;
+	    ++resultOutI;
+	  }
+	}
+	
+	lastLevelDocNum = levelDocNum;
+      }
+    }
+    
+    ++termDataI;
+  }
+
+  if (lastLevelDocNum > 0) {
+    // find this document number
+    while (resultI < resultSize &&
+	   result.docs[resultI] < lastLevelDocNum)
+      ++resultI;
+    
+    // store the result
+    if (resultI < resultSize && result.docs[resultI] == lastLevelDocNum) {
+      result.docs[resultOutI] = lastLevelDocNum;
+      if (needRanks) 
+	result.ranks[resultOutI] = result.ranks[resultI];
+      ++resultI;
+      ++resultOutI;
+    }
+  }
+
+  // remove unneeded entries
+  result.docs.erase (result.docs.begin()+resultOutI, result.docs.end());
+  if (needRanks)
+    result.ranks.erase (result.ranks.begin()+resultOutI, result.ranks.end());
+  else
+    result.ranks.erase (result.ranks.begin(), result.ranks.end());
+}
+
+
+
+//--------------------------------------------------------------
+// functions to support full text browse
+
+void FindNearestWordNumber (IndexData &indexData,
+			    const UCArray &term,
+			    unsigned long &number) {
+
+    // find the word number for this term
+    unsigned long wordElNum = 0;
+    unsigned long numLevels = indexData.bdh.num_levels;
+    word_block_dict_el wordDictEl;
+    wordDictEl.SetNumLevels (numLevels);
+    if (NearestSearchWordBlockDictEl (indexData.dictFile, indexData.biWords,
+				      indexData.bdh.entries_per_wblk,
+				      indexData.bdh.word_dict_size,
+				      numLevels, term, wordDictEl, wordElNum))
+      number = wordElNum;
+
+}
+
+void GetTermList(IndexData &indexData,
+		 unsigned long startTerm,
+		 unsigned long numTerms,
+		 TermFreqArray &terms) {
+
+  word_block_dict_el_array wordBlocks; // = new word_block_dict_el_array();
+  TermFreqData termdata;
+
+  terms.erase(terms.begin(), terms.end());
+
+  SearchWordBlockDictElNumRange (indexData.dictFile, indexData.biWords,
+				 indexData.bdh.entries_per_wblk,
+				 indexData.bdh.word_dict_size,
+				 indexData.bdh.num_levels, startTerm,
+				 numTerms, wordBlocks);
+
+  word_block_dict_el_array::iterator here = wordBlocks.begin();
+  word_block_dict_el_array::iterator end = wordBlocks.end();
+
+  while (here != end) {
+    termdata.Clear();
+    termdata.term = (*here).el;
+    termdata.termFreq = (*here).freq;
+    terms.push_back(termdata);
+    ++here;
+  }
+
+}
+
+void GetTermList(IndexData &indexData,
+		 unsigned long startTerm,
+		 unsigned long numTerms,
+		 UCArrayVector &terms) {
+
+  
+  
+  SearchWordBlockDictElNumRange (indexData.dictFile, indexData.biWords,
+				 indexData.bdh.entries_per_wblk,
+				 indexData.bdh.word_dict_size,
+				 indexData.bdh.num_levels, startTerm,
+				 numTerms, terms);
+
+}
Index: /indexers/branches/3.03a/mgpp/text/Terms.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/Terms.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/Terms.h	(revision 14757)
@@ -0,0 +1,215 @@
+/**************************************************************************
+ *
+ * Terms.h -- Query related functions
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef TERMS_H
+#define TERMS_H
+
+#include "IndexData.h"
+
+#if defined(GSDL_USE_OBJECTSPACE)
+#  include <ospace\std\iostream>
+#elif defined(GSDL_USE_IOS_H)
+#  include <iostream.h>
+#else
+#  include <iostream>
+#endif
+
+
+class QueryInfo {
+public:
+  // general query information
+  UCArray docLevel;
+  unsigned long maxDocs; // 0 = all
+  bool sortByRank;
+  bool exactWeights;
+
+  // information need to return
+  bool needRankInfo;
+  bool needTermFreqs;
+
+  void Clear ();
+  QueryInfo () { Clear (); }
+};
+
+
+class TermFreqData {
+public:
+  UCArray tag;  // level tag or query tag
+  UCArray term; // unstemmed term
+  int stemMethod;
+  UCArrayVector equivTerms; // the stemmed and casefolded variants of the term
+  unsigned long matchDocs; // tf for level - num levels
+			   // containing this term
+  unsigned long termFreq;  // overall term freq - num words that
+				// are this term
+  void Clear ();
+  TermFreqData () { Clear (); }
+};
+
+ostream &operator<< (ostream &s, const TermFreqData &t);
+bool operator== (const TermFreqData &t1, const TermFreqData &t2);
+
+typedef vector<TermFreqData> TermFreqArray;
+
+
+typedef vector<float> RankArray;
+typedef vector<unsigned long> DocNumArray;
+
+class QueryResult {
+public:
+  DocNumArray docs;
+  RankArray ranks; // used for accumulators during query
+  
+  TermFreqArray termFreqs;
+
+  unsigned long actualNumDocs;
+  void Clear ();
+  QueryResult ();
+  void printShort(ostream &s);
+};
+
+ostream &operator<< (ostream &s, const QueryResult &r);
+bool operator== (const QueryResult &r1, const QueryResult &r2);
+
+typedef vector<unsigned long> FragNumArray;
+typedef vector<unsigned long> FragFreqArray;
+
+class FragData {
+public:
+  unsigned long matchDocs;    // ft for level
+  FragNumArray fragNums;
+  FragFreqArray fragFreqs;
+
+  void Clear ();
+  FragData () { Clear (); }
+};
+
+
+class FragRange {
+public:
+  unsigned long rangeStart;
+  unsigned long rangeEnd;
+
+  void Clear () { rangeStart = rangeEnd = 0; }
+  FragRange () { Clear (); }
+};
+
+typedef vector<FragRange> FragRangeArray;
+
+
+
+void FindWordNumbers (IndexData &indexData,
+		      const UCArray &term,
+		      unsigned long stemMethod,
+		      vector<unsigned long> &equivWords);
+
+void ReadTermFragData (IndexData &indexData,
+		       bool needFragFreqs,
+		       unsigned long termNum,
+		       FragData &fragData,
+		       FragRangeArray *fragLimits,
+		       UCArray &termWord);
+
+void CombineFragData (bool needFragFreqs,
+		      const FragData &f1,
+		      const FragData &f2,
+		      FragData &outFragData);
+
+// output will be in fragData (as this is an and operation)
+void AndCombineFragData (bool needFragFreqs,
+			 FragData &fragData,
+			 const FragData &comFragData,
+			 signed long startRange,
+			 signed long endRange,
+			 const FragRangeArray *fragLimits);
+
+void FragsToQueryResult (IndexData &indexData,
+			 const QueryInfo &queryInfo,
+			 const FragData &termData,
+			 const UCArray &tag,
+			 const UCArray &term,
+			 unsigned long stemMethod,
+			 unsigned long termWeight,
+			 UCArrayVector &equivTerms,
+			 QueryResult &result);
+
+void AndFragsToQueryResult (IndexData &indexData,
+			    const QueryInfo &queryInfo,
+			    const FragData &termData,
+			    const UCArray &tag,
+			    const UCArray &term,
+			    unsigned long stemMethod,
+			    unsigned long termWeight,
+			    UCArrayVector &equivTerms,
+			    QueryResult &result);
+
+void RemoveUnwantedResults (IndexData &indexData,
+			    const QueryInfo &queryInfo,
+			    const FragData &termData,
+			    QueryResult &result);
+
+//-----------------------------------------------------------------
+// new QueryResult class to handle retrieval of doc and level nums.
+// Use this class with extended version of MGQuery
+
+class ExtQueryResult : public QueryResult {
+public:
+  DocNumArray levels; // used for returning a different granularity, eg
+  // search sections but return Document numbers, or search Documents, 
+  // return Section numbers.
+ 
+  void Clear ();
+  ExtQueryResult ();
+};
+
+ostream &operator<< (ostream &s, const ExtQueryResult &r);
+bool operator== (const ExtQueryResult &r1, const ExtQueryResult &r2);
+
+//------------------------------------------------------------
+// new functions to handle full text browse
+
+class BrowseQueryResult {
+ public:
+  TermFreqArray termFreqs;
+  void Clear();
+  BrowseQueryResult ();
+
+};
+
+
+ostream &operator<< (ostream &s, const BrowseQueryResult &r);
+bool operator== (const BrowseQueryResult &r1, const BrowseQueryResult &r2);
+
+void FindNearestWordNumber (IndexData &indexData,
+			    const UCArray &term,
+			    unsigned long &number);
+
+void GetTermList(IndexData &indexData,
+		 unsigned long startTerm,
+		 unsigned long numTerms,
+		 TermFreqArray &terms);
+
+void GetTermList (IndexData &indexData,
+		 unsigned long startTerm,
+		 unsigned long numTerms,
+		 UCArrayVector &terms);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/TextEl.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/TextEl.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/TextEl.cpp	(revision 14757)
@@ -0,0 +1,374 @@
+/**************************************************************************
+ *
+ * TextEl.cpp -- Data structures for parsed documents
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "TextEl.h"
+#include "ctype.h"
+
+#define REC_TERM   '\002'
+#define PARA_TERM  '\003'
+
+
+void TextEl::Clear () {
+  elType = TextE;
+  tagName.erase (tagName.begin(), tagName.end());
+  text.erase (text.begin(), text.end());
+}
+
+
+static bool ReadTextTag (FileBuf &buf, TextEl &el) {
+  // we must have some sort of tag
+  unsigned char c;
+  if (!buf.Peek(c)) return false;
+  
+  // get the '<'
+  if (c != '<') return false;
+  el.text.push_back (c);
+  if (!buf.Next() || !buf.Peek (c)) return false;
+  
+  // see if we have a '/'
+  if (c == '/') {
+    // we have a closing tag
+    el.text.push_back (c);
+    if (!buf.Next() || !buf.Peek (c)) return false;
+    el.elType = CloseTagE;
+  } else {
+    // we have an opening tag
+    el.elType = OpenTagE;
+  }
+
+  // get the tag name
+  while (isalnum(c)) {
+    el.text.push_back (c);
+    el.tagName.push_back (c);
+    if (!buf.Next() || !buf.Peek (c)) return false;
+  }
+  
+  // get everything up to the closing '>'
+  while (c != '>') {
+    el.text.push_back (c);
+    if (!buf.Next() || !buf.Peek (c)) return false;
+  }
+
+  // get the closing '>'
+  el.text.push_back (c);
+  buf.Next();
+
+  // if there is no tag name then make this a text element
+  if (el.tagName.empty()) el.elType = TextE;
+  
+  return true;
+}
+
+static bool ReadTextTag (u_char ** buffer, TextEl &el) {
+  // we must have some sort of tag
+  u_char * buffer_pos = *buffer;
+  if (*buffer_pos == '\0' || *buffer_pos != '<') {
+     return false;
+  }
+  el.text.push_back('<');
+  buffer_pos ++;
+  if (*buffer_pos == '\0') {
+    *buffer = buffer_pos;
+    return false;
+  }
+  // see if we have a '/'
+  if (*buffer_pos == '/') {
+    el.text.push_back('/');
+    el.elType = CloseTagE;
+    buffer_pos++;
+    if (*buffer_pos == '\0') {    
+      *buffer = buffer_pos;
+      return false;
+    }
+  } else {
+    el.elType = OpenTagE;
+  }
+  // get the tag name
+  while (isalnum(*buffer_pos)) {
+    el.text.push_back (*buffer_pos);
+    el.tagName.push_back (*buffer_pos);
+    buffer_pos++;
+    
+    if (*buffer_pos == '\0') {
+      *buffer = buffer_pos;
+      return false;
+    }
+
+  }
+  cout << "tag name = "<<el.tagName<<endl;
+  // get everything up to closing '>'
+  while (*buffer_pos != '>') {
+    el.text.push_back(*buffer_pos);
+    buffer_pos++;
+    if (*buffer_pos == '\0') {
+      *buffer = buffer_pos;
+      return false;
+    }
+    
+  }
+  // get teh closing '>'
+  el.text.push_back('>');
+  buffer_pos++;
+  *buffer = buffer_pos;
+  cout << "at end of readtexttag, buffer is "<<*buffer<<endl;
+  // if there is no tag name then make this a text element
+  if (el.tagName.empty()) el.elType = TextE;
+  
+  return true;
+}
+
+static void ToggleParaTag (TextEl &el, bool &compatInPara) {
+  SetCStr (el.tagName, "Paragraph", 9);
+  el.text.erase (el.text.begin(), el.text.end());
+  if (compatInPara) {
+    el.elType = CloseTagE;
+    el.text.push_back (PARA_TERM);
+  } else el.elType = OpenTagE;
+  compatInPara = !compatInPara;
+}
+
+static void SetRecTag (TextEl &el, TextElType elType) {
+  el.elType = elType;
+  SetCStr (el.tagName, "Document", 8);
+  el.text.erase (el.text.begin(), el.text.end());
+  if (elType == CloseTagE)
+    el.text.push_back (REC_TERM);
+}
+
+
+bool ReadTextEl (FileBuf &buf, TextEl &el,
+		 bool compatMode, bool &compatInPara) {
+  el.Clear();
+
+  unsigned char c;
+  if (!buf.Peek (c)) return false;
+
+  if (compatMode) {
+    if (c == PARA_TERM) {
+      ToggleParaTag (el, compatInPara);
+      if (!compatInPara) buf.Next();
+      return true;
+    }
+    if (c == REC_TERM) {
+      if (compatInPara) {
+	// need to close this paragraph
+	ToggleParaTag (el, compatInPara);
+	return true;
+      }
+      // can close this document
+      buf.Next();
+      SetRecTag (el, CloseTagE);
+      return true;
+    }
+    if (!compatInPara) {
+      // need to open a paragraph
+      ToggleParaTag (el, compatInPara);
+      return true;
+    }
+  }
+  
+  // see if we have some sort of tag
+  if (c == '<') return ReadTextTag (buf, el);
+
+  // read in a text element
+  el.elType = TextE;
+  while (c != '<' && !(compatMode && (c == PARA_TERM || c == REC_TERM))) {
+    el.text.push_back (c);
+    if (!buf.Next() || !buf.Peek (c)) break;
+  }
+
+  return true;
+}
+bool ReadTextEl (u_char **buffer, TextEl &el,
+		 bool compatMode, bool &compatInPara) {
+  el.Clear();
+  u_char * buffer_pos = *buffer;
+  if (*buffer_pos == '\0') return false;
+  if (compatMode) {
+    if (*buffer_pos == PARA_TERM) {
+      ToggleParaTag (el, compatInPara);
+      if (!compatInPara) buffer_pos++;
+      *buffer = buffer_pos;
+      return true;
+    }
+    if (*buffer_pos == REC_TERM) {
+      if (compatInPara) {
+	// need to close this paragraph
+	ToggleParaTag (el, compatInPara);
+	*buffer = buffer_pos;
+	return true;
+      }
+      // can close this document
+      buffer_pos++;
+      SetRecTag (el, CloseTagE);
+      *buffer = buffer_pos;
+      return true;
+    }
+    if (!compatInPara) {
+      // need to open a paragraph
+      ToggleParaTag (el, compatInPara);
+      *buffer = buffer_pos;
+      return true;
+    }
+  }
+  
+  // see if we have some sort of tag
+  if (*buffer_pos == '<') return ReadTextTag (buffer, el);
+
+  // read in a text element
+  el.elType = TextE;
+  while (*buffer_pos != '<' && !(compatMode && (*buffer_pos == PARA_TERM || *buffer_pos == REC_TERM))) {
+    el.text.push_back (*buffer_pos);
+    buffer_pos++;
+    if (*buffer_pos == '\0') break;
+  }
+  *buffer = buffer_pos;
+  cout << "text element: "<<el.text<<endl;
+  return true;
+}
+  
+static void AddTextEl (TextElArray &doc, unsigned long &docLen,
+		       const TextEl &el) {
+  doc.push_back (el);
+  docLen += el.text.size();
+
+//    cout << "elType:  " << el.elType << "\n";
+//    cout << "tagName: " << el.tagName << "\n";
+//    cout << "text:    \"" << el.text << "\"\n\n";
+}
+
+
+bool ReadDoc (FileBuf &buf, const UCArray &docTag,
+	      TextElArray &doc, unsigned long &docLen,
+	      bool compatMode) {
+  bool compatInPara = false;
+  bool foundDocEl = false;
+  TextEl el;
+  
+  doc.erase (doc.begin(), doc.end());
+  docLen = 0;
+
+  if (compatMode) {
+    // add <Document><Paragraph>
+    SetRecTag (el, OpenTagE);
+    AddTextEl (doc, docLen, el);
+    ToggleParaTag (el, compatInPara);
+    AddTextEl (doc, docLen, el);
+    
+  } else {
+    // look for an opening docTag
+    do {
+      if (!ReadTextEl (buf, el, compatMode, compatInPara)) return false;
+    } while (el.elType != OpenTagE || el.tagName != docTag);
+    
+    AddTextEl (doc, docLen, el);
+  }
+
+  
+  // get all elements until the closing docTag
+  while (ReadTextEl (buf, el, compatMode, compatInPara)) {
+    foundDocEl = true;
+    AddTextEl (doc, docLen, el);
+    if (el.elType == CloseTagE && el.tagName == docTag)
+      return true;
+  }
+
+  
+  if (compatMode) {
+    if (!foundDocEl) { // end of text
+      doc.erase (doc.begin(), doc.end());
+      return false;
+    }
+
+    // if we got here then the eof was encountered before
+    // the closing document tag
+    if (compatInPara) {
+      // need to close this paragraph
+      ToggleParaTag (el, compatInPara);
+      AddTextEl (doc, docLen, el);
+    }
+    // close this document
+    SetRecTag (el, CloseTagE);
+    AddTextEl (doc, docLen, el);
+  }
+  
+  return true;
+}
+
+// copy of readdoc to get TextElArray from u_char buffer
+bool ReadDoc(u_char ** buffer, const UCArray &docTag, 
+	     TextElArray &doc, unsigned long &docLen,
+	     bool compatMode) {
+  bool compatInPara = false;
+  bool foundDocEl = false;
+  TextEl el;
+  
+  doc.erase (doc.begin(), doc.end());
+  docLen = 0;
+
+  if (compatMode) {
+    // add <Document><Paragraph>
+    SetRecTag (el, OpenTagE);
+    AddTextEl (doc, docLen, el);
+    ToggleParaTag (el, compatInPara);
+    AddTextEl (doc, docLen, el);
+    
+  } else {
+    // look for an opening docTag
+    do {
+      if (!ReadTextEl (buffer, el, compatMode, compatInPara)) return false;
+    } while (el.elType != OpenTagE || el.tagName != docTag);
+    
+    AddTextEl (doc, docLen, el);
+  }
+
+  
+  // get all elements until the closing docTag
+  while (ReadTextEl (buffer, el, compatMode, compatInPara)) {
+    foundDocEl = true;
+    AddTextEl (doc, docLen, el);
+    if (el.elType == CloseTagE && el.tagName == docTag)
+      return true;
+  }
+
+  
+  if (compatMode) {
+    if (!foundDocEl) { // end of text
+      doc.erase (doc.begin(), doc.end());
+      return false;
+    }
+
+    // if we got here then the eof was encountered before
+    // the closing document tag
+    if (compatInPara) {
+      // need to close this paragraph
+      ToggleParaTag (el, compatInPara);
+      AddTextEl (doc, docLen, el);
+    }
+    // close this document
+    SetRecTag (el, CloseTagE);
+    AddTextEl (doc, docLen, el);
+  }
+  
+  return true;
+}
+
+
Index: /indexers/branches/3.03a/mgpp/text/TextEl.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/TextEl.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/TextEl.h	(revision 14757)
@@ -0,0 +1,69 @@
+/**************************************************************************
+ *
+ * TextEl.h -- Data structures for parsed documents
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef TEXTEL_H
+#define TEXTEL_H
+
+#include "UCArray.h"
+#include "FileBuf.h"
+#include "sysfuncs.h"
+
+enum TextElType {OpenTagE, CloseTagE, TextE};
+
+class TextEl {
+protected:
+  bool ReadTextTag (FileBuf &buf, TextEl &el);
+  bool ReadTextTag (u_char ** buffer, TextEl &el);
+public:
+  TextElType elType;
+  UCArray tagName;
+  UCArray text; // complete text, including tag
+
+  TextEl () { Clear (); }
+  void Clear ();
+};
+
+
+typedef vector<TextEl> TextElArray;
+
+
+// compatMode parses documents similar to "old mg" -- ie with
+// C-b between documents and C-c between paragraphs
+
+// returns true if a text element could be read
+bool ReadTextEl (FileBuf &buf, TextEl &el,
+		 bool compatMode, bool &compatInPara);
+bool ReadTextEl (u_char **buffer, TextEl &el,
+		 bool compatMode, bool &compatInPara);
+
+// looks for an opening docTag and reads all text elements up
+// to a corresponding closing docTag. note that this does not
+// hierarchically parse the document so you can't nest documents.
+// returns true if a document could be found
+bool ReadDoc (FileBuf &buf, const UCArray &docTag,
+	      TextElArray &doc, unsigned long &docLen,
+	      bool compatMode=false);
+
+bool ReadDoc(u_char **buffer, const UCArray &docTag, 
+	     TextElArray &doc, unsigned long &docLen,
+	     bool compatMode=false);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/TextGet.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/TextGet.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/TextGet.cpp	(revision 14757)
@@ -0,0 +1,685 @@
+/**************************************************************************
+ *
+ * TextGet.cpp -- Decompressing the text
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+// is important to be first, so we escape the truncation warning on VC++
+#include "TextGet.h"
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+#include "mg_files.h"
+#include "netorder.h"
+#include "mg_errors.h"
+#include "locallib.h"
+#include "words.h"
+#include "local_strings.h"
+#include "bitio_m_stdio.h"
+
+typedef enum huff_type {lengths, chars};
+
+
+static auxiliary_dict *LoadAuxDict (compression_dict &cd, FILE *text_aux_dict) {
+  auxiliary_dict *ad;
+  int i;
+
+  if (!(ad = new auxiliary_dict))
+    {
+      mg_errno = MG_NOMEM;
+      return (NULL);
+    }
+
+  memset (ad, '\0', sizeof (*ad));
+
+  for (i = 0; i <= 1; ++i)
+    {
+      int j;
+      u_char *pos;
+
+      fread (&ad->afh[i], sizeof (aux_frags_header), 1, text_aux_dict);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(ad->afh[i].num_frags);
+      NTOHUL(ad->afh[i].mem_for_frags);
+
+      if (!(ad->word_data[i] = new u_char[ad->afh[i].mem_for_frags]))
+	{
+	  mg_errno = MG_NOMEM;
+	  delete ad;
+	  return (NULL);
+	}
+      if (!(ad->words[i] = new u_char* [ad->afh[i].num_frags]))
+	{
+	  mg_errno = MG_NOMEM;
+	  delete ad;
+	  return (NULL);
+	}
+
+      fread (ad->word_data[i], ad->afh[i].mem_for_frags, sizeof (u_char),
+	     text_aux_dict);
+
+      pos = ad->word_data[i];
+      for (j = 0; j < (int)ad->afh[i].num_frags; ++j)
+	{
+	  ad->words[i][j] = pos;
+	  pos += *pos + 1;
+	}
+      if (cd.cdh.novel_method == MG_NOVEL_HYBRID)
+	{
+	  int num;
+	  num = 1;
+	  ad->blk_start[i][0] = 0;
+	  ad->blk_end[i][0] = cd.cdh.num_words[i] - 1;
+	  while (num < 33)
+	    {
+	      ad->blk_start[i][num] = ad->blk_end[i][num - 1] + 1;
+	      ad->blk_end[i][num] = ad->blk_start[i][num] +
+		(ad->blk_end[i][num - 1] - ad->blk_start[i][num - 1]) * 2;
+	      ++num;
+	    }
+	}
+    }
+  return (ad);
+}
+
+
+static u_char ***ReadInWords (FILE *dict, compression_dict &cd,
+			      comp_frags_header *cfh, u_char **escape) {
+  int i, lookback;
+  int ptrs_reqd = 0;
+  int mem_reqd = 0;
+  int num_set[MAX_HUFFCODE_LEN + 1];
+  u_char *next_word[MAX_HUFFCODE_LEN + 1];
+  u_char **vals;
+  u_char ***values;
+  u_char word[MAXWORDLEN + 1];
+  u_char last_word[MAX_HUFFCODE_LEN + 1][MAXWORDLEN + 1];
+
+  lookback = cd.cdh.lookback;
+
+  for (i = cfh->hd.mincodelen; i <= cfh->hd.maxcodelen; ++i) {
+    ptrs_reqd += (cfh->hd.lencount[i] + ((1 << lookback) - 1)) >> lookback;
+    mem_reqd += cfh->huff_words_size[i];
+  }
+
+  if (!(vals = new u_char* [ptrs_reqd]))
+    return (NULL);
+
+  if (!(values = new u_char** [MAX_HUFFCODE_LEN + 1]))
+    return (NULL);
+
+  if (!(next_word[0] = new u_char[mem_reqd])) 
+    return (NULL);
+
+  cd.MemForCompDict += ptrs_reqd * sizeof (*vals) +
+    (MAX_HUFFCODE_LEN + 1) * sizeof (u_char **) +
+    mem_reqd;
+
+  values[0] = vals;
+  values[0][0] = next_word[0];
+  for (i = 1; i <= cfh->hd.maxcodelen; ++i)
+    {
+      int next_start = (values[i - 1] - vals) +
+      ((cfh->hd.lencount[i - 1] + ((1 << lookback) - 1)) >> lookback);
+      values[i] = &vals[next_start];
+      next_word[i] = next_word[i - 1] + cfh->huff_words_size[i - 1];
+      values[i][0] = next_word[i];
+    }
+
+  memset (num_set, '\0', sizeof (num_set));
+
+  for (i = 0; i < cfh->hd.num_codes; ++i)
+    {
+      register int val, copy;
+      register int len = cfh->hd.clens[i];
+      val = getc (dict);
+      copy = (val >> 4) & 0xf;
+      val &= 0xf;
+
+      fread (word + copy + 1, sizeof (u_char), val, dict);
+      *word = val + copy;
+
+      if ((num_set[len] & ((1 << lookback) - 1)) == 0)
+	{
+	  values[len][num_set[len] >> lookback] = next_word[len];
+	  memcpy (next_word[len], word, *word + 1);
+	  if (escape && i == cfh->hd.num_codes - 1)
+	    *escape = next_word[len];
+	  next_word[len] += *word + 1;
+	}
+      else
+	{
+	  copy = prefixlen (last_word[len], word);
+	  memcpy (next_word[len] + 1, word + copy + 1, *word - copy);
+	  *next_word[len] = (copy << 4) + (*word - copy);
+	  if (escape && i == cfh->hd.num_codes - 1)
+	    *escape = next_word[len];
+	  next_word[len] += (*word - copy) + 1;
+	}
+      memcpy (last_word[len], word, *word + 1);
+      ++num_set[len];
+    }
+  if (cfh->hd.clens)
+    delete []cfh->hd.clens;
+  cfh->hd.clens = NULL;
+  return values;
+}
+
+static int Load_Comp_HuffData(compression_dict &cd, int which, FILE *dict, 
+			      huff_type type) {
+  huff_data * hd;
+  u_long **   vals;
+
+  if (!(hd = new huff_data))
+    return 1;
+  cd.MemForCompDict += sizeof (huff_data);
+  if (Read_Huffman_Data (dict, hd, &cd.MemForCompDict, NULL) == -1)
+    return 2;
+  if (!(vals = Generate_Huffman_Vals (hd, &cd.MemForCompDict)))
+    return 3;
+  if (hd->clens)
+    delete []hd->clens;
+  hd->clens = NULL;
+  if (type == chars)
+    {
+      cd.chars_huff[which] = hd;
+      cd.chars_vals[which] = vals;
+    }
+  else
+    {
+      cd.lens_huff[which] = hd;
+      cd.lens_vals[which] = vals;
+    }
+
+  return 0;
+}
+
+static int Load_Comp_FragsHeader(compression_dict &cd, int which, int getEscape,
+				 FILE *dict) {
+  if (!(cd.cfh[which] = new comp_frags_header))
+    return 1;
+  cd.MemForCompDict += sizeof (*cd.cfh[which]);
+  if (Read_cfh (dict, cd.cfh[which], &cd.MemForCompDict, NULL) == -1)
+    return 2;
+
+  if (!(cd.values[which] = ReadInWords (dict, cd, cd.cfh[which],
+					getEscape == 0 ? NULL : &cd.escape[which])))
+    return 3;
+  
+  return 0;
+}
+
+static bool LoadSlowCompDict (FILE *dict, FILE *aux_dict, compression_dict &cd) {
+  if (dict == NULL) return false;
+
+  int which;
+
+  memset (&cd, '\0', sizeof (compression_dict));
+
+  cd.MemForCompDict = sizeof (compression_dict);
+
+  if (Read_cdh (dict, &cd.cdh, &cd.MemForCompDict, NULL) == -1)
+    return false;
+
+  for (which = 0; which < 2; ++which)
+    switch (cd.cdh.dict_type)
+      {
+      case MG_COMPLETE_DICTIONARY:
+	{
+	  if (Load_Comp_FragsHeader(cd, which, 0, dict) != 0)
+	    return false;
+	  cd.escape[which] = NULL;
+
+	}
+	break;
+      case MG_PARTIAL_DICTIONARY:
+	{
+	  if (cd.cdh.num_words[which])
+	    {
+	      if (Load_Comp_FragsHeader(cd, which, 1, dict) != 0)
+		return false;
+	    }
+
+	  if (Load_Comp_HuffData(cd, which, dict, chars) != 0)
+	    return false;
+
+	  if (Load_Comp_HuffData(cd, which, dict, lengths) != 0)
+	    return false;
+	}
+	break;
+      case MG_SEED_DICTIONARY:
+	{
+	  if (cd.cdh.num_words[which])
+	    {
+	      if (Load_Comp_FragsHeader(cd, which, 1, dict) != 0)
+		return false;
+	    }
+	  switch (cd.cdh.novel_method)
+	    {
+	    case MG_NOVEL_HUFFMAN_CHARS:
+	      if (Load_Comp_HuffData(cd, which, dict, chars) != 0)
+		return false;
+
+	      if (Load_Comp_HuffData(cd, which, dict, lengths) != 0)
+		return false;
+	      break;
+	    case MG_NOVEL_DELTA:
+	      break;
+	    case MG_NOVEL_HYBRID:
+	      break;
+	    }
+	  break;
+	}
+      }
+
+  if (cd.cdh.novel_method == MG_NOVEL_DELTA ||
+      cd.cdh.novel_method == MG_NOVEL_HYBRID)
+    {
+      if (!aux_dict)
+	{
+	  mg_errno = MG_NOFILE;
+	  cd.Clear();
+	  return false;
+	}
+
+      if (!(cd.ad = LoadAuxDict (cd, aux_dict)))
+	{
+	  cd.Clear();
+	  return false;
+	}
+    }
+
+  mg_errno = MG_NOERROR;
+
+  cd.fast_loaded = 0;
+  
+  return true;
+}
+
+
+
+#define WORDNO(p, base) ((((char*)(p))-((char*)(base)))/sizeof(u_char*))
+#define IS_FIXUP(p) ((fixup[WORDNO(p,cd)/8] & (1<<(WORDNO(p,cd) & 7))) != 0)
+
+// fast loading really needs to be totally re-writen. "Unloading" the
+// text data will currently cause a crash because memory is being
+// deleted multiple times (and probably a zillion other reasons).
+static bool LoadFastCompDict (FILE *text_fast_comp_dict, compression_dict &_cd) {
+  if (text_fast_comp_dict == NULL) return false;
+  
+  u_long *p, *end;
+  u_char *fixup;
+  u_long mem;
+  u_long fixup_mem;
+  int i;  /* [RPAP - Jan 97: Endian Ordering] */
+
+  fread (&mem, sizeof (mem), 1, text_fast_comp_dict);
+  NTOHUL(mem);  /* [RPAP - Jan 97: Endian Ordering] */
+  fread (&fixup_mem, sizeof (fixup_mem), 1, text_fast_comp_dict);
+  NTOHUL(fixup_mem);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  compression_dict *cd;
+  if (!(cd = (compression_dict *)malloc (mem))) {
+    mg_errno = MG_NOMEM;
+    return false;
+  }
+
+  end = (u_long *) (((u_char *) cd) + mem);
+  fread (cd, sizeof (u_char), mem, text_fast_comp_dict);
+
+  if (!(fixup = new u_char[fixup_mem]))
+    {
+      mg_errno = MG_NOMEM;
+      return false;
+    }
+
+  fread (fixup, fixup_mem, sizeof (u_char), text_fast_comp_dict);
+
+  for (p = (u_long *) cd; (u_long) p < (u_long) end; ++p)
+    if (IS_FIXUP (p))
+      {
+	NTOHUL(*p);  /* [RPAP - Jan 97: Endian Ordering] */
+	*p = *p + (u_long) cd;
+      }
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  /* cdh */
+  NTOHUL(cd->cdh.dict_type);
+  NTOHUL(cd->cdh.novel_method);
+  for (i = 0; i < TEXT_PARAMS; ++i)
+    NTOHUL(cd->cdh.params[i]);
+  NTOHUL(cd->cdh.num_words[0]);
+  NTOHUL(cd->cdh.num_words[1]);
+  NTOHUL(cd->cdh.num_word_chars[0]);
+  NTOHUL(cd->cdh.num_word_chars[1]);
+  NTOHUL(cd->cdh.lookback);
+  /* cfh */
+  for (i = 0; i <= 1; ++i)
+    {
+      int j;
+
+      NTOHSI(cd->cfh[i]->hd.num_codes);
+      NTOHSI(cd->cfh[i]->hd.mincodelen);
+      NTOHSI(cd->cfh[i]->hd.maxcodelen);
+      for (j = 0; j < MAX_HUFFCODE_LEN + 1; ++j)
+	{
+	  NTOHSI(cd->cfh[i]->hd.lencount[j]);
+	  NTOHUL(cd->cfh[i]->hd.min_code[j]);
+	}
+      NTOHUL(cd->cfh[i]->uncompressed_size);
+      for (j = 0; j < MAX_HUFFCODE_LEN + 1; ++j)
+	NTOHUL(cd->cfh[i]->huff_words_size[j]);
+    }
+  NTOHUL(cd->MemForCompDict);
+  /* ad */
+  if (cd->cdh.novel_method == MG_NOVEL_DELTA ||
+      cd->cdh.novel_method == MG_NOVEL_HYBRID)
+    for (i = 0; i <= 1; ++i)
+      {
+	int j;
+	
+	NTOHUL(cd->ad->afh[i].num_frags);
+	NTOHUL(cd->ad->afh[i].mem_for_frags);
+	for (j = 0; j < 33; ++j)
+	  {
+	    NTOHSI(cd->ad->blk_start[i][j]);
+	    NTOHSI(cd->ad->blk_end[i][j]);
+	  }
+      }
+  NTOHSI(cd->fast_loaded);
+
+  delete []fixup;
+
+  // the whole fast comp dict is a bit of a hack so I don't
+  // feel too bad about the next line :-) -- Rodger.
+  _cd = *cd;
+  
+  return true;
+}
+
+
+static bool LoadCompDict (FILE *compDictFile,
+			  FILE *auxDictFile,
+			  FILE *fastCompDictFile,
+			  compression_dict &cd) {
+  // see if we have a fast loading compression dictionary
+  if (fastCompDictFile != NULL)
+    return LoadFastCompDict (fastCompDictFile, cd);
+  
+  // slow compression dictionary
+  return LoadSlowCompDict (compDictFile, auxDictFile, cd);
+}
+
+
+// try to open the dictionary files and load the dictionary
+static bool OpenLoadCompDict (char *textname, compression_dict &cd) {
+  FILE *compDictFile = NULL;
+  FILE *auxDictFile = NULL;
+  FILE *fastCompDictFile = NULL;
+
+  fastCompDictFile = open_file (textname, TEXT_DICT_FAST_SUFFIX,
+				"rb", MAGIC_FAST_DICT, MG_CONTINUE);
+  
+  if (fastCompDictFile == NULL) {
+    compDictFile = open_file (textname, TEXT_DICT_SUFFIX,
+			      "rb", MAGIC_DICT, MG_MESSAGE);
+    auxDictFile =  open_file (textname, TEXT_DICT_AUX_SUFFIX,
+			      "rb", MAGIC_AUX_DICT, MG_CONTINUE);
+  }
+  
+  bool res = LoadCompDict (compDictFile, auxDictFile, fastCompDictFile, cd);
+
+  if (compDictFile != NULL) fclose (compDictFile);
+  if (auxDictFile != NULL) fclose (auxDictFile);
+  if (fastCompDictFile != NULL) fclose (fastCompDictFile);
+  
+  return res;
+}
+
+static bool LoadLevels (char *textname, FTextLevel &levels) {
+  FILE *levelFile = NULL;
+
+  // open the text level file
+  levelFile = open_file (textname, TEXT_LEVEL_SUFFIX,
+			 "rb", MAGIC_TEXT_LEVELS, MG_CONTINUE);
+  if (levelFile == NULL) return false;
+
+  // seek to the appropriate place and read the level information
+  bool res = ((fseek (levelFile, sizeof (u_long), SEEK_SET) == 0) &&
+	      levels.Read (levelFile));
+
+  // close the file
+  fclose (levelFile);
+  
+  return res;
+}
+
+
+TextData::TextData () {
+  // put file pointers in known state first
+  textFile = NULL;
+  textIdxFile = NULL;
+  Clear ();
+}
+
+void TextData::Clear () {
+  cd.Clear(); 
+  textFile = NULL;
+  textIdxFile = NULL;
+  cth.Clear();
+  levels.Clear();
+}
+
+bool TextData::LoadData (char *basepath, char *textname) {
+  
+  if (textname[0] == '\0') return false;
+  
+  // set the basepath
+  set_basepath(basepath);
+  
+  // load the compression dictionary
+  if (!OpenLoadCompDict (textname, cd)) return false;
+
+  // open the compressed text and text index file
+  textFile = open_file (textname, TEXT_SUFFIX, "rb", MAGIC_TEXT, MG_CONTINUE);
+  if (textFile == NULL) return false;
+
+  textIdxFile = open_file (textname, TEXT_IDX_SUFFIX, "rb", MAGIC_TEXI, MG_CONTINUE);
+  if (textIdxFile == NULL) return false;
+
+  // read in the compressed text header
+  if ((fseek (textFile, sizeof (u_long), SEEK_SET) != 0) || !cth.Read (textFile))
+    return false;
+
+  // read in the level information
+  if (!LoadLevels (textname, levels)) return false;
+  
+  return true;
+}
+
+bool TextData::UnloadData () {
+  // close any open files
+  if (textFile != NULL) {
+    fclose (textFile);
+    textFile = NULL;
+  }
+  if (textIdxFile != NULL) {
+    fclose (textIdxFile);
+    textIdxFile = NULL;
+  }
+
+  // do general clear
+  Clear ();
+  
+  return true;  
+}
+
+
+bool GetDocIdx (TextData &td, const UCArray &docLevel,
+		unsigned long docNum, TextIdx &docIdx) {
+  // make sure the text index file was opened successfully
+  if (td.textIdxFile == NULL) return false;
+
+  // read in the index
+  TextLevelInfo &levelInfo = td.levels.levelInfo[docLevel];
+  if (!docIdx.Read (td.textIdxFile, levelInfo, docNum)) return false;
+  
+  return true;
+}
+
+
+
+
+#define MY_HUFF_DECODE(len, code, mcodes)				\
+  do {									\
+    register unsigned long *__min_code = (mcodes);			\
+    register unsigned long *__mclen = __min_code;			\
+    register unsigned long __code = 0;					\
+    do									\
+      {									\
+        __code += __code + buffer.bit();	                  	\
+      }									\
+    while (__code < *++__mclen);					\
+    (len) = __mclen - __min_code;					\
+    (code) = __code - *__mclen;						\
+  } while(0);
+
+
+bool GetDocText (TextData &td, const UCArray &docLevel,
+		 unsigned long docNum, UCArray &docText) {
+  // erase the current text
+  docText.erase (docText.begin(), docText.end());
+
+  // look up the information about this document
+  TextIdx docIdx;
+  if (!GetDocIdx (td, docLevel, docNum, docIdx)) return false;
+
+  // do seek to appropriate position
+  stdio_bitio_buffer buffer (td.textFile);
+  buffer.seek (docIdx.start.byte, docIdx.start.bit);
+  
+  // decompress the document
+  compression_dict &cd = td.cd;
+  auxiliary_dict *ad = cd.ad;
+  int which = docIdx.which;
+  unsigned long num_bits = (docIdx.end.byte*8+(8-docIdx.end.bit)) -
+    (docIdx.start.byte*8+(8-docIdx.start.bit));
+  unsigned long bits = 0;
+
+  if (docText.capacity() < docText.size() + num_bits + 1) {
+    docText.reserve(docText.size() + num_bits + 1);
+  }
+  // keep decoding bits until enough bits have been decoded
+  while (bits < num_bits) {
+    register unsigned code, len;
+    register int r;
+    register u_char *t, *b = NULL;
+    u_char word[MAXWORDLEN + 1];
+    
+    if (cd.cfh[which]) {
+      MY_HUFF_DECODE (len, code, cd.cfh[which]->hd.min_code);
+      bits += len;
+      
+      r = code & ((1 << cd.cdh.lookback) - 1);
+      t = cd.values[which][len][code >> cd.cdh.lookback];
+      
+      /* step through from base pointer */
+      b = word + 1;
+      while (r--) {
+	register int copy = *t >> 4;
+	memcpy (word + copy + 1, t + 1, *t & 0xf);
+	word[0] = copy + (*t & 0xf);
+	t += ((*t) & 0xf) + 1;
+      }
+    } else t = NULL;
+    
+    if (t == cd.escape[which]) {
+      switch (cd.cdh.novel_method) {
+      case MG_NOVEL_HUFFMAN_CHARS:
+	{
+	  int len, i;
+	  int c;
+	  len = buffer.huff_decode(cd.lens_huff[which]->min_code,
+				   cd.lens_vals[which], &bits);
+	  for (i = 0; i < len; ++i) {
+	    c = buffer.huff_decode(cd.chars_huff[which]->min_code,
+				   cd.chars_vals[which], &bits);
+	    docText.push_back (c);
+	  }
+	}
+	break;
+      case MG_NOVEL_DELTA:
+      case MG_NOVEL_HYBRID:
+	{
+	  int idx = 0, len;
+	  u_char *base;
+	  switch (cd.cdh.novel_method)
+	    {
+	    case MG_NOVEL_DELTA:
+	      {
+		idx = buffer.delta_decode (&bits);
+		--idx;
+	      }
+	      break;
+	    case MG_NOVEL_HYBRID:
+	      {
+		int k;
+		k = buffer.gamma_decode (&bits);
+		--k;
+		idx = buffer.binary_decode(ad->blk_end[which][k] -
+					   ad->blk_start[which][k] + 1, 
+					   &bits);
+		idx += ad->blk_start[which][k] - 1;
+	      }
+	      break;
+	    }
+	  base = ad->words[which][idx];
+	  len = *base++;
+	  for (; len; --len)
+	    {
+	      docText.push_back (*base++);
+	    }
+	}
+	break;
+      }
+    }
+    else
+      {
+	/* copy over the matching prefix */
+	r = (*t >> 4);
+	while (r--) {
+	  docText.push_back (*b++);
+	}
+	
+	/* and the stored suffix */
+	r = ((*t) & 0xf);
+	while (r--) {
+	  docText.push_back (*++t);
+	}
+      }
+    which = !which;
+  }
+  
+  buffer.done();
+  
+  return true;
+}
+
Index: /indexers/branches/3.03a/mgpp/text/TextGet.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/TextGet.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/TextGet.h	(revision 14757)
@@ -0,0 +1,58 @@
+/**************************************************************************
+ *
+ * TextGet.h -- Decompressing the text
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef TEXTGET_H
+#define TEXTGET_H
+
+#include "text.h"
+#include "FText.h"
+
+
+class TextData {
+public:
+  compression_dict cd;
+  FILE *textFile;
+  FILE *textIdxFile;
+  compressed_text_header cth;
+  FTextLevel levels;
+
+  TextData ();
+  void Clear ();
+
+  // loads compression dictionary, the compressed text header,
+  // and all level informaiton
+  bool LoadData (char *basepath, char *textname);
+  bool UnloadData ();
+};
+
+
+// note: document numbers start at 1
+
+// get information about where a document starts and finishes
+bool GetDocIdx (TextData &td, const UCArray &docLevel,
+		unsigned long docNum, TextIdx &docIdx);
+
+
+// decompress a document's text
+bool GetDocText (TextData &td, const UCArray &docLevel,
+		 unsigned long docNum, UCArray &docText);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/UCArray.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/UCArray.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/UCArray.cpp	(revision 14757)
@@ -0,0 +1,440 @@
+/**************************************************************************
+ *
+ * UCArray.cpp -- vector based string class
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "UCArray.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+#include "unitool.h"
+
+void SetCStr (UCArray &text, const char *cStr) {
+  text.erase(text.begin(), text.end());
+  
+  while (*cStr != '\0') {
+    text.push_back (*cStr);
+    ++cStr;
+  }
+}
+
+void SetCStr (UCArray &text, const char *cStr, size_t nSizeHint) {
+  text.erase(text.begin(), text.end());
+
+  // reserve the needed space in advance
+  if (text.capacity() < nSizeHint + 1) {
+    text.reserve(nSizeHint + 1);
+  }
+  while (*cStr != '\0') {
+    text.push_back (*cStr);
+    ++cStr;
+  }
+}
+
+/** char * returned becomes the responsibility of the caller */
+char * GetCStr(const UCArray& text) {
+
+  char *cstr = new char[text.size()+1];
+  UCArray::const_iterator here = text.begin();
+  UCArray::const_iterator end = text.end();
+
+  int i = 0;
+  while (here != end) {
+    cstr[i] = text[i];
+    ++here; ++i;
+  }
+  cstr[i]='\0';
+  return cstr;
+}
+
+/** char * returned becomes the responsibility of the caller */
+unsigned char * MyGetCStr(const UCArray& text) {
+
+  unsigned char *cstr = new unsigned char[text.size()+1];
+  cstr[0] = text.size();
+  UCArray::const_iterator here = text.begin();
+  UCArray::const_iterator end = text.end();
+
+  int i = 1;
+  while (here != end) {
+    cstr[i] = text[i-1];
+    ++here; ++i;
+  }
+  //  cstr[i]='\0';
+  return cstr;
+}
+
+bool UCArrayCStrEquals(const UCArray &text, const unsigned char *cStr)
+{
+  if ((cStr == NULL || *cStr == '\0') && text.empty()) return true;
+  UCArray::const_iterator thisUC = text.begin();
+  UCArray::const_iterator endUC = text.end();
+  while (thisUC != endUC && *cStr != '\0') {
+    if (*thisUC != *cStr) return false;
+    ++cStr; ++thisUC;
+  }
+  if (thisUC == endUC && *cStr == '\0') return true;
+  return false;
+}
+
+ostream &operator<<(ostream &s, const UCArray &a) {
+  UCArray::const_iterator here = a.begin();
+  UCArray::const_iterator end = a.end();
+  while (here != end) {
+    s << *here;
+    ++here;
+  }
+
+  return s;
+}
+
+
+bool ReadVarLenUL (FILE *f, unsigned long &n) {
+  register unsigned long temp = 0;
+  register unsigned int bitPos = 0;
+  unsigned char b = 0;
+
+  do {
+    b = fgetc (f);
+    if (feof(f)) return false;
+    temp |= (b & 0x7f) << bitPos;
+    bitPos += 7;
+  } while (b >= 0x80 && bitPos < 32);
+
+  n = temp;
+  
+  return true;
+}
+
+bool WriteVarLenUL (FILE *f, unsigned long n) {
+  register unsigned long temp = n;
+  register unsigned char b = 0;
+  do {
+    b = static_cast<unsigned char> (temp & 0x7f);
+    if (temp >= 0x80) b |= 0x80;
+    fputc (b, f);
+    if (ferror (f) != 0) return false;
+  } while ((temp = temp >> 7) > 0);
+  
+  return true;
+}
+
+
+bool ReadUL (FILE *f, unsigned long &n) {
+  if (fread (&n, sizeof (unsigned long), 1, f) <= 0) return false;
+  NTOHUL (n);
+  return true;
+}
+
+
+bool WriteUL (FILE *f, unsigned long n) {
+  HTONUL (n);
+  return (fwrite (&n, sizeof (unsigned long), 1, f) > 0);
+}
+
+bool ReadF (FILE *f, float &n) {
+  if (fread (&n, sizeof (float), 1, f) <= 0) return false;
+  NTOHF(n);
+  return true;
+}
+
+bool WriteF (FILE *f, float n) {
+  HTONF(n);
+  return (fwrite (&n, sizeof (float), 1, f) > 0);
+}
+
+bool ReadD (FILE *f, double &n) {
+  if (fread (&n, sizeof (double), 1, f) <= 0) return false;
+  NTOHD(n);
+  return true;
+}
+
+bool WriteD (FILE *f, double n) {
+  HTOND(n);
+  return (fwrite (&n, sizeof (double), 1, f) > 0);
+}
+
+bool ReadUCArray (FILE *f, UCArray &a) {
+  // clear the array in preparation
+  a.erase (a.begin(), a.end());
+
+  // read in the array size
+  unsigned long arraySize = 0;
+  if (!ReadVarLenUL (f, arraySize)) return false;
+
+  // reserve the needed space in advance
+  if (a.capacity() < arraySize + 1) {
+    a.reserve(arraySize + 1);
+  }
+
+  // read in the array
+  unsigned char b = 0;
+  while (arraySize > 0) {
+    b = fgetc (f);
+    if (feof(f)) return false;
+    a.push_back (b);
+    
+    --arraySize;
+  }
+  
+  return true;
+}
+
+bool WriteUCArray (FILE *f, const UCArray &a) {
+  // write out the array size
+  if (!WriteVarLenUL (f, a.size())) return false;
+
+  UCArray::const_iterator here = a.begin();
+  UCArray::const_iterator end = a.end();
+  while (here != end) {
+    fputc (*here, f);
+    if (ferror (f) != 0) return false;
+    
+    ++here;
+  }
+  
+  return true;
+}
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+// static unsigned char casecharmap[] = {
+// 	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+// 	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+// 	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+// 	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+// 	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+// 	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+// 	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+// 	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+// 	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+// 	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+// 	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+// 	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+// 	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+// 	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+// 	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+// 	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+// 	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+// 	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+// 	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+// 	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+// 	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+// 	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+// 	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+// 	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+// 	'\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+// 	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+// 	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+// 	'\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
+// 	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+// 	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+// 	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+// 	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+// };
+
+int DictCompare (const UCArray &a1, const UCArray &a2) {
+  unsigned short a1_out[256]; /* temp space */
+  unsigned short a2_out[256]; /* temp space */
+
+  unsigned char * a1_str = (unsigned char *)MyGetCStr(a1);
+  unsigned char * a2_str = (unsigned char *)MyGetCStr(a2);
+  
+  /* decode the words to unicode */
+  utf8_word_to_unicode (a1_str, a1_out, 255);
+  utf8_word_to_unicode (a2_str, a2_out, 255);
+
+  delete []a1_str;
+  delete []a2_str;
+
+  int l1 = a1_out[0];
+  int l2 = a2_out[0];
+
+  int len = (l1 < l2) ? l1 : l2;
+  int pos = 0;
+  int diff = 0;
+  for (int i=1; i<=len; ++i) {
+    if ((diff = unicode_tosimplified(unicode_tolower(a1_out[i])) - 
+	 unicode_tosimplified(unicode_tolower(a2_out[i]))) != 0) {
+      return diff;
+    }
+    if ((pos == 0) && (diff = a1_out[i] - a2_out[i]) != 0) {
+      pos = diff;
+    }
+  }
+  return ((l1 - l2) ? (l1 - l2) : (pos));
+  
+}
+
+// int DictCompare (const UCArray &a1, const UCArray &a2) {
+//   unsigned int l1 = a1.size();
+//   unsigned int l2 = a2.size();
+//   unsigned int l = (l1 < l2) ? l1 : l2;
+//   int pos = 0;
+//   register int diff = 0;
+
+//   UCArray::const_iterator a1Here = a1.begin();
+//   UCArray::const_iterator a2Here = a2.begin();
+  
+//   while (l--) {
+//     if ((diff = casecharmap[*a1Here] - casecharmap[*a2Here]) != 0)
+//       return diff;
+//     if (pos == 0 && (diff = *a1Here - *a2Here) != 0)
+//       pos = diff;
+
+//     ++a1Here;
+//     ++a2Here;
+//   }
+
+//   return ((l1 - l2) ? (l1 - l2) : (pos));
+// }
+
+// does the first string start with the second?
+bool StartsWith (const UCArray &a1, const UCArray &a2) {
+  unsigned int l1 = a1.size();
+  unsigned int l2 = a2.size();
+  if (l2 > l1) {
+    // if the prefix is longer than the string, it can't start with it
+    return false; 
+  }
+  unsigned int l =l2;
+  UCArray::const_iterator a1Here = a1.begin();
+  UCArray::const_iterator a2Here = a2.begin();
+  
+  while (l--) {
+    if ((*a1Here != *a2Here))
+      return false;
+    ++a1Here;
+    ++a2Here;
+  }
+  return true; // we have successfully matched the whole way
+    
+}
+
+// does the first string start with the second, ignoring case?
+bool StartsWithCasefold(const UCArray &a1, const UCArray &a2) {
+  unsigned int l1 = a1.size();
+  unsigned int l2 = a2.size();
+  if (l2 > l1) {
+    // if the prefix is longer than the string, it can't start with it
+    return false; 
+  }
+  unsigned short a1_out[256]; /* temp space */
+  unsigned short a2_out[256]; /* temp space */
+  unsigned char * a1_str = (unsigned char *)MyGetCStr(a1);
+  unsigned char * a2_str = (unsigned char *)MyGetCStr(a2);
+  
+  /* decode the words to unicode */
+  utf8_word_to_unicode (a1_str, a1_out, 255);
+  utf8_word_to_unicode (a2_str, a2_out, 255);
+
+  delete []a1_str;
+  delete []a2_str;
+
+  unsigned int len = a2_out[0];;  
+  for (int i=1; i<=len; ++i) {
+    if (unicode_tosimplified(unicode_tolower(a1_out[i])) != 
+	unicode_tosimplified(unicode_tolower(a2_out[i])) ) return false;
+    
+  }
+  return true; // we have successfully matched the whole way
+    
+}
+
+// does the first string start with the second, ignoring case?
+// bool StartsWithCasefold(const UCArray &a1, const UCArray &a2) {
+//   unsigned int l1 = a1.size();
+//   unsigned int l2 = a2.size();
+//   if (l2 > l1) {
+//     // if the prefix is longer than the string, it can't start with it
+//     return false; 
+//   }
+//   unsigned int l =l2;
+//   UCArray::const_iterator a1Here = a1.begin();
+//   UCArray::const_iterator a2Here = a2.begin();
+  
+//   while (l--) {
+//     if (casecharmap[*a1Here] != casecharmap[*a2Here]) 
+//       return false;
+//     ++a1Here;
+//     ++a2Here;
+//   }
+//   return true; // we have successfully matched the whole way
+    
+// }
+
+
+unsigned long PrefixLen (const UCArray &a1, const UCArray &a2) {
+  unsigned long l = (a1.size() < a2.size()) ? a1.size() : a2.size();
+  unsigned long i = 0;
+
+  UCArray::const_iterator a1Here = a1.begin();
+  UCArray::const_iterator a2Here = a2.begin();
+
+  while (i < l && *a1Here == *a2Here) {
+    ++i; ++a1Here; ++a2Here;
+  }
+  
+  return i;
+}
+
+bool WritePreSufStr (FILE *f, const UCArray *prev, const UCArray &a) {
+  unsigned char preLen;
+  unsigned char sufLen;
+  
+  if (prev != NULL) preLen = PrefixLen (*prev, a);
+  else preLen = 0;
+  sufLen = a.size() - preLen;
+
+  // output the prefix length, suffix length, and the suffix
+  fputc (preLen, f);
+  if (ferror(f) != 0) return false;
+  fputc (sufLen, f);
+  if (ferror(f) != 0) return false;
+  char* tmp=GetCStr(a);
+  int ret=(fwrite (tmp+preLen, sizeof (char), sufLen, f) == sufLen);
+  delete []tmp;
+  return (ret != 0);
+}
+
+// a also used for prev
+bool ReadPreSufStr (FILE *f, UCArray &a) {
+  unsigned char preLen = 0;
+  unsigned char sufLen = 0;
+
+  preLen = fgetc(f);
+  sufLen = fgetc(f);
+
+  if (a.size() > preLen) a.erase (a.begin()+preLen, a.end());
+
+  // reserve the needed space in advance
+  if (a.capacity() < a.size() + sufLen + 1) {
+    a.reserve(a.size() + sufLen + 1);
+  }
+
+  while (sufLen > 0) {
+    unsigned char c = fgetc (f);
+    a.push_back (c);
+    --sufLen;
+  }
+
+  return true;
+}
+
Index: /indexers/branches/3.03a/mgpp/text/UCArray.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/UCArray.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/UCArray.h	(revision 14757)
@@ -0,0 +1,131 @@
+/**************************************************************************
+ *
+ * UCArray.h -- vector based string class
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef UCARRAY_H
+#define UCARRAY_H
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
+#pragma warning(disable:4786)
+#endif
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if !defined (GSDL_NAMESPACE_BROKEN) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+using namespace std;
+#endif
+
+#if defined(GSDL_USE_OBJECTSPACE)
+#  include <ospace\std\vector>
+#  include <ospace\std\set>
+#elif defined(GSDL_USE_STL_H)
+#  include <vector.h>
+#  include <set.h>
+#else
+#  include <vector>
+#  include <set>
+#endif
+
+#if defined(GSDL_USE_OBJECTSPACE)
+#  include <ospace\std\iostream>
+#elif defined(GSDL_USE_IOS_H)
+#  include <iostream.h>
+#else
+#  include <iostream>
+#endif
+
+#include <stdio.h>
+
+
+typedef vector<unsigned char> UCArray;
+
+// functions to manipulate UCArrays
+void SetCStr (UCArray &text, const char *cStr);
+// same as SetCStr but first tries to allocate nSizeHint space (only if needed)
+void SetCStr (UCArray &text, const char *cStr, size_t nSizeHint);
+char * GetCStr(const UCArray& text);
+inline void UCArrayClear (UCArray &a) {
+  a.erase (a.begin(), a.end());
+}
+bool UCArrayCStrEquals(const UCArray &text, const unsigned char *cStr);
+inline bool UCArrayCStrEquals(const UCArray &text, const char *cStr) { return UCArrayCStrEquals(text, (const unsigned char *)cStr); }
+
+// stream operator to print UCArray
+ostream &operator<<(ostream &s, const UCArray &a);
+
+// used for reading and writing unsigned characters
+inline bool ReadUC (FILE *f, unsigned char &c) {
+  return (fread (&c, sizeof (unsigned char), 1, f) == 1);
+}
+inline bool WriteUC (FILE *f, unsigned char c) {
+  return (fwrite (&c, sizeof (unsigned char), 1, f) == 1);
+}
+
+// used for reading and writing variable length unsigned longs
+bool ReadVarLenUL (FILE *f, unsigned long &n);
+bool WriteVarLenUL (FILE *f, unsigned long n);
+
+// used for reading and writing unsigned longs
+bool ReadUL (FILE *f, unsigned long &n);
+bool WriteUL (FILE *f, unsigned long n);
+
+// used for reading and writing floats
+bool ReadF (FILE *f, float &n);
+bool WriteF (FILE *f, float n);
+
+// used for reading and writing doubles
+bool ReadD (FILE *f, double &n);
+bool WriteD (FILE *f, double n);
+
+// used for reading and writing arrays to files
+bool ReadUCArray (FILE *f, UCArray &a);
+bool WriteUCArray (FILE *f, const UCArray &a);
+
+
+// compares the two strings in dictionary order
+int DictCompare (const UCArray &a1, const UCArray &a2);
+
+// does the first string start with the second?
+bool StartsWith(const UCArray &a1, const UCArray &a2);
+// does the first string start with the second, ignoring case?
+bool StartsWithCasefold(const UCArray &a1, const UCArray &a2);
+
+struct LTUCArray {
+  bool operator()(const UCArray &a1, const UCArray &a2) const
+    { return (a1 < a2); }
+};
+
+struct DictLTUCArray {
+  bool operator() (const UCArray &a1, const UCArray &a2) const
+    { return (DictCompare (a1, a2) < 0); }
+};
+
+
+typedef set<UCArray, LTUCArray> UCArraySet;
+typedef vector<UCArray> UCArrayVector;
+
+unsigned long PrefixLen (const UCArray &a1, const UCArray &a2);
+
+// prev == NULL if no previous string
+bool WritePreSufStr (FILE *f, const UCArray *prev, const UCArray &a);
+bool ReadPreSufStr (FILE *f, UCArray &a); // a also used for prev
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/WIN32.MAK
===================================================================
--- /indexers/branches/3.03a/mgpp/text/WIN32.MAK	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/WIN32.MAK	(revision 14757)
@@ -0,0 +1,193 @@
+###########################################################################
+#
+# win32 makefile -- mgpp\lib
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999  The New Zealand Digital Library Project
+#
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+MGPPHOME = ..
+# for now put executables in indexers/bin
+INSTALLDIR = ..\..\bin
+AR = lib
+CC = cl
+CPPFLAGS = -GX
+LINK = cl
+
+DEFS = -DQUIET -DHAVE_CONFIG_H -D__WIN32__ -DSHORT_SUFFIX -D__STDC__ -D__GNU_LIBRARY__ -D__MSDOS__
+INCLUDES = -I"." -I"$(MGPPHOME)" -I"$(MGPPHOME)\lib"
+LIBS = $(MGPPHOME)\lib\libmgpplib.lib
+
+COMPILE = $(CC) -c  $(CPPFLAGS) $(DEFS) $(INCLUDES)
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .obj
+.c.obj:
+	$(COMPILE) $<
+.cpp.obj:
+	$(COMPILE) $<
+
+ANSI2KNR = 
+o = .obj
+e = .exe
+
+HEADERS = \
+  FIvfLevelInfo.h     TextEl.h            hash.h              stemmer.h  \
+  FText.h             TextGet.h           invf.h              text.h     \
+  FileBuf.h           UCArray.h           locallib.h          words.h    \
+  FragLevelConvert.h  WordData.h          mg.h                           \
+  IndexData.h         build.h             mg_errors.h                    \
+  TagInfo.h           comp_dict.h         mg_files.h          Weights.h  \
+  MGQuery.h           Terms.h             QueryLex.h          QueryParser.h \
+  GSDLQueryLex.h	GSDLQueryParser.h
+
+
+SOURCES = \
+  FIvfLevelInfo.cpp        ivf.pass1.cpp            mgpp_invf_dump.cpp       \
+  FText.cpp                ivf.pass2.cpp            mgpp_passes.cpp          \
+  FileBuf.cpp              locallib.cpp             mgpp_perf_hash_build.cpp \
+  FragLevelConvert.cpp     mg.special.cpp           mgpp_stem_idx.cpp        \
+  IndexData.cpp            mgpp_compression_dict.cpp  mgpp_weights_build.cpp   \
+  TagInfo.cpp              mgpp_decompress_text.cpp   stemmer.cpp            \
+  TextEl.cpp               mg_errors.cpp            text.cpp               \
+  TextGet.cpp              mgpp_fast_comp_dict.cpp    text.pass1.cpp         \
+  UCArray.cpp              mg_files.cpp             text.pass2.cpp         \
+  comp_dict.cpp            mgpp_invf_dict.cpp         words.cpp              \
+  invf.cpp                 mgpp_invf_dict_dump.cpp    Weights.cpp            \
+  MGQuery.cpp              Terms.cpp                QueryTester.cpp        \
+  QueryLex.cpp             QueryParser.cpp         \
+  GSDLQueryLex.cpp	   GSDLQueryParser.cpp      Queryer.cpp
+
+
+EXEC          = mgpp_passes$e mgpp_decompress_text$e mgpp_perf_hash_build$e \
+                mgpp_invf_dump$e mgpp_weights_build$e mgpp_invf_dict$e \
+		mgpp_stem_idx$e mgpp_invf_dict_dump$e mgpp_compression_dict$e \
+		mgpp_fast_comp_dict$e QueryTester$e Queryer$e
+
+DISTFILES = Makefile.in $(HEADERS) $(SOURCES)
+ 
+all : $(EXEC) libmgpptext.lib libmgpppass.lib
+
+
+PASSES_OBJS = \
+	mgpp_passes$o text.pass1$o comp_dict$o \
+	text.pass2$o locallib$o \
+	ivf.pass1$o ivf.pass2$o mg.special$o mg_files$o \
+	words$o invf$o FileBuf$o TextEl$o UCArray$o TagInfo$o \
+        FText$o text$o FIvfLevelInfo$o
+
+mgpp_passes$e: $(PASSES_OBJS)
+	$(LINK) $(PASSES_OBJS) $(LIBS)
+
+QUERYER_OBJS = Queryer$o mg_files$o mg_errors$o locallib$o invf$o UCArray$o \
+               FIvfLevelInfo$o FragLevelConvert$o Terms$o MGQuery$o \
+               IndexData$o stemmer$o Weights$o TextGet$o text$o FText$o \
+               GSDLQueryParser$o GSDLQueryLex$o words$o
+
+Queryer$e: $(QUERYER_OBJS)
+	$(LINK) $(QUERYER_OBJS) $(LIBS)
+
+QUERY_TESTER_OBJS = QueryTester$o mg_files$o invf$o UCArray$o \
+                    FIvfLevelInfo$o FragLevelConvert$o Terms$o MGQuery$o \
+                    IndexData$o stemmer$o Weights$o
+
+QueryTester$e: $(QUERY_TESTER_OBJS)
+	$(LINK) $(QUERY_TESTER_OBJS) $(LIBS)
+
+WEIGHTS_BUILD_OBJS = mgpp_weights_build$o mg_files$o invf$o UCArray$o \
+                     FIvfLevelInfo$o FragLevelConvert$o
+
+mgpp_weights_build$e: $(WEIGHTS_BUILD_OBJS)
+	$(LINK) $(WEIGHTS_BUILD_OBJS) $(LIBS)
+
+COMP_DICT_OBJS = mgpp_compression_dict$o mg_files$o locallib$o
+
+mgpp_compression_dict$e: $(COMP_DICT_OBJS)
+	$(LINK) $(COMP_DICT_OBJS) $(LIBS)
+
+FAST_COMP_OBJS = mgpp_fast_comp_dict$o mg_files$o locallib$o
+
+mgpp_fast_comp_dict$e: $(FAST_COMP_OBJS)
+	$(LINK) $(FAST_COMP_OBJS) $(LIBS)
+
+INVF_DUMP_OBJS = mgpp_invf_dump$o locallib$o mg_files$o invf$o UCArray$o
+
+mgpp_invf_dump$e: $(INVF_DUMP_OBJS)
+	$(LINK) $(INVF_DUMP_OBJS) $(LIBS)
+
+INVF_DICT_OBJS = mgpp_invf_dict$o mg_files$o invf$o UCArray$o
+
+mgpp_invf_dict$e: $(INVF_DICT_OBJS)
+	$(LINK) $(INVF_DICT_OBJS) $(LIBS)
+
+INVF_DICT_DUMP_OBJS = mgpp_invf_dict_dump$o mg_files$o invf$o UCArray$o
+
+mgpp_invf_dict_dump$e: $(INVF_DICT_DUMP_OBJS)
+	$(LINK) $(INVF_DICT_DUMP_OBJS) $(LIBS)
+
+PERF_HASH_OBJS = mgpp_perf_hash_build$o mg_files$o invf$o UCArray$o
+
+mgpp_perf_hash_build$e: $(PERF_HASH_OBJS)
+	$(LINK) $(PERF_HASH_OBJS) $(LIBS)
+
+STEM_IDX_OBJS = mgpp_stem_idx$o mg_files$o stemmer$o \
+                invf$o UCArray$o
+
+mgpp_stem_idx$e: $(STEM_IDX_OBJS)
+	$(LINK) $(STEM_IDX_OBJS) $(LIBS)
+
+DECOMPRESS_TEXT_OBJS = \
+                mgpp_decompress_text$o mg_files$o mg_errors$o \
+                locallib$o text$o UCArray$o TextGet$o FText$o
+
+mgpp_decompress_text$e: $(DECOMPRESS_TEXT_OBJS)
+	$(LINK) $(DECOMPRESS_TEXT_OBJS) $(LIBS)
+
+
+LIB_OBJS = mg_files$o  mg_errors$o locallib$o invf$o UCArray$o \
+           FIvfLevelInfo$o FragLevelConvert$o Terms$o MGQuery$o \
+           IndexData$o stemmer$o Weights$o TextGet$o text$o FText$o \
+           GSDLQueryParser$o GSDLQueryLex$o words$o
+
+libmgpptext.lib: $(LIB_OBJS)
+        if exist libmgpptext.lib del libmgpptext.lib
+        $(AR) /out:libmgpptext.lib $(LIB_OBJS)
+
+JNI_LIB_OBJS = \
+	mgpp_passes_4jni$o text.pass1$o comp_dict$o \
+	text.pass2$o locallib$o \
+	ivf.pass1$o ivf.pass2$o mg.special$o mg_files$o \
+	words$o invf$o FileBuf$o TextEl$o UCArray$o TagInfo$o \
+        FText$o text$o FIvfLevelInfo$o
+
+libmgpppass.lib: $(JNI_LIB_OBJS)
+	if exist libmgpppass.lib del libmgpppass.lib
+	$(AR) /out:libmgpppass.lib $(JNI_LIB_OBJS)
+
+install: 
+	if not exist "$(INSTALLDIR)" mkdir "$(INSTALLDIR)"
+	for %%i in ($(EXEC)) do \
+	  copy %%i "$(INSTALLDIR)"
+ 
+clean:
+	del *$o 
+        del libmgpptext.lib libmgpppass.lib
+
Index: /indexers/branches/3.03a/mgpp/text/Weights.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/Weights.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/Weights.cpp	(revision 14757)
@@ -0,0 +1,126 @@
+/**************************************************************************
+ *
+ * Weights.cpp -- Dealing with document weights
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "UCArray.h"
+#include "Weights.h"
+#include "sysfuncs.h"
+
+#define MAXBITS (sizeof(unsigned long) * 8)
+
+
+ApproxWeightsData::ApproxWeightsData () {
+  weightBuf = NULL;
+  table = NULL;
+  Free();
+}
+
+ApproxWeightsData::~ApproxWeightsData () {
+  Free ();
+}
+
+void ApproxWeightsData::Free () {
+  bits = 0;
+  mask = 0;
+  L = 0.0;
+  B = 0.0;
+  numLevelDocs = 0;
+  if (weightBuf != NULL) {
+    delete [] weightBuf;
+    weightBuf = NULL;
+  }
+  if (table != NULL) {
+    delete [] table;
+    table = NULL;
+  }
+}
+
+bool ApproxWeightsData::Read (FILE *approxWeightsFile, unsigned long diskPtr,
+			      unsigned long _numLevelDocs) {
+  Free ();
+  
+  // go to the appropriate place in the weights file
+  fseek (approxWeightsFile, diskPtr, SEEK_SET);
+
+  // read in approx weights parameters
+  ReadUC (approxWeightsFile, bits);
+  ReadD (approxWeightsFile, L);
+  ReadD (approxWeightsFile, B);
+
+  mask = (bits == 32) ? 0xffffffff : (1 << bits) - 1;
+  numLevelDocs = _numLevelDocs;
+
+  // allocate buffer for the weights
+  unsigned long arrSize = (bits*numLevelDocs+sizeof(unsigned long)-1) / 32;
+  weightBuf = new unsigned long[arrSize];
+
+  // read in the weights
+  unsigned long i;
+  for (i=0; i<arrSize; ++i) {
+    ReadUL (approxWeightsFile, weightBuf[i]);
+  }
+
+  // create precomputed table of values if it will be small enough
+  // (if not small enough table == NULL
+  if (bits <= 12) {
+    unsigned long i, tableSize = (1 << bits);
+    table = new float[tableSize];
+    table[0] = L;
+    for (i = 1; i < tableSize; ++i)
+      table[i] = table[i - 1] * B;
+  }
+
+  return true;
+}
+
+float ApproxWeightsData::GetLowerApproxDocWeight (unsigned long levelDocNum) {
+  // sanity check
+  if (bits == 0 || weightBuf == NULL) return 1.0;
+
+  register unsigned long c, pos;
+  register unsigned long *dw;
+
+  // get the compressed version of the weight
+  pos = levelDocNum * bits;
+  dw = &weightBuf[pos / MAXBITS];
+  pos &= (MAXBITS - 1);
+  c = *dw >> pos;
+  if (pos + bits > MAXBITS)
+    c |= *(dw + 1) << (MAXBITS - pos);
+  c &= mask;
+
+  // decompress the weight
+  if (table != NULL) return table[c];
+  return (L * pow (B, (double) c));
+}
+
+
+
+float GetExactDocWeight (FILE *exactWeightsFile, unsigned long diskPtr,
+			 unsigned long levelDocNum) {
+  // go to the appropriate place in the weights file
+  fseek (exactWeightsFile, diskPtr+sizeof(float)*levelDocNum, SEEK_SET);
+
+  // read in the exact weight
+  float weight;
+  ReadF (exactWeightsFile, weight);
+  
+  return weight;
+}
Index: /indexers/branches/3.03a/mgpp/text/Weights.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/Weights.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/Weights.h	(revision 14757)
@@ -0,0 +1,56 @@
+/**************************************************************************
+ *
+ * Weights.h -- Dealing with document weights
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef WEIGHTS_H
+#define WEIGHTS_H
+
+#include <stdio.h>
+
+
+class ApproxWeightsData {
+public:
+  unsigned char bits;
+  unsigned long mask;
+  double L;
+  double B;
+  unsigned long numLevelDocs;
+  unsigned long *weightBuf;
+  float *table;   // precomputed translation table
+  
+  ApproxWeightsData ();
+  ~ApproxWeightsData ();
+
+  void Free (); // frees any allocated memory
+  
+  bool Read (FILE *approxWeightsFile, unsigned long diskPtr,
+	     unsigned long _numLevelDocs);
+
+  float GetLowerApproxDocWeight (unsigned long levelDocNum);
+};
+
+
+// diskPtr points to the start of the exact document weights
+// for this level
+float GetExactDocWeight (FILE *exactWeightsFile, unsigned long diskPtr,
+			 unsigned long levelDocNum);
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/WordData.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/WordData.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/WordData.h	(revision 14757)
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * WordData.h -- 
+ * Copyright (C) 1999  NZDL
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+class WordData
+{
+
+ public:
+  unsigned long docCount;
+  unsigned long wordCount;
+
+  inline void read(FILE *f)
+    {
+      fread((char *) &docCount, sizeof(docCount), 1, f);
+      fread((char *) &wordCount, sizeof(wordCount), 1, f);
+
+      NTOHUL(docCount);
+      NTOHUL(wordCount);
+    }
+
+  inline unsigned long documents()
+    {
+      return docCount;
+    }
+
+  inline int words()
+    {
+      return wordCount;
+    }
+};
Index: /indexers/branches/3.03a/mgpp/text/build.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/build.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/build.h	(revision 14757)
@@ -0,0 +1,86 @@
+/**************************************************************************
+ *
+ * build.h -- Global information for the passes of mg_passes
+ * Copyright (C) 1994  Neil Sharman, Alistair Moffat and Lachlan Andrew
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+
+#ifndef H_BUILD
+#define H_BUILD
+
+#include "longlong.h"
+
+#include "TextEl.h"
+#include "TagInfo.h"
+
+
+int init_special (const TagInfo &tagInfo, char *file_name);
+int init_text_1 (const TagInfo &tagInfo, char *file_name);
+int init_text_2 (const TagInfo &tagInfo, char *file_name);
+int init_ivf_1 (const TagInfo &tagInfo, char *file_name);
+int init_ivf_2 (const TagInfo &tagInfo, char *file_name);
+/*
+ * file_name  IN      The name of the dictionary file
+ * 
+ * returns      COMPALLOK for all ok,
+ *              COMPERROR for any error.  e.g. cannot read file
+ */
+
+
+
+
+
+int process_special (const TagInfo &tagInfo, const TextElArray &doc);
+int process_text_1 (const TagInfo &tagInfo, const TextElArray &doc);
+int process_text_2 (const TagInfo &tagInfo, const TextElArray &doc);
+int process_ivf_1 (const TagInfo &tagInfo, const TextElArray &doc);
+int process_ivf_2 (const TagInfo &tagInfo, const TextElArray &doc);
+/*
+ * returns      COMPALLOK for all ok,
+ *              COMPERROR for any error.  e.g. cannot read file
+ *
+ * The calling routine is responsible for ensuring that s_out is long 
+ * enough.
+ */
+
+
+
+
+
+int done_special (const TagInfo &tagInfo, char *filename);
+int done_text_1 (const TagInfo &tagInfo, char *filename);
+int done_text_2 (const TagInfo &tagInfo, char *filename);
+int done_ivf_1 (const TagInfo &tagInfo, char *filename);
+int done_ivf_2 (const TagInfo &tagInfo, char *filename);
+/*
+ * returns    COMPALLOK for all ok,
+ *              COMPERROR for any error.  e.g. cannot write file
+ */
+
+
+
+
+extern unsigned long invf_buffer_size;
+/*
+ * The amount of memory to allocate to the invertion buffer.
+ */
+
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/comp_dict.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/comp_dict.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/comp_dict.cpp	(revision 14757)
@@ -0,0 +1,229 @@
+/**************************************************************************
+ *
+ * comp_dict.cpp -- Functions for loading the compression dictionary
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "huffman.h"
+#include "local_strings.h"
+#include "memlib.h"
+#include "messages.h"
+
+#include "mg.h"
+#include "hash.h"
+#include "text.h"
+#include "comp_dict.h"
+#include "locallib.h"
+#include "mg_files.h"
+
+compression_dict_header cdh;
+compressed_text_header cth;
+comp_frags_header cfh[2];
+
+dict_hash_table *ht[2];
+
+huff_data char_huff[2];
+huff_data lens_huff[2];
+u_long *char_codes[2], *lens_codes[2];
+u_long Words_disk = 0;
+u_long Chars_disk = 0;
+
+
+static dict_hash_table *
+ReadInWords (FILE * dict, comp_frags_header * cfh,
+	     int esc)
+{
+  int i;
+  u_char *allwords, *prev = NULL;
+  dict_hash_table *ht;
+  u_char **words;
+  u_long ht_size;
+
+  ht_size = prime (cfh->hd.num_codes * HASH_RATIO);
+  if (!(ht = (dict_hash_table *) Xmalloc (sizeof (dict_hash_table) +
+		                            (ht_size - 1) * sizeof (ht->table[0]))))
+    {
+      Message ("no memory for hash_table\n");
+      return NULL;
+    }
+
+  ht->size = ht_size;
+  ht->hd = &cfh->hd;
+
+  if (!(ht->codes = Generate_Huffman_Codes (&cfh->hd, NULL)))
+    {
+      Message ("no memory for huffman codes\n");
+      return NULL;
+    }
+
+  if (!(ht->words = (u_char **) Xmalloc (sizeof (u_char *) * cfh->hd.num_codes)))
+    {
+      Message ("no memory for word pointers\n");
+      return NULL;
+    }
+  words = ht->words;
+
+  memset (ht->table, '\0', ht_size * sizeof (ht->table[0]));
+
+  if (!(allwords = (u_char *) Xmalloc (sizeof (u_char) * cfh->uncompressed_size)))
+    {
+      Message ("no memory for words\n");
+      return NULL;
+    }
+
+  for (i = 0; i < cfh->hd.num_codes; ++i, ++words)
+    {
+      register int val, copy;
+      val = fgetc (dict);
+      copy = (val >> 4) & 0xf;
+      val &= 0xf;
+
+      *words = allwords;
+
+      memcpy (allwords + 1, prev + 1, copy);
+      fread (allwords + copy + 1, sizeof (u_char), val, dict);
+      *allwords = val + copy;
+
+      Words_disk += val + 1;
+
+      /* insert into the hash table */
+      if (i < cfh->hd.num_codes - esc)
+	{
+	  register u_char **wptr;
+	  register unsigned long tsize = ht->size;
+	  register unsigned long hashval, step;
+
+	  HASH (hashval, step, allwords, tsize);
+
+	  wptr = ht->table[hashval];
+	  for (; wptr;)
+	    {
+	      hashval += step;
+	      if (hashval >= tsize)
+		hashval -= tsize;
+	      wptr = ht->table[hashval];
+	    }
+	  ht->table[hashval] = words;
+	}
+      prev = allwords;
+      allwords += *allwords + 1;
+    }
+  return ht;
+}
+
+inline int LoadWords(FILE *dict, int which)
+{
+  if (Read_cfh (dict, &cfh[which], NULL, &Words_disk) == -1)
+    return 1;
+  
+  if (!(ht[which] = ReadInWords (dict, &cfh[which], 0)))
+    return 1;
+
+  return 0;
+}
+
+inline int LoadHuffmanCodes(FILE *dict, int which)
+{
+  if (Read_Huffman_Data (dict, &char_huff[which], NULL,
+			 &Chars_disk) == -1)
+    return 1;
+  if (!(char_codes[which] =
+	Generate_Huffman_Codes (&char_huff[which], NULL)))
+    return 2;
+  if (Read_Huffman_Data (dict, &lens_huff[which], NULL,
+			 &Chars_disk) == -1)
+    return 3;
+  if (!(lens_codes[which] =
+	Generate_Huffman_Codes (&lens_huff[which], NULL)))
+    return 4;
+
+  return 0;
+}
+
+int 
+LoadCompressionDictionary (char *dict_file_name)
+{
+  FILE *dict;
+  int which;
+  if (!(dict = open_named_file (dict_file_name, "rb", MAGIC_DICT, MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    return COMPERROR;
+
+  Words_disk = sizeof (u_long);
+
+  if (Read_cdh (dict, &cdh, NULL, &Words_disk) == -1)
+    goto error;
+
+  for (which = 0; which < 2; ++which)
+    switch (cdh.dict_type)
+      {
+      case MG_COMPLETE_DICTIONARY:
+	{
+	  if (LoadWords(dict, which) != 0)
+	    goto error;
+	}
+	break;
+      case MG_PARTIAL_DICTIONARY:
+	{
+	  if (cdh.num_words[which])
+	    {
+	      if (LoadWords(dict, which) != 0)
+		goto error;
+	    }
+	  else
+	    ht[which] = NULL;
+	  if (LoadHuffmanCodes(dict, which) != 0)
+	    goto error;
+	}
+	break;
+      case MG_SEED_DICTIONARY:
+	{
+	  if (cdh.num_words[which])
+	    {
+	      if (LoadWords(dict, which) != 0)
+		goto error;
+	    }
+	  else
+	    ht[which] = NULL;
+	  switch (cdh.novel_method)
+	    {
+	    case MG_NOVEL_HUFFMAN_CHARS:
+	      if (LoadHuffmanCodes(dict, which) != 0)
+		goto error;
+	      break;
+	    case MG_NOVEL_DELTA:
+	      break;
+	    case MG_NOVEL_HYBRID:
+	      break;
+	    default:
+	      FatalError (1, "Bad novel method");
+	    }
+	}
+	break;
+      default:
+	FatalError (1, "Bad dictionary kind\n");
+      }
+
+  return (COMPALLOK);
+
+
+error:
+  fclose (dict);
+  return (COMPERROR);
+}
Index: /indexers/branches/3.03a/mgpp/text/comp_dict.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/comp_dict.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/comp_dict.h	(revision 14757)
@@ -0,0 +1,48 @@
+/**************************************************************************
+ *
+ * comp_dict.h -- Functions for loading the compression dictionary
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define HASH_RATIO 2
+
+typedef struct dict_hash_table
+  {
+    u_long size;
+    huff_data *hd;
+    u_long *codes;
+    u_char **words;
+    u_char **table[1];
+  }
+dict_hash_table;
+
+extern compression_dict_header cdh;
+extern compressed_text_header cth;
+extern comp_frags_header cfh[2];
+
+extern dict_hash_table *ht[2];
+
+extern huff_data char_huff[2];
+extern huff_data lens_huff[2];
+extern u_long *char_codes[2], *lens_codes[2];
+extern u_long Words_disk;
+extern u_long Chars_disk;
+
+
+
+int LoadCompressionDictionary (char *dict_file_name);
Index: /indexers/branches/3.03a/mgpp/text/hash.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/hash.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/hash.h	(revision 14757)
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * hash.h -- Hash function
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_HASH
+#define H_HASH
+
+#define HASH(h, step, wd, tablesize)			\
+	do {						\
+		register u_char *p=wd;			\
+		register long len = *p++;		\
+		register unsigned long hval;		\
+		if (len>25) len = 25;			\
+		for (hval=0; len; --len)		\
+		  hval = (hval << 5) - hval + *p++;	\
+		step = hval % (tablesize - 2) + 1;	\
+		h = hval % tablesize;			\
+	} while (0)
+
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/invf.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/invf.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/invf.cpp	(revision 14757)
@@ -0,0 +1,914 @@
+/**************************************************************************
+ *
+ * invf.cpp -- Data structures for inverted files
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "invf.h"
+#include "UCArray.h"
+
+
+invf_dict_header::invf_dict_header () {
+  Clear();
+}
+
+invf_dict_header::~invf_dict_header () {
+}
+
+void invf_dict_header::Clear() {
+  lookback = 0;
+  word_dict_start = 0;
+  word_dict_size = 0;
+  tag_dict_start = 0;
+  tag_dict_size = 0;
+  num_docs = 0;
+  num_frags = 0;
+  num_words = 0;
+  total_bytes = 0;
+  index_string_bytes = 0;
+  num_levels = 0;
+}
+
+bool invf_dict_header::Read (FILE *f) {
+  return (ReadUL (f, lookback) &&
+	  ReadUL (f, word_dict_start) &&
+	  ReadUL (f, word_dict_size) &&
+	  ReadUL (f, tag_dict_start) &&
+	  ReadUL (f, tag_dict_size) &&
+	  ReadUL (f, num_docs) &&
+	  ReadUL (f, num_frags) &&
+	  ReadUL (f, num_words) &&
+	  ReadUL (f, total_bytes) &&
+	  ReadUL (f, index_string_bytes) &&
+	  ReadUL (f, num_levels));
+}
+
+bool invf_dict_header::Write (FILE *f) const {
+  return (WriteUL (f, lookback) &&
+	  WriteUL (f, word_dict_start) &&
+	  WriteUL (f, word_dict_size) &&
+	  WriteUL (f, tag_dict_start) &&
+	  WriteUL (f, tag_dict_size) &&
+	  WriteUL (f, num_docs) &&
+	  WriteUL (f, num_frags) &&
+	  WriteUL (f, num_words) &&
+	  WriteUL (f, total_bytes) &&
+	  WriteUL (f, index_string_bytes) &&
+	  WriteUL (f, num_levels));
+}
+
+
+
+void dict_el::Clear () {
+  el.erase (el.begin(), el.end());
+  frag_occur = 0;
+  freq = 0;
+}
+
+bool dict_el::Read (FILE *f) {
+  return (ReadPreSufStr (f, el) &&
+	  ReadUL (f, frag_occur) &&
+	  ReadUL (f, freq));
+}
+
+bool dict_el::Write (FILE *f, const UCArray *lastEl) const {
+  return (WritePreSufStr (f, lastEl, el) &&
+	  WriteUL (f, frag_occur) &&
+	  WriteUL (f, freq));
+}
+
+
+void word_dict_el::Clear () {
+  dict_el::Clear();
+  if (levelFreqs != NULL) delete [] levelFreqs;
+  levelFreqs = NULL;
+}
+
+word_dict_el::~word_dict_el () {
+  if (levelFreqs != NULL) delete [] levelFreqs;
+}
+
+void word_dict_el::SetNumLevels (unsigned long numLevels) {
+  if (levelFreqs != NULL) delete [] levelFreqs;
+  levelFreqs = new unsigned long [numLevels];
+}
+  
+bool word_dict_el::Read (FILE *f, unsigned long numLevels) {
+  if (!dict_el::Read (f)) return false;
+
+  if (levelFreqs == NULL) return false;
+  
+  unsigned long i;
+  for (i=0; i<numLevels; ++i) {
+    if (!ReadUL (f, levelFreqs[i])) return false;
+  }
+
+  return true;
+}
+
+bool word_dict_el::Write (FILE *f, const UCArray *lastEl,
+			  unsigned long numLevels) const {
+  if (!dict_el::Write (f, lastEl)) return false;
+
+  if (levelFreqs == NULL) return false;
+
+  unsigned long i;
+  for (i=0; i<numLevels; ++i) {
+    if (!WriteUL (f, levelFreqs[i])) return false;
+  }
+
+  return true;
+}
+
+
+
+block_dict_header::block_dict_header () {
+  Clear();
+}
+
+void block_dict_header::Clear () {
+  invf_dict_header::Clear();
+
+  entries_per_wblk = 0;
+  num_wblks = 0;
+  max_wblk_size = 0;
+  wblk_start = 0;
+  wblk_idx_start = 0;
+  
+  entries_per_tblk = 0;
+  num_tblks = 0;
+  max_tblk_size = 0;
+  tblk_start = 0;
+  tblk_idx_start = 0;
+}
+
+bool block_dict_header::Read (FILE *f) {
+  return (invf_dict_header::Read (f) &&
+
+	  ReadUL (f, entries_per_wblk) &&
+	  ReadUL (f, num_wblks) &&
+	  ReadUL (f, max_wblk_size) &&
+	  ReadUL (f, wblk_start) &&
+	  ReadUL (f, wblk_idx_start) &&
+  
+	  ReadUL (f, entries_per_tblk) &&
+	  ReadUL (f, num_tblks) &&
+	  ReadUL (f, max_tblk_size) &&
+	  ReadUL (f, tblk_start) &&
+	  ReadUL (f, tblk_idx_start));
+}
+
+bool block_dict_header::Write (FILE *f) const {
+  return (invf_dict_header::Write (f) &&
+
+	  WriteUL (f, entries_per_wblk) &&
+	  WriteUL (f, num_wblks) &&
+	  WriteUL (f, max_wblk_size) &&
+	  WriteUL (f, wblk_start) &&
+	  WriteUL (f, wblk_idx_start) &&
+  
+	  WriteUL (f, entries_per_tblk) &&
+	  WriteUL (f, num_tblks) &&
+	  WriteUL (f, max_tblk_size) &&
+	  WriteUL (f, tblk_start) &&
+	  WriteUL (f, tblk_idx_start));
+}
+
+
+
+
+
+void block_dict_el::Clear () {
+  el.erase (el.begin(), el.end());
+  frag_occur = 0;
+  freq = 0;
+  invf_ptr = 0;
+}
+
+bool block_dict_el::Read (FILE *f) {
+  return (ReadPreSufStr (f, el) &&
+	  ReadUL (f, frag_occur) &&
+	  ReadUL (f, freq) &&
+	  ReadUL (f, invf_ptr));
+}
+
+bool block_dict_el::Write (FILE *f, const UCArray *lastEl) const {
+  return (WritePreSufStr (f, lastEl, el) &&
+	  WriteUL (f, frag_occur) &&
+	  WriteUL (f, freq) &&
+	  WriteUL (f, invf_ptr));
+}
+
+
+
+
+
+void word_block_dict_el::Clear () {
+  block_dict_el::Clear();
+  if (levelFreqs != NULL) delete [] levelFreqs;
+  levelFreqs = NULL;
+}
+
+word_block_dict_el::~word_block_dict_el () {
+  if (levelFreqs != NULL) delete [] levelFreqs;
+}
+
+void word_block_dict_el::SetNumLevels (unsigned long numLevels) {
+  if (levelFreqs != NULL) delete [] levelFreqs;
+  levelFreqs = new unsigned long [numLevels];
+}
+
+bool word_block_dict_el::Read (FILE *f, unsigned long numLevels) {
+  if (!block_dict_el::Read (f)) return false;
+  
+  if (levelFreqs == NULL) return false;
+  
+  unsigned long i;
+  for (i=0; i<numLevels; ++i) {
+    if (!ReadUL (f, levelFreqs[i])) return false;
+  }
+
+  return true;
+}
+
+bool word_block_dict_el::Write (FILE *f, const UCArray *lastEl,
+				unsigned long numLevels) const {
+  if (!block_dict_el::Write (f, lastEl)) return false;
+  
+  if (levelFreqs == NULL) return false;
+  
+  unsigned long i;
+  for (i=0; i<numLevels; ++i) {
+    if (!WriteUL (f, levelFreqs[i])) return false;
+  }
+  
+  return true;
+}
+
+
+
+
+block_idx_info::block_idx_info () {
+  Clear ();
+}
+
+void block_idx_info::Clear () {
+  el.erase (el.begin(), el.end());
+  block_ptr = 0;
+}
+
+bool block_idx_info::Read (FILE *f) {
+  return (ReadUCArray (f, el) &&
+	  ReadUL (f, block_ptr));
+}
+
+bool block_idx_info::Write (FILE *f) const {
+  return (WriteUCArray (f, el) &&
+	  WriteUL (f, block_ptr));
+}
+
+
+bool ReadBlockIdx (FILE *f, block_idx &blockIdx) {
+  blockIdx.erase (blockIdx.begin(), blockIdx.end());
+  
+  // read in the array size
+  unsigned long arraySize = 0;
+  if (!ReadVarLenUL (f, arraySize)) return false;
+  
+  // read in the array
+  block_idx_info bi;
+  while (arraySize > 0) {
+    if (!bi.Read (f)) return false;
+    blockIdx.push_back (bi);
+    
+    --arraySize;
+  }
+  
+  return true;
+}
+
+bool WriteBlockIdx (FILE *f, const block_idx &blockIdx) {
+  // write out the array size
+  if (!WriteVarLenUL (f, blockIdx.size())) return false;
+
+  block_idx::const_iterator here = blockIdx.begin();
+  block_idx::const_iterator end = blockIdx.end();
+  while (here != end) {
+    if (!(*here).Write (f)) return false;
+    ++here;
+  }
+
+  return true;
+}
+
+
+
+
+stem_idx_header::stem_idx_header () {
+  Clear ();
+}
+
+void stem_idx_header::Clear () {
+  lookback = 0;
+  dict_size = 0;
+
+  entries_per_block = 0;
+  num_blocks = 0;
+  max_block_size = 0;
+  blocks_start = 0;
+  block_idx_start = 0;
+  
+  stemmer_num = 0;
+  stem_method = 0;
+}
+
+bool stem_idx_header::Read (FILE *f) {
+  return (ReadUL (f, lookback) &&
+	  ReadUL (f, dict_size) &&
+	  
+	  ReadUL (f, entries_per_block) &&
+	  ReadUL (f, num_blocks) &&
+	  ReadUL (f, max_block_size) &&
+	  ReadUL (f, blocks_start) &&
+	  ReadUL (f, block_idx_start) &&
+	  
+	  ReadUL (f, stemmer_num) &&
+	  ReadUL (f, stem_method));
+}
+
+bool stem_idx_header::Write (FILE *f) const {
+  return (WriteUL (f, lookback) &&
+	  WriteUL (f, dict_size) &&
+	  
+	  WriteUL (f, entries_per_block) &&
+	  WriteUL (f, num_blocks) &&
+	  WriteUL (f, max_block_size) &&
+	  WriteUL (f, blocks_start) &&
+	  WriteUL (f, block_idx_start) &&
+	  
+	  WriteUL (f, stemmer_num) &&
+	  WriteUL (f, stem_method));
+}
+
+
+
+stem_block_dict_el::stem_block_dict_el () {
+  Clear ();
+}
+
+void stem_block_dict_el::Clear () {
+  el.erase (el.begin(), el.end());
+  equivWords.erase (equivWords.begin(), equivWords.end());
+}
+
+bool stem_block_dict_el::Read (FILE *f) {
+  equivWords.erase (equivWords.begin(), equivWords.end());
+  
+  if (!ReadPreSufStr (f, el)) return false;
+  
+  // read in the array size
+  unsigned long arraySize = 0;
+  if (!ReadVarLenUL (f, arraySize)) return false;
+  
+  // read in the array
+  unsigned long wordNum;
+  while (arraySize > 0) {
+    if (!ReadUL (f, wordNum)) return false;
+    equivWords.push_back (wordNum);
+    
+    --arraySize;
+  }
+  
+  return true;
+}
+
+bool stem_block_dict_el::Write (FILE *f, const UCArray *lastEl) const {
+  if (!WritePreSufStr (f, lastEl, el)) return false;
+
+  // write out the array size
+  if (!WriteVarLenUL (f, equivWords.size())) return false;
+
+  vector<unsigned long>::const_iterator here = equivWords.begin();
+  vector<unsigned long>::const_iterator end = equivWords.end();
+  while (here != end) {
+    if (!WriteUL (f, (*here))) return false;
+    ++here;
+  }
+
+  return true;
+}
+
+
+
+
+invf_file_header::invf_file_header () {
+  Clear ();
+}
+
+void invf_file_header::Clear () {
+  no_of_words = 0;
+  no_of_tags = 0;
+  skip_mode = SKIP_MODE_NO_SKIPS;
+  word_level_index = 0;
+  
+  int i;
+  for (i=0; i<16; ++i) params[i] = 0;
+}
+  
+bool invf_file_header::Read (FILE *f) {
+  if (!ReadUL (f, no_of_words) ||
+      !ReadUL (f, no_of_tags) ||
+      !ReadUL (f, skip_mode) ||
+      !ReadUL (f, word_level_index)) return false;
+
+  int i;
+  for (i=0; i<16; ++i) {
+    if (!ReadUL (f, params[i])) return false;
+  }
+
+  return true;
+}
+
+bool invf_file_header::Write (FILE *f) const {
+  if (!WriteUL (f, no_of_words) ||
+      !WriteUL (f, no_of_tags) ||
+      !WriteUL (f, skip_mode) ||
+      !WriteUL (f, word_level_index)) return false;
+
+  int i;
+  for (i=0; i<16; ++i) {
+    if (!WriteUL (f, params[i])) return false;
+  }
+
+  return true;
+}
+
+
+
+
+
+bool SearchElNum (const block_idx &bIdx,
+		  unsigned long entriesPerBlock,
+		  unsigned long elNum,
+		  unsigned long &blockIdxNum,
+		  unsigned long &blockStartElNum) {
+  blockIdxNum = 0;
+  blockStartElNum = 0;
+
+  // make sure the element number isn't out of range
+  if (elNum > bIdx.size()*entriesPerBlock) return false;
+
+  blockIdxNum = elNum / entriesPerBlock;
+  blockStartElNum = blockIdxNum * entriesPerBlock;
+  
+  return true;
+}
+
+bool SearchEl (const block_idx &bIdx,
+	       unsigned long entriesPerBlock,
+	       const UCArray &el,
+	       unsigned long &blockIdxNum,
+	       unsigned long &blockStartElNum) {
+  blockIdxNum = 0;
+  blockStartElNum = 0;
+
+  unsigned long begin = 0;
+  unsigned long bIdxEnd = bIdx.size();
+  unsigned long end = bIdxEnd;
+  unsigned long mid;
+  while (begin < end) {
+    mid = (begin+end)/2;
+    if (DictCompare (el, bIdx[mid].el) < 0) {
+      end = mid;
+    } else if (mid+1 < bIdxEnd &&
+	       DictCompare (el, bIdx[mid+1].el) >= 0) {
+      begin = mid+1;
+    } else {
+      blockIdxNum = mid;
+      blockStartElNum = blockIdxNum * entriesPerBlock;
+      return true;
+    }
+  }
+  
+  return false;
+}
+
+
+
+// use the block dictionary functions for tag entries, and word block dict
+// functions for word entries.
+
+
+bool SearchBlockDictElNum (FILE *dictFile,
+			   const block_idx &bIdx,
+			   unsigned long entriesPerBlock,
+			   unsigned long dictSize,
+			   unsigned long elNum,
+			   block_dict_el &dictEl) {
+  UCArrayClear (dictEl.el);
+  if (elNum >= dictSize) return false;
+
+  // find the block that contains the element
+  unsigned long blockIdxNum, curElNum;
+  if (!SearchElNum (bIdx, entriesPerBlock, elNum,
+		    blockIdxNum, curElNum))
+    return false;
+
+  // look for the block
+  fseek (dictFile, bIdx[blockIdxNum].block_ptr, SEEK_SET);
+  do {
+    dictEl.Read (dictFile);
+  } while (curElNum++ < elNum);
+
+  return true;
+}
+
+bool SearchBlockDictEl (FILE *dictFile,
+			const block_idx &bIdx,
+			unsigned long entriesPerBlock,
+			unsigned long dictSize,
+			const UCArray &el,
+			block_dict_el &dictEl,
+			unsigned long &elNum) {
+  UCArrayClear (dictEl.el);
+
+  // find the block that contains the element
+  unsigned long blockIdxNum;
+  if (!SearchEl (bIdx, entriesPerBlock, el,
+		 blockIdxNum, elNum))
+    return false;
+
+  unsigned long blockEndElNum = elNum + entriesPerBlock;
+  if (blockEndElNum > dictSize) blockEndElNum = dictSize;
+
+  // look for the block
+  fseek (dictFile, bIdx[blockIdxNum].block_ptr, SEEK_SET);
+  while (elNum < blockEndElNum) {
+    dictEl.Read (dictFile);
+    int res = DictCompare (dictEl.el, el);
+    if (res == 0) return true; // found it
+    else if (res > 0) break; // not here
+    
+    ++elNum;
+  }
+
+  return false;
+}
+
+
+
+
+bool SearchWordBlockDictElNum (FILE *dictFile,
+			       const block_idx &bIdx,
+			       unsigned long entriesPerBlock,
+			       unsigned long dictSize,
+			       unsigned long numLevels,
+			       unsigned long elNum,
+			       word_block_dict_el &dictEl) {
+  UCArrayClear (dictEl.el);
+  if (elNum >= dictSize) return false;
+
+  // find the block that contains the element
+  unsigned long blockIdxNum, curElNum;
+  if (!SearchElNum (bIdx, entriesPerBlock, elNum,
+		    blockIdxNum, curElNum))
+    return false;
+
+  // look for the block
+  fseek (dictFile, bIdx[blockIdxNum].block_ptr, SEEK_SET);
+  do {
+    dictEl.Read (dictFile, numLevels);
+  } while (curElNum++ < elNum);
+
+  return true;
+}
+
+bool SearchWordBlockDictEl (FILE *dictFile,
+			    const block_idx &bIdx,
+			    unsigned long entriesPerBlock,
+			    unsigned long dictSize,
+			    unsigned long numLevels,
+			    const UCArray &el,
+			    word_block_dict_el &dictEl,
+			    unsigned long &elNum) {
+  UCArrayClear (dictEl.el);
+
+  // find the block that contains the element
+  unsigned long blockIdxNum;
+  if (!SearchEl (bIdx, entriesPerBlock, el,
+		 blockIdxNum, elNum))
+    return false;
+
+  unsigned long blockEndElNum = elNum + entriesPerBlock;
+  if (blockEndElNum > dictSize) blockEndElNum = dictSize;
+
+  // look for the block
+  fseek (dictFile, bIdx[blockIdxNum].block_ptr, SEEK_SET);
+  while (elNum < blockEndElNum) {
+    dictEl.Read (dictFile, numLevels);
+    int res = DictCompare (dictEl.el, el);
+    if (res == 0) return true; // found it
+    else if (res > 0) break; // not here
+    
+    ++elNum;
+  }
+
+  return false;
+}
+
+
+
+
+bool SearchStemBlockDictElNum (FILE *dictFile,
+			       const block_idx &bIdx,
+			       unsigned long entriesPerBlock,
+			       unsigned long dictSize,
+			       unsigned long elNum,
+			       stem_block_dict_el &dictEl) {
+  UCArrayClear (dictEl.el);
+  if (elNum >= dictSize) return false;
+
+  // find the block that contains the element
+  unsigned long blockIdxNum, curElNum;
+  if (!SearchElNum (bIdx, entriesPerBlock, elNum,
+		    blockIdxNum, curElNum))
+    return false;
+
+  // look for the block
+  fseek (dictFile, bIdx[blockIdxNum].block_ptr, SEEK_SET);
+  do {
+    dictEl.Read (dictFile);
+  } while (curElNum++ < elNum);
+
+  return true;
+}
+
+bool SearchStemBlockDictEl (FILE *dictFile,
+			    const block_idx &bIdx,
+			    unsigned long entriesPerBlock,
+			    unsigned long dictSize,
+			    const UCArray &el,
+			    stem_block_dict_el &dictEl,
+			    unsigned long &elNum) {
+  UCArrayClear (dictEl.el);
+
+  // find the block that contains the element
+  unsigned long blockIdxNum;
+  if (!SearchEl (bIdx, entriesPerBlock, el,
+		 blockIdxNum, elNum))
+    return false;
+
+  unsigned long blockEndElNum = elNum + entriesPerBlock;
+  if (blockEndElNum > dictSize) blockEndElNum = dictSize;
+
+  // look for the block
+  fseek (dictFile, bIdx[blockIdxNum].block_ptr, SEEK_SET);
+  while (elNum < blockEndElNum) {
+    dictEl.Read (dictFile);
+    int res = DictCompare (dictEl.el, el);
+    if (res == 0) return true; // found it
+    else if (res > 0) break; // not here
+    
+    ++elNum;
+  }
+
+  return false;
+}
+
+// ------------------------------------------
+// functions for partial term matching
+// ie find all words that start with xxx
+bool PartialMatchSearchWordBlockDictEl (FILE *dictFile,
+				 const block_idx &bIdx,
+				 unsigned long entriesPerBlock,
+				 unsigned long dictSize,
+				 unsigned long numLevels,
+				 const UCArray &el,
+				 word_block_dict_el &dictEl,
+				 vector<unsigned long> &elNumList,
+				 bool casefold) {
+
+  UCArrayClear (dictEl.el);
+  elNumList.erase (elNumList.begin(), elNumList.end());
+  unsigned long elNum;
+  // find the block that contains the element
+  unsigned long blockIdxNum;
+  // will this work??
+  if (!SearchEl (bIdx, entriesPerBlock, el,
+		 blockIdxNum, elNum)) {
+    return false;
+  }
+  unsigned long blockEndElNum = elNum + entriesPerBlock;
+  if (blockEndElNum > dictSize) blockEndElNum = dictSize;
+  
+  bool still_looking = true;
+  // look for the block
+  fseek (dictFile, bIdx[blockIdxNum].block_ptr, SEEK_SET);
+  // test each element
+  while (elNum < blockEndElNum) {
+    dictEl.Read (dictFile, numLevels);
+    if (StartsWithCasefold(dictEl.el, el)) {
+      if (casefold || StartsWith(dictEl.el, el)) {
+	elNumList.push_back(elNum);
+      }
+      still_looking=false; // we have found one now, so stop the next time we don't have a match
+    } else if (!still_looking) {
+      // we have found a match previously, and now this doesn't match
+      return true;
+    } // else keep looking
+    
+    ++elNum;
+  }
+  // if we get here, we are either still searching for the first
+  // case, or we are collecting terms.
+  if (still_looking) {
+    //we haven't found a match yet, just check the next element,
+    dictEl.Read (dictFile, numLevels);
+    if (!StartsWithCasefold(dictEl.el, el)) {
+      // the first element of the next block is not a match, so there are no matches
+      return false;
+    } else {
+      if (casefold || StartsWith(dictEl.el, el)) {
+	elNumList.push_back(elNum);
+	++elNum;
+      } 
+
+    }
+  }
+  // just keep accumulating matches until there are no more
+  dictEl.Read (dictFile, numLevels);
+  while (StartsWithCasefold(dictEl.el, el)) {
+    if (casefold || StartsWith(dictEl.el, el)) {
+      elNumList.push_back(elNum);
+    }
+    ++elNum;
+    dictEl.Read (dictFile, numLevels);
+  }
+  return true;
+  
+}
+
+
+//----------------------------------------------------------------
+// functions for full text browse
+
+bool NearestSearchWordBlockDictEl (FILE *dictFile,
+				   const block_idx &bIdx,
+				   unsigned long entriesPerBlock,
+				   unsigned long dictSize,
+				   unsigned long numLevels,
+				   const UCArray &el,
+				   word_block_dict_el &dictEl,
+				   unsigned long &elNum) {
+
+  UCArrayClear (dictEl.el);
+
+  // find the block that contains the element
+  unsigned long blockIdxNum;
+  if (!SearchEl (bIdx, entriesPerBlock, el,
+		 blockIdxNum, elNum))
+    return false;
+
+  unsigned long blockEndElNum = elNum + entriesPerBlock;
+  if (blockEndElNum > dictSize) blockEndElNum = dictSize;
+
+  // look for the block
+  fseek (dictFile, bIdx[blockIdxNum].block_ptr, SEEK_SET);
+  while (elNum < blockEndElNum) {
+    dictEl.Read (dictFile, numLevels);
+    int res = DictCompare (el, dictEl.el); // look for the first word that is
+                                     // greater or equal to the el
+    if (res <= 0) {
+      return true; // found one
+   } 
+    
+    ++elNum;
+  }
+  // it must be the last term
+  return true;
+
+
+}
+
+
+bool SearchWordBlockDictElNumRange (FILE *dictFile,
+				    const block_idx &bIdx,
+				    unsigned long entriesPerBlock,
+				    unsigned long dictSize,
+				    unsigned long numLevels,
+				    unsigned long elNum,
+				    unsigned long numWords,
+				    UCArrayVector &terms) {
+
+  word_block_dict_el dictEl;  
+  dictEl.SetNumLevels (numLevels);
+  UCArrayClear(dictEl.el);
+
+  terms.erase(terms.begin(), terms.end());
+
+  if (elNum >= dictSize) return false;
+  
+  // find the block that contains the element
+  unsigned long blockIdxNum, curElNum;
+  if (!SearchElNum (bIdx, entriesPerBlock, elNum,
+		    blockIdxNum, curElNum))
+    return false;
+
+  unsigned long lastElNum = elNum + numWords - 1;
+  if (lastElNum > dictSize) lastElNum = dictSize;
+
+  // look for the block
+  fseek (dictFile, bIdx[blockIdxNum].block_ptr, SEEK_SET);
+  
+  // get the first term
+  do {
+    dictEl.Read (dictFile, numLevels);
+  } while (curElNum++ < elNum);
+
+  terms.push_back(dictEl.el);
+  while (curElNum <= lastElNum ) {
+    dictEl.Read(dictFile, numLevels);
+    terms.push_back(dictEl.el);
+    ++curElNum;
+  }
+  
+
+  return true;
+}
+
+// NOte: before each addition of dictEl to the array, the level freqs array
+// is deleted, as this was causing problems - generating a seg fault, I think if
+// the vector had to be reallocated or something.
+// setNumLevels has to be called each time before a read, now, to set up the level
+//freqs array. this is necessary.
+bool SearchWordBlockDictElNumRange (FILE *dictFile,
+				    const block_idx &bIdx,
+				    unsigned long entriesPerBlock,
+				    unsigned long dictSize,
+				    unsigned long numLevels,
+				    unsigned long elNum,
+				    unsigned long numWords,
+				    word_block_dict_el_array &terms) {
+
+  word_block_dict_el dictEl;
+  dictEl.SetNumLevels (numLevels);
+  UCArrayClear(dictEl.el);
+
+  block_dict_el elem;
+  terms.erase(terms.begin(), terms.end());
+
+  if (elNum >= dictSize) return false;
+  
+  // find the block that contains the element
+  unsigned long blockIdxNum, curElNum;
+  if (!SearchElNum (bIdx, entriesPerBlock, elNum,
+		    blockIdxNum, curElNum))
+    return false;
+
+  unsigned long lastElNum = elNum + numWords - 1;
+  if (lastElNum > dictSize) lastElNum = dictSize;
+
+  // look for the block
+  fseek (dictFile, bIdx[blockIdxNum].block_ptr, SEEK_SET);
+  // get the first term
+  do {
+    dictEl.Read (dictFile, numLevels);
+  } while (curElNum++ < elNum);
+
+  dictEl.levelFreqs = NULL;
+  terms.push_back(dictEl);
+
+  while (curElNum <= lastElNum ) { 
+    dictEl.SetNumLevels(numLevels);
+    dictEl.Read(dictFile, numLevels);
+    dictEl.levelFreqs = NULL;
+    terms.push_back(dictEl);
+    ++curElNum;
+  }
+
+  return true;
+}
+
+
+
+
+
+
+
+
+
Index: /indexers/branches/3.03a/mgpp/text/invf.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/invf.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/invf.h	(revision 14757)
@@ -0,0 +1,351 @@
+/**************************************************************************
+ *
+ * invf.h -- Data structures for inverted files
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************/
+
+
+#ifndef H_INVF
+#define H_INVF
+
+#include <stdio.h>
+
+#include "UCArray.h"
+
+// NOTE: This does not include the magic number
+// header info for .invf.dict file
+struct invf_dict_header {
+  unsigned long lookback;
+  unsigned long word_dict_start;
+  unsigned long word_dict_size;
+  unsigned long tag_dict_start;
+  unsigned long tag_dict_size;
+  unsigned long num_docs;
+  unsigned long num_frags;
+  unsigned long num_words;
+  unsigned long total_bytes;
+  unsigned long index_string_bytes;
+  unsigned long num_levels;
+
+  invf_dict_header ();
+  virtual ~invf_dict_header ();
+  virtual void Clear();
+
+  virtual bool Read (FILE *f);
+  virtual bool Write (FILE *f) const;
+};
+
+
+struct dict_el {
+  UCArray el; // word or tag
+  unsigned long frag_occur;
+  unsigned long freq;
+
+  virtual void Clear ();
+  dict_el () { Clear (); }
+  virtual ~dict_el () { }
+
+  // Read assumes that the last word is in el
+  bool Read (FILE *f);
+  bool Write (FILE *f, const UCArray *lastEl) const;
+};
+
+
+struct word_dict_el : public dict_el {
+  unsigned long *levelFreqs;
+
+  void Clear ();
+  word_dict_el () { levelFreqs = NULL; Clear (); }
+  ~word_dict_el ();
+
+  void SetNumLevels (unsigned long numLevels);
+
+  // SetNumLevels should be called before either
+  // reading or writing using Read and Write
+  
+  // Read assumes that the last word is in el
+  bool Read (FILE *f, unsigned long numLevels);
+  bool Write (FILE *f, const UCArray *lastEl,
+	      unsigned long numLevels) const;
+};
+
+
+// wblk = word block
+// tblk = tag block
+// this version of the blocked dictionary uses a fixed number
+// of entries per block, not a fixed block size
+// info for .invf.dict.blocked file
+// blocked dict has a heap of blocks, some for words, some for tags
+// and an index into each set of blocks. The index has pointers to
+// the first entry in each block. Can do a binary search on the index
+// to find out which block an elemnet is in
+struct block_dict_header : public invf_dict_header {
+  // note: word_dict_start and tag_dict_start are undefined
+  // for blocked dictionaries
+
+  unsigned long entries_per_wblk; // word blocks
+  unsigned long num_wblks;
+  unsigned long max_wblk_size;
+  unsigned long wblk_start;
+  unsigned long wblk_idx_start;
+  
+  unsigned long entries_per_tblk; // tag blocks
+  unsigned long num_tblks;
+  unsigned long max_tblk_size;
+  unsigned long tblk_start;
+  unsigned long tblk_idx_start;
+  
+  block_dict_header ();
+  void Clear ();
+  
+  bool Read (FILE *f);
+  bool Write (FILE *f) const;
+};
+
+
+struct block_dict_el {
+  UCArray el; // word or tag
+  unsigned long frag_occur; // # entries in invf file - if have a
+  // word level index, this is the same as freq, otherwise, its the number
+  // of fragments containing this word
+  unsigned long freq; // # of times this word occurs
+  unsigned long invf_ptr; // pointer into inverted file
+
+  virtual void Clear ();
+  block_dict_el () { Clear (); }
+  virtual ~block_dict_el () { }
+
+  // Read assumes that the last word is in el
+  // set lastEl = NULL when no lookback is wanted (eg
+  // for the start of a block
+  bool Read (FILE *f);
+  bool Write (FILE *f, const UCArray *lastEl) const;
+};
+
+struct word_block_dict_el : public block_dict_el {
+  unsigned long *levelFreqs; // freq of the word at each level
+
+  void Clear ();
+  word_block_dict_el () { levelFreqs = NULL; Clear (); }
+  ~word_block_dict_el ();
+
+  void SetNumLevels (unsigned long numLevels);
+
+  // SetNumLevels should be called before either
+  // reading or writing using Read and Write
+  
+  // Read assumes that the last word is in el
+  bool Read (FILE *f, unsigned long numLevels);
+  bool Write (FILE *f, const UCArray *lastEl,
+	      unsigned long numLevels) const;
+};
+
+typedef vector<word_block_dict_el> word_block_dict_el_array;
+
+struct block_idx_info {
+  UCArray el;
+  unsigned long block_ptr;
+
+  block_idx_info ();
+  void Clear ();
+
+  bool Read (FILE *f);
+  bool Write (FILE *f) const;
+};
+
+// used for an index into the word and tag blocks
+typedef vector<block_idx_info> block_idx;
+
+bool ReadBlockIdx (FILE *f, block_idx &blockIdx);
+bool WriteBlockIdx (FILE *f, const block_idx &blockIdx);
+
+
+
+struct stem_idx_header {
+  unsigned long lookback;
+  unsigned long dict_size;
+
+  unsigned long entries_per_block;
+  unsigned long num_blocks;
+  unsigned long max_block_size;
+  unsigned long blocks_start;
+  unsigned long block_idx_start;
+  
+  unsigned long stemmer_num;
+  unsigned long stem_method;
+
+  stem_idx_header ();
+  void Clear ();
+
+  bool Read (FILE *f);
+  bool Write (FILE *f) const;
+};
+
+struct stem_block_dict_el {
+  UCArray el; // word or tag
+  vector<unsigned long> equivWords;
+  
+  stem_block_dict_el ();
+  void Clear ();
+
+  // Read assumes that the last word is in el
+  // set lastEl = NULL when no lookback is wanted (eg
+  // for the start of a block
+  bool Read (FILE *f);
+  bool Write (FILE *f, const UCArray *lastEl) const;
+};
+
+
+
+#define SKIP_MODE_NO_SKIPS 0
+
+// invf file - has a list of frags for each word, but the word is not 
+//  stored in the invf file - the dictionaries store the words, along
+// with num entries, and a pointer into invf file
+struct invf_file_header {
+  unsigned long no_of_words;
+  unsigned long no_of_tags;
+  unsigned long skip_mode;
+  unsigned long word_level_index; // 1 if word level index
+  unsigned long params[16];
+
+  invf_file_header ();
+  void Clear ();
+  
+  bool Read (FILE *f);
+  bool Write (FILE *f) const;
+};
+
+
+
+
+
+
+// the search functions returns true if a block that could
+// satisfy the request is found. these functions assume that
+// the block index is sorted by DictCompare (or DictLTUCArray)
+bool SearchElNum (const block_idx &bIdx,
+		  unsigned long entriesPerBlock,
+		  unsigned long elNum,
+		  unsigned long &blockIdxNum,
+		  unsigned long &blockStartElNum);
+bool SearchEl (const block_idx &bIdx,
+	       unsigned long entriesPerBlock,
+	       const UCArray &el,
+	       unsigned long &blockIdxNum,
+	       unsigned long &blockStartElNum);
+
+
+// The next six functions use SearchElNum and SearchEl
+// for a particular type of dictionary (Block, WordBlock, or StemBlock)
+// and then look up the entry
+bool SearchBlockDictElNum (FILE *dictFile,
+			   const block_idx &bIdx,
+			   unsigned long entriesPerBlock,
+			   unsigned long dictSize,
+			   unsigned long elNum,
+			   block_dict_el &dictEl);
+bool SearchBlockDictEl (FILE *dictFile,
+			const block_idx &bIdx,
+			unsigned long entriesPerBlock,
+			unsigned long dictSize,
+			const UCArray &el,
+			block_dict_el &dictEl,
+			unsigned long &elNum);
+
+// assumes the numLevels has been set for dictEl
+bool SearchWordBlockDictElNum (FILE *dictFile,
+			       const block_idx &bIdx,
+			       unsigned long entriesPerBlock,
+			       unsigned long dictSize,
+			       unsigned long numLevels,
+			       unsigned long elNum,
+			       word_block_dict_el &dictEl);
+bool SearchWordBlockDictEl (FILE *dictFile,
+			    const block_idx &bIdx,
+			    unsigned long entriesPerBlock,
+			    unsigned long dictSize,
+			    unsigned long numLevels,
+			    const UCArray &el,
+			    word_block_dict_el &dictEl,
+			    unsigned long &elNum);
+
+bool SearchStemBlockDictElNum (FILE *dictFile,
+			       const block_idx &bIdx,
+			       unsigned long entriesPerBlock,
+			       unsigned long dictSize,
+			       unsigned long elNum,
+			       stem_block_dict_el &dictEl);
+bool SearchStemBlockDictEl (FILE *dictFile,
+			    const block_idx &bIdx,
+			    unsigned long entriesPerBlock,
+			    unsigned long dictSize,
+			    const UCArray &el,
+			    stem_block_dict_el &dictEl,
+			    unsigned long &elNum);
+
+//-----------------------------------------------------
+// New functions for partial matching
+// returns a list of word numbers from the main block index whose
+// words start with el.
+bool PartialMatchSearchWordBlockDictEl (FILE *dictFile,
+				 const block_idx &bIdx,
+				 unsigned long entriesPerBlock,
+				 unsigned long dictSize,
+				 unsigned long numLevels,
+				 const UCArray &el,
+				 word_block_dict_el &dictEl,
+				 vector<unsigned long> &elNumList,
+				 bool casefold); 
+//----------------------------------------------------------
+
+// new functions for full text browse
+
+bool NearestSearchWordBlockDictEl (FILE *dictFile,
+			    const block_idx &bIdx,
+			    unsigned long entriesPerBlock,
+			    unsigned long dictSize,
+			    unsigned long numLevels,
+			    const UCArray &el,
+			    word_block_dict_el &dictEl,
+			    unsigned long &elNum);
+
+// returns a list of word_block_dict_el, with no levelfreqs
+bool SearchWordBlockDictElNumRange (FILE *dictFile,
+				    const block_idx &bIdx,
+				    unsigned long entriesPerBlock,
+				    unsigned long dictSize,
+				    unsigned long numLevels,
+				    unsigned long elNum,
+				    unsigned long numWords,
+				    word_block_dict_el_array &terms);
+				    
+// just returns a list of terms
+bool SearchWordBlockDictElNumRange (FILE *dictFile,
+				    const block_idx &bIdx,
+				    unsigned long entriesPerBlock,
+				    unsigned long dictSize,
+				    unsigned long numLevels,
+				    unsigned long elNum,
+				    unsigned long numWords,
+				    UCArrayVector &terms);
+				    
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/ivf.pass1.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/ivf.pass1.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/ivf.pass1.cpp	(revision 14757)
@@ -0,0 +1,775 @@
+/**************************************************************************
+ *
+ * ivf.pass1.cpp -- Memory efficient pass 1 inversion
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "UCArray.h"
+#include "sysfuncs.h"
+#include "mg_files.h"
+#include "invf.h"
+#include "mg.h"
+#include "build.h"
+#include "locallib.h"
+#include "bitio_m_stdio.h"
+#include "bitio_gen.h"
+#include <stdio.h>
+#include "words.h"
+#include "messages.h"
+#include "netorder.h"
+#include "FIvfLevelInfo.h"
+
+#include "longlong.h"
+
+#if defined(GSDL_USE_OBJECTSPACE)
+#  include <ospace\std\map>
+#elif defined(GSDL_USE_STL_H)
+#  include <map.h>
+#else
+#  include <map>
+#endif
+
+// a fragment corresponds to the index level (word-level is the
+// minimum index level)
+
+
+// structure to determine level information
+struct LevelWorker {
+  unsigned long lastLevelDocNum;
+  unsigned long count;
+
+  LevelWorker () {
+    lastLevelDocNum = count = 0;
+  }
+};
+
+
+// note: the word is stored in the map
+struct IvfWordInfo {
+  unsigned long wordCount;      // word frequency
+  unsigned long fragCount;      // number of fragments that contain the word
+  unsigned long lastFragNum;    // last fragment to contain the word
+  unsigned long chunkWordCount; // word frequency within this chunk
+  unsigned long chunkFragCount; // number of fragments within this chunk that
+                                //   contain the word
+
+  LevelWorker *levels;          // level info for this word
+  
+  IvfWordInfo ();
+  ~IvfWordInfo ();
+  void Clear ();                // will delete levels
+};
+
+typedef map<UCArray, IvfWordInfo, DictLTUCArray> IvfWordInfoMap;
+typedef vector<IvfWordInfoMap::iterator> IvfWordInfoItArray;
+
+// tags don't require as much information
+struct IvfTagInfo {
+  unsigned long tagCount;       // tag frequency
+  unsigned long fragCount;      // number of fragments that contain the tag
+  unsigned long lastFragNum;    // last fragment to contain the tag
+  unsigned long chunkFragCount; // number of fragments within this chunk that
+                                //   contain the tag
+
+  IvfTagInfo ();
+  void Clear ();
+};
+
+typedef map<UCArray, IvfTagInfo, DictLTUCArray> IvfTagInfoMap;
+typedef vector<IvfTagInfoMap::iterator> IvfTagInfoItArray;
+
+
+#define INIT_CHECK_FRAC 0.10
+#define CHECK_FRAC 0.75
+#define CHECK_CLOSE 0.999
+#define CHECK_DIV 1.5
+
+
+static FILE *ic;		// the invf chunk file
+static stdio_bitio_buffer icb;
+
+IvfWordInfoMap ivfWordInfo;
+IvfWordInfoItArray ivfWordInfoOccurOrder;
+IvfTagInfoMap ivfTagInfo;
+IvfTagInfoItArray ivfTagInfoOccurOrder;
+
+static unsigned long chunksWritten;
+static unsigned long maxMemNeeded;
+
+static unsigned long numDocs;
+static unsigned long numChunkDocs;
+
+static unsigned long numFrags;
+static unsigned long numChunkFrags;
+
+static unsigned long numWords;
+
+// the number of document numbers in the inverted file
+static unsigned long numChunkEntries;
+
+// next entry in the inverted file to check memory
+// requirements for the current chunk
+static unsigned long entryCheckPoint;
+
+// information about all the different levels
+static FIvfLevel ivfLevel;
+
+
+
+IvfWordInfo::IvfWordInfo () {
+  levels = NULL;
+  Clear();
+}
+
+IvfWordInfo::~IvfWordInfo () {
+  if (levels != NULL) delete [] levels;
+}
+
+void IvfWordInfo::Clear () {
+  wordCount = 0;
+  chunkWordCount = 0;
+  lastFragNum = 0;
+  fragCount = 0;
+  chunkFragCount = 0;
+
+  if (levels != NULL) {
+    delete [] levels;
+    levels = NULL;
+  }
+}
+
+
+IvfTagInfo::IvfTagInfo () {
+  Clear();
+}
+
+void IvfTagInfo::Clear () {
+  tagCount = 0;
+  lastFragNum = 0;
+  fragCount = 0;
+  chunkFragCount = 0;
+}
+
+
+
+int init_ivf_1 (const TagInfo &tagInfo, char *file_name) {
+  // set up the chunk file
+  if (!(ic = create_file (file_name, INVF_CHUNK_SUFFIX, "wb",
+			  MAGIC_CHUNK, MG_MESSAGE)))
+    return COMPERROR;
+  fwrite ("    ", sizeof (u_long), 1, ic);	// Space for the maxmem
+  icb.attachFile (ic);
+  icb.encodeStart();
+
+  // reset global variables
+  ivfWordInfo.erase (ivfWordInfo.begin(), ivfWordInfo.end());
+  ivfWordInfoOccurOrder.erase (ivfWordInfoOccurOrder.begin(), ivfWordInfoOccurOrder.end());
+  ivfTagInfo.erase (ivfTagInfo.begin(), ivfTagInfo.end());
+  ivfTagInfoOccurOrder.erase (ivfTagInfoOccurOrder.begin(), ivfTagInfoOccurOrder.end());
+  
+  chunksWritten = 0;
+  maxMemNeeded = 0;
+ 
+  numDocs = 0;
+  numChunkDocs = 0;
+
+  numFrags = 0;
+  numChunkFrags = 0;
+
+  numWords = 0;
+
+  numChunkEntries = 0;
+  entryCheckPoint = (unsigned long) ((invf_buffer_size * INIT_CHECK_FRAC) / CHECK_DIV);
+
+  // init the level information
+  ivfLevel.Clear();
+  ivfLevel.docTag = tagInfo.docTag;
+  ivfLevel.indexLevel = tagInfo.indexLevel;
+  IvfLevelInfo blankLevel;
+  UCArraySet::const_iterator levelHere = tagInfo.levelTags.begin();
+  UCArraySet::const_iterator levelEnd = tagInfo.levelTags.end();
+  while (levelHere != levelEnd) {
+    blankLevel.levelTag = *levelHere;
+    ivfLevel.levelInfo[*levelHere] = blankLevel;
+    ++levelHere;
+  }
+  
+  return COMPALLOK;
+}
+
+static void ProcessOpenTag (const TagInfo &tagInfo, const TextEl &el,
+			    bool &inFrag) {
+  bool wordLevelIndex = tagInfo.indexLevel.empty();
+
+  // check for start of next fragment
+  if (!wordLevelIndex && el.tagName == tagInfo.indexLevel) {
+    ++numFrags;
+    ++numChunkFrags;
+    inFrag = true;
+  }
+  
+  // update tag stats
+  IvfTagInfo &i = ivfTagInfo[el.tagName];
+  if (i.tagCount == 0) {
+    // new tag, add to list of iterators
+    IvfTagInfoMap::iterator iIt = ivfTagInfo.find (el.tagName);
+    ivfTagInfoOccurOrder.push_back (iIt);
+  }
+  ++i.tagCount;
+
+  // all open tags count as new tags
+  ++numChunkEntries;
+  ++i.fragCount;
+  ++i.chunkFragCount;
+  i.lastFragNum = numFrags;
+  
+  // update level information
+  IvfLevelInfoMap::iterator levelIt = ivfLevel.levelInfo.find (el.tagName);
+  if (levelIt != ivfLevel.levelInfo.end()) {
+    // is a level tag
+    ++levelIt->second.numEntries;
+    levelIt->second.workInLevel = true;
+  }
+}
+
+static void ProcessCloseTag (const TagInfo &tagInfo, const TextEl &el,
+			     bool &inFrag) {
+  bool wordLevelIndex = tagInfo.indexLevel.empty();
+
+  // check for end of fragment
+  if (!wordLevelIndex && el.tagName == tagInfo.indexLevel) {
+    inFrag = false;
+  }
+
+  // update level information
+  IvfLevelInfoMap::iterator levelIt = ivfLevel.levelInfo.find (el.tagName);
+  if (levelIt != ivfLevel.levelInfo.end()) {
+    // is a level tag
+    (*levelIt).second.workInLevel = false;
+  }
+}
+
+static void ProcessText (const TagInfo &tagInfo, const TextEl &el,
+			 bool &inFrag) {
+  bool wordLevelIndex = tagInfo.indexLevel.empty();
+
+  // make sure this text is to be indexed
+  if (!wordLevelIndex && !inFrag) return;
+
+  const unsigned char *textHere = &(el.text[0]);
+  const unsigned char *textEnd = &(el.text[el.text.size() - 1]);
+  UCArray word;
+  
+  if (!inaword_mgpp (textHere, textEnd))
+    ParseNonindexWord (textHere, textEnd);
+
+  
+  // Alternately parse off words and non-words from the input
+  // Each token is then inserted into the set if it does
+  // not exist or has it's frequency count incremented if it does.
+
+  while (textHere <= textEnd) {
+    textHere = ParseIndexWord (textHere, textEnd, word);
+    textHere = ParseNonindexWord (textHere, textEnd);
+
+    if (!word.empty()) {
+      ++numWords;
+
+      if (wordLevelIndex) {
+	++numFrags;
+	++numChunkFrags;
+      }
+      
+      // update word stats
+
+      IvfWordInfo &i = ivfWordInfo[word];
+      if (i.wordCount == 0) {
+	// new word
+	// add to list of iterators
+	IvfWordInfoMap::iterator iIt = ivfWordInfo.find (word);
+	ivfWordInfoOccurOrder.push_back (iIt);
+
+	// add level information array
+	if (ivfLevel.levelInfo.size() > 0) 
+	  i.levels = new LevelWorker [ivfLevel.levelInfo.size()];
+      }
+
+      ++i.wordCount;
+      ++i.chunkWordCount;
+      if (numFrags > i.lastFragNum) {
+	++numChunkEntries;
+	++i.fragCount;
+	++i.chunkFragCount;
+	i.lastFragNum = numFrags;
+      }
+
+      // update level information for this word
+      if (i.levels != NULL) {
+	IvfLevelInfoMap::iterator levelHere = ivfLevel.levelInfo.begin();
+	IvfLevelInfoMap::iterator levelEnd = ivfLevel.levelInfo.end();
+	LevelWorker *levelWorkerPtr = i.levels;
+	while (levelHere != levelEnd) {
+
+	  // check to make sure the level encompases this fragment
+	  if (!(*levelHere).second.workInLevel) {
+	    cerr << "Level tag <" << (*levelHere).first
+		 << "> does not encompass all fragments\n";
+	    exit (1);
+	  }
+	  
+	  if ((*levelHere).second.numEntries > (*levelWorkerPtr).lastLevelDocNum) {
+	    (*levelWorkerPtr).lastLevelDocNum = (*levelHere).second.numEntries;
+	    ++levelWorkerPtr->count;
+	  }
+	  
+	  ++levelHere;
+	  ++levelWorkerPtr;
+	}
+      }
+    }
+  }
+}
+
+
+static unsigned long MemoryRequired (bool wordLevelIndex) {
+  register unsigned long total = 0;
+
+  // add memory required for word entries
+  IvfWordInfoMap::const_iterator wordHere = ivfWordInfo.begin();
+  IvfWordInfoMap::const_iterator wordEnd = ivfWordInfo.end();
+  while (wordHere != wordEnd) {
+    register const IvfWordInfo &info = (*wordHere).second;
+    if (info.chunkFragCount > 0) {
+      total += BIO_Bblock_Bound (numChunkFrags, info.chunkFragCount);
+      if (!wordLevelIndex) {
+	total += info.chunkWordCount;
+      }
+    }
+    
+    ++wordHere;
+  }
+
+  // add memory required for tag entries
+  IvfTagInfoMap::const_iterator tagHere = ivfTagInfo.begin();
+  IvfTagInfoMap::const_iterator tagEnd = ivfTagInfo.end();
+  while (tagHere != tagEnd) {
+    register const IvfTagInfo &info = (*tagHere).second;
+    if (info.chunkFragCount > 0) {
+      // two d entries for each frag entry
+      unsigned long pTag = info.chunkFragCount*2;
+      total += BIO_Bblock_Bound (numChunkFrags+pTag, pTag);
+    }
+    
+    ++tagHere;
+  }
+  
+  total = (total + 7) >> 3;
+  return total;
+}
+
+
+/*
+static void PrintChunkInfo (unsigned long mem) {
+  cout << "Chunk Number: " << chunksWritten << "\n";
+  cout << "numChunkDocs " << numChunkDocs << "\n";
+  cout << "numChunkFrags " << numChunkFrags << "\n";
+  cout << "mem " << mem << "\n";
+  cout << "numWords " << ivfWordInfo.size() << "\n";
+  cout << "numTags " << ivfTagInfo.size() << "\n\n";
+
+  // output debug tag information in dictionary order
+  IvfTagInfoMap::iterator tagMapHere = ivfTagInfo.begin();
+  IvfTagInfoMap::iterator tagMapEnd = ivfTagInfo.end();
+  unsigned long tagNum = 0;
+  while (tagMapHere != tagMapEnd) {
+    cout << (*tagMapHere).first << " " << tagNum
+	 << " " << (*tagMapHere).second.chunkFragCount << "\n";
+    ++tagNum;
+    ++tagMapHere;
+  }
+}
+*/
+
+static void OutputChunkInfo (unsigned long mem, bool /*wordLevelIndex*/) {
+  ++chunksWritten;
+
+  // sanity check
+  if (ivfWordInfo.size() != ivfWordInfoOccurOrder.size()) {
+    Message ("ERROR: Word information size mismatch: %u vs %u\n",
+	     (unsigned int)ivfWordInfo.size(),
+	     (unsigned int)ivfWordInfoOccurOrder.size());
+    exit (1);
+  }
+  if (ivfTagInfo.size() != ivfTagInfoOccurOrder.size()) {
+    Message ("ERROR: Tag information size mismatch: %u vs %u\n",
+	     (unsigned int)ivfTagInfo.size(),
+	     (unsigned int)ivfTagInfoOccurOrder.size());
+    exit (1);
+  }
+
+  icb.gamma_encode (numChunkDocs + 1, NULL);
+  icb.gamma_encode (numChunkFrags + 1, NULL);
+  icb.gamma_encode (mem + 1, NULL);
+  icb.gamma_encode (ivfWordInfo.size() + 1, NULL);
+  icb.gamma_encode (ivfTagInfo.size() + 1, NULL);
+
+  /*  PrintChunkInfo (mem);*/
+
+  // output word information in occurance order
+  IvfWordInfoItArray::iterator wordHere = ivfWordInfoOccurOrder.begin();
+  IvfWordInfoItArray::iterator wordEnd = ivfWordInfoOccurOrder.end();
+  while (wordHere != wordEnd) {
+    register IvfWordInfo &ivfWordInfo = (*(*wordHere)).second;
+    
+    icb.gamma_encode (ivfWordInfo.chunkWordCount + 1, NULL);
+    if (ivfWordInfo.chunkWordCount >= 2) {
+      icb.gamma_encode (ivfWordInfo.chunkFragCount, NULL);
+    }
+
+    ivfWordInfo.lastFragNum = 0;
+    ivfWordInfo.chunkWordCount = 0;
+    ivfWordInfo.chunkFragCount = 0;
+    
+    ++wordHere;
+  }
+
+  // output tag information in occurance order
+  IvfTagInfoItArray::iterator tagHere = ivfTagInfoOccurOrder.begin();
+  IvfTagInfoItArray::iterator tagEnd = ivfTagInfoOccurOrder.end();
+  while (tagHere != tagEnd) {
+    register IvfTagInfo &ivfTagInfo = (*(*tagHere)).second;
+
+    icb.gamma_encode (ivfTagInfo.chunkFragCount + 1, NULL);
+
+    ivfTagInfo.lastFragNum = 0;
+    ivfTagInfo.chunkFragCount = 0;
+    
+    ++tagHere;
+  }
+
+  numChunkDocs = 0;
+  numChunkFrags = 0;
+  numChunkEntries = 0;
+}
+
+
+int process_ivf_1 (const TagInfo &tagInfo, const TextElArray &doc) {
+  bool wordLevelIndex = tagInfo.indexLevel.empty();
+  bool inFrag = false;
+  if (wordLevelIndex) inFrag = true; // unconditional
+  
+  ++numDocs;
+  ++numChunkDocs;
+
+  // process each text element in this document
+  TextElArray::const_iterator here = doc.begin();
+  TextElArray::const_iterator end = doc.end();
+  while (here != end) {
+    if ((*here).elType == OpenTagE)
+      ProcessOpenTag (tagInfo, *here, inFrag);
+    else if ((*here).elType == CloseTagE)
+      ProcessCloseTag (tagInfo, *here, inFrag);
+    else if ((*here).elType == TextE)
+      ProcessText (tagInfo, *here, inFrag);
+    
+    ++here;
+  }
+
+  // check the amount of memory needed for this chunk
+  if (numChunkEntries >= entryCheckPoint) {
+    unsigned long mem = MemoryRequired (wordLevelIndex);
+    if (mem >= invf_buffer_size * CHECK_CLOSE) {
+      if (mem > maxMemNeeded) maxMemNeeded = mem;
+      OutputChunkInfo (mem, wordLevelIndex);
+      entryCheckPoint = (unsigned long)
+	((invf_buffer_size * INIT_CHECK_FRAC) / CHECK_DIV);
+      
+    } else {
+      entryCheckPoint = (unsigned long)
+	(entryCheckPoint * ((CHECK_FRAC * (invf_buffer_size - mem)) / mem) +
+	 entryCheckPoint);
+      if (entryCheckPoint <= numChunkEntries)
+	entryCheckPoint = numChunkEntries + 1;
+    }
+  }
+  
+  return COMPALLOK;
+}
+
+
+static void CalcInvfDictSize (unsigned long &totalBytes,
+			      unsigned long &indexStringBytes) {
+  totalBytes = 0;	// The sum of the length of all words, including 
+			// the length byte
+  indexStringBytes = 0; // The amount of space required to store the 
+			// words in the diction, this takes into account 
+			// the prefixes
+  const UCArray *lastWord = NULL;
+  
+  // calculate size of word information
+  IvfWordInfoMap::iterator wordHere = ivfWordInfo.begin();
+  IvfWordInfoMap::iterator wordEnd = ivfWordInfo.end();
+  while (wordHere != wordEnd) {
+    unsigned long wordSize = (*wordHere).first.size();
+    totalBytes += wordSize + 1;
+    indexStringBytes += wordSize + 2;
+    if (lastWord != NULL)
+      indexStringBytes -= PrefixLen (*lastWord, (*wordHere).first);
+    lastWord = &((*wordHere).first);
+    
+    ++wordHere;
+  }
+
+  // calculate size of tag information
+  lastWord = NULL;
+  IvfTagInfoMap::iterator tagHere = ivfTagInfo.begin();
+  IvfTagInfoMap::iterator tagEnd = ivfTagInfo.end();
+  while (tagHere != tagEnd) {
+    unsigned long tagSize = (*tagHere).first.size();
+    totalBytes += tagSize + 1;
+    indexStringBytes += tagSize + 2;
+    if (lastWord != NULL)
+      indexStringBytes -= PrefixLen (*lastWord, (*tagHere).first);
+    lastWord = &((*tagHere).first);
+    
+    ++tagHere;
+  }
+}
+
+
+//      OutputInvfDict ():
+//                writes out the stemmed dictionary file
+//                in the following format 
+//                        lookback value (int)
+//                        totalbytes value (int)
+//                        indexstringbytes (int)
+//                        for each word 
+//                          wordlen (4 bits)
+//                          prefix match (4 bits)
+//                          word (wordlen bytes)
+//                          word frequency (int)
+//                          word count (int)
+//
+//        Accesses outside variables:     
+//
+//        Return value...:                
+static void OutputInvfDict (char *filename) {
+  // create the dictionary header
+  invf_dict_header idh;
+  idh.word_dict_size = ivfWordInfo.size();
+  idh.tag_dict_size = ivfTagInfo.size();
+  idh.num_docs = numDocs;
+  idh.num_frags = numFrags;
+  idh.num_words = numWords;
+  idh.num_levels = ivfLevel.levelInfo.size();
+  CalcInvfDictSize (idh.total_bytes, idh.index_string_bytes);
+
+  // create the inverted dictionary file
+  FILE *sp;
+  if (!(sp = create_file (filename, INVF_DICT_SUFFIX, "wb", MAGIC_STEM_BUILD,
+			  MG_MESSAGE)))
+    return;
+
+  // write out the dictionary header
+  if (!idh.Write (sp)) { fclose (sp); return; }
+
+  // remember where the word dictionary starts
+  idh.word_dict_start = ftell (sp);
+  
+  // output the word dictionary
+  const UCArray *lastWord = NULL;
+  IvfWordInfoMap::iterator wordHere = ivfWordInfo.begin();
+  IvfWordInfoMap::iterator wordEnd = ivfWordInfo.end();
+  while (wordHere != wordEnd) {
+    // get the prefix and suffix lengths
+    const UCArray &thisWord = (*wordHere).first;
+    WritePreSufStr (sp, lastWord, thisWord);
+
+    // output the number of fragments the word appeared in and the
+    // number of times the word appeared
+    WriteUL (sp, (*wordHere).second.fragCount);
+    WriteUL (sp, (*wordHere).second.wordCount);
+
+    // output frequency information for each level
+    // note that we are expecting every word to have
+    // level information
+    LevelWorker *lwHere = (*wordHere).second.levels;
+    LevelWorker *lwEnd = lwHere + idh.num_levels;
+    while (lwHere != lwEnd) {
+      WriteUL (sp, (*lwHere).count);
+      ++lwHere;
+    }
+    
+    lastWord = &thisWord;
+    ++wordHere;
+  }
+
+  // remember where the tag dictionary starts
+  idh.tag_dict_start = ftell (sp);
+  
+  // output the tag dictionary
+  const UCArray *lastTag = NULL;
+  IvfTagInfoMap::iterator tagHere = ivfTagInfo.begin();
+  IvfTagInfoMap::iterator tagEnd = ivfTagInfo.end();
+  while (tagHere != tagEnd) {
+    // get the prefix and suffix lengths
+    const UCArray &thisTag = (*tagHere).first;
+    WritePreSufStr (sp, lastTag, thisTag);
+
+    // output the number of fragments the tag appeared in and the
+    // number of times the tag appeared
+    WriteUL (sp, (*tagHere).second.fragCount);
+    WriteUL (sp, (*tagHere).second.tagCount);
+    
+    lastTag = &thisTag;
+    ++tagHere;
+  }
+
+  // write out the updated header
+  fseek (sp, sizeof (u_long), SEEK_SET);
+  if (!idh.Write (sp)) { fclose (sp); return; }
+  
+  fclose (sp);
+}
+
+static void OutputLevelFile (char *filename) {
+  // create the level file
+  FILE *f;
+  if (!(f = create_file (filename, INVF_LEVEL_SUFFIX, "wb", MAGIC_INVF_LEVELS,
+			 MG_MESSAGE)))
+    return;
+
+  // write out the information
+  ivfLevel.Write (f);
+  
+  // close the file
+  fclose (f);
+}
+
+static void OutputTransFile (char *filename) {
+  // save the word number (in lastFragNum :-/)
+  int i = 0;
+  IvfWordInfoMap::iterator wordHere = ivfWordInfo.begin();
+  IvfWordInfoMap::iterator wordEnd = ivfWordInfo.end();
+  while (wordHere != wordEnd) {
+    (*wordHere).second.lastFragNum = i;
+    ++i; ++wordHere;
+  }
+
+  // save the tag number (in lastFragNum :-/)
+  i = 0;
+  IvfTagInfoMap::iterator tagHere = ivfTagInfo.begin();
+  IvfTagInfoMap::iterator tagEnd = ivfTagInfo.end();
+  while (tagHere != tagEnd) {
+    (*tagHere).second.lastFragNum = i;
+    ++i; ++tagHere;
+  }
+  
+  // create the translation file
+  FILE *f;
+  if (!(f = create_file (filename, INVF_CHUNK_TRANS_SUFFIX, "wb",
+			 MAGIC_CHUNK_TRANS, MG_MESSAGE)))
+    return;
+
+  stdio_bitio_buffer buffer(f);
+  buffer.encodeStart();
+
+  // write out the word translation table
+  unsigned long wordDictSize = ivfWordInfoOccurOrder.size();
+  IvfWordInfoItArray::iterator wordItHere = ivfWordInfoOccurOrder.begin();
+  IvfWordInfoItArray::iterator wordItEnd = ivfWordInfoOccurOrder.end();
+  unsigned long oN = 0;
+  while (wordItHere != wordItEnd) {
+    register IvfWordInfo &ivfWordInfo = (*(*wordItHere)).second;
+    buffer.binary_encode (ivfWordInfo.lastFragNum + 1, wordDictSize + 1, NULL);
+    ++oN;
+    ++wordItHere;
+  }
+
+  // write out the tag translation table
+  unsigned long tagDictSize = ivfTagInfoOccurOrder.size();
+  IvfTagInfoItArray::iterator tagItHere = ivfTagInfoOccurOrder.begin();
+  IvfTagInfoItArray::iterator tagItEnd = ivfTagInfoOccurOrder.end();
+  while (tagItHere != tagItEnd) {
+    register IvfTagInfo &ivfTagInfo = (*(*tagItHere)).second;
+    buffer.binary_encode (ivfTagInfo.lastFragNum + 1, tagDictSize + 1, NULL);
+    ++oN;
+    ++tagItHere;
+  }
+
+  // finish encoding and close the file
+  buffer.encodeDone();
+  fclose (f);
+}
+
+#ifndef SILENT
+static void PrintStats () {
+  Message ("Inverted buffer size:          %8u bytes\n", invf_buffer_size);
+  Message ("Max memory needed for 1 chunk: %8u bytes\n", maxMemNeeded);
+
+  Message ("Number of chunks written:      %8u\n", chunksWritten);
+  Message ("Number of documents:           %8u\n", numDocs);
+  Message ("Number of fragments:           %8u\n", numFrags);
+  Message ("Number of words:               %8u\n", numWords);
+
+  Message ("Size of word dictionary:       %8u\n", ivfWordInfo.size());
+  Message ("Size of tag dictionary:        %8u\n", ivfTagInfo.size());
+}
+#endif
+
+int done_ivf_1 (const TagInfo &tagInfo, char * filename) {
+  bool wordLevelIndex = tagInfo.indexLevel.empty();
+
+  char *temp_str = msg_prefix;
+  msg_prefix = "ivf.pass1";
+
+  // output the last chunk
+  if (numChunkDocs > 0) {
+    unsigned long mem = MemoryRequired (wordLevelIndex);
+    OutputChunkInfo (mem, wordLevelIndex);
+    if (mem > maxMemNeeded) maxMemNeeded = mem;
+  }
+  
+  // write out and encoded 1 to say there are no more chunks
+  icb.gamma_encode (1, NULL);
+  icb.encodeDone ();
+
+  // write out the maximum memory required and close the file
+  fseek (ic, sizeof (long), 0);
+  WriteUL (ic, maxMemNeeded);
+  fclose (ic);
+
+  // output the inverted dictionary
+  OutputInvfDict (filename);
+
+  // write out the translation file
+  OutputTransFile (filename);
+
+  // output the level information
+  OutputLevelFile (filename);
+  
+  // output statistics
+#ifndef SILENT
+  PrintStats ();
+#endif
+  
+  msg_prefix = temp_str;
+
+  return COMPALLOK;
+}
+
Index: /indexers/branches/3.03a/mgpp/text/ivf.pass2.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/ivf.pass2.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/ivf.pass2.cpp	(revision 14757)
@@ -0,0 +1,1111 @@
+/**************************************************************************
+ *
+ * ivf.pass2.cpp -- Memory efficient pass 2 inversion
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+#include <stdio.h>
+
+#if defined __WIN32__
+# include <process.h>
+# include <io.h>
+# define getpid _getpid
+# define unlink _unlink
+#else
+# include <unistd.h>
+# include "non_ansi.h"
+#endif
+
+#include "UCArray.h"
+#include "sysfuncs.h"
+#include "mg_files.h"
+#include "invf.h"
+#include "mg.h"
+#include "build.h"
+#include "locallib.h"
+#include "bitio_m_random.h"
+#include "bitio_m_stdio.h"
+#include "bitio_m_mems.h"
+#include "bitio_gen.h"
+#include <stdio.h>
+#include "words.h"
+#include "messages.h"
+#include "netorder.h"
+#include "FIvfLevelInfo.h"
+#include "perf_hash.h"
+#include "string.h"
+
+#include "longlong.h"
+
+#if defined(GSDL_USE_OBJECTSPACE)
+#  include <ospace\std\map>
+#elif defined(GSDL_USE_STL_H)
+#  include <map.h>
+#else
+#  include <map>
+#endif
+
+
+#ifdef USE_LONG_LONG
+#define SEEK_X seek_LL
+#define TELL_X tell_LL
+#else
+#define SEEK_X seek
+#define TELL_X tell
+#endif
+
+#ifndef RND_BUF_SIZE
+#define RND_BUF_SIZE 8*1024
+#endif
+
+
+static unsigned long numDocs = 0;
+static unsigned long numChunkDocs = 0;
+static unsigned long numDocsInChunk = 0;
+
+static unsigned long numFrags = 0;
+static unsigned long numFragsInChunk = 0;
+static unsigned long chunkStartFragNum = 0;
+
+
+
+
+struct BitPtr {
+  unsigned long start;
+  unsigned long here;
+  unsigned long lastFragNum;
+  unsigned long lgB;
+  
+  void Clear () { start = here = lastFragNum = lgB = 0; }
+  BitPtr () { Clear(); }
+};
+
+class WordBitPtrs {
+protected:
+  unsigned long numWords;
+  unsigned long numTags;
+  unsigned long size;
+  BitPtr *wordBitPtrs;
+
+  void CheckBufOverrun (unsigned long num) {
+    if (wordBitPtrs[num].here > wordBitPtrs[num+1].start) {
+      cerr << "numDocs: " << numDocs << "\n";
+      cerr << "numChunkDocs: " << numChunkDocs << "\n";
+      cerr << "numDocsInChunk: " << numDocsInChunk << "\n";
+      cerr << "numFrags: " << numFrags << "\n";
+      cerr << "numFragsInChunk: " << numFragsInChunk << "\n";
+      cerr << "chunkStartFragNum: " << chunkStartFragNum << "\n";
+      cerr << "num: " << num << "\n";
+      cerr << "[num].start: " << wordBitPtrs[num].start << "\n";
+      cerr << "[num].here: " << wordBitPtrs[num].here << "\n";
+      cerr << "[num+1].start: " << wordBitPtrs[num+1].start << "\n";
+      FatalError (1, "Bit buffer overrun");
+    }
+  }
+  
+public:
+  void Clear ();
+  WordBitPtrs () { wordBitPtrs = NULL; Clear(); }
+  ~WordBitPtrs ();
+  void SetSize (unsigned long _numWords,
+		unsigned long _numTags);
+
+  void ResetPtrs () {
+    if (wordBitPtrs == NULL) return;
+    unsigned long i;
+    for (i=0; i<size; ++i) wordBitPtrs[i].Clear();
+  }
+  
+  BitPtr &GetWordBitPtr (unsigned long wordNum)
+    { return wordBitPtrs[wordNum]; }
+  unsigned long &GetWordStart (unsigned long wordNum)
+    { return wordBitPtrs[wordNum].start; }
+  unsigned long &GetWordHere (unsigned long wordNum)
+    { return wordBitPtrs[wordNum].here; }
+  void CheckWordBufOverrun (unsigned long wordNum)
+    { CheckBufOverrun (wordNum); }
+
+  BitPtr &GetTagBitPtr (unsigned long tagNum)
+    { return wordBitPtrs[tagNum + numWords]; }
+  unsigned long &GetTagStart (unsigned long tagNum)
+    { return wordBitPtrs[tagNum + numWords].start; }
+  unsigned long &GetTagHere (unsigned long tagNum)
+    { return wordBitPtrs[tagNum + numWords].here; }
+  void CheckTagBufOverrun (unsigned long tagNum)
+    { CheckBufOverrun (tagNum + numWords); }
+
+  BitPtr &GetEndBitPtr ()
+    { return wordBitPtrs[size-1]; }
+  unsigned long &GetEndStart ()
+    { return wordBitPtrs[size-1].start; }
+  unsigned long &GetEndHere ()
+    { return wordBitPtrs[size-1].here; }
+};
+
+
+struct IP2TagInfo {
+  bool inTag;
+  unsigned long startFrag;
+  unsigned long tagNum;
+
+  IP2TagInfo () {
+    inTag = false;
+    startFrag = 0;
+    tagNum = 0;
+  }
+};
+
+// maps tags to tag information
+typedef map<UCArray, IP2TagInfo, DictLTUCArray> TagMapDict;
+
+
+// class to handle the translation of occurrence order
+// to dictionary order for words and tags
+class OccurToDictConverter {
+protected:
+  unsigned long pos;
+  unsigned long val;
+  FILE *transFile;
+  random_bitio_buffer rbs;
+
+  unsigned long wordDictSize;
+  unsigned long tagDictSize;
+
+  void SeekStart ();
+  unsigned long TranslateNum (unsigned long num);
+  
+public:
+  OccurToDictConverter ();
+  ~OccurToDictConverter ();
+
+  void Open (char *filename, unsigned long _wordDictSize,
+	     unsigned long _tagDictSize);
+
+  // Close frees all allocated memory
+  void Close ();
+
+  unsigned long TranslateWord (unsigned long occurNum)
+    { return TranslateNum (occurNum); }
+  unsigned long TranslateTag (unsigned long occurNum)
+    { return TranslateNum (occurNum+wordDictSize); }
+};
+
+
+struct InvfStateRec {
+  mg_ullong start;
+  mg_ullong here;
+  unsigned long lastFragNum;
+  unsigned long B;
+
+  void Clear () {
+    start = here = 0;
+    lastFragNum = B = 0;
+  }
+  InvfStateRec () { Clear (); }
+};
+
+
+#define ISR_SIZE 1024
+
+class InvfStateCache {
+protected:
+  InvfStateRec recCache [ISR_SIZE];
+  unsigned long startNum;
+
+  FILE *stateFile;
+
+  void ClearCache () {
+    unsigned int i = 0;
+    for (i=0; i<ISR_SIZE; ++i) recCache[i].Clear();
+  }
+  
+public:
+  InvfStateCache ();
+  ~InvfStateCache ();
+  
+  void Open (char *filename);
+  void Close ();
+
+  // previous references to state records may be
+  // invalidated calling GetRec
+  InvfStateRec &GetRec (unsigned long num);
+};
+
+
+static invf_dict_header idh;
+static WordBitPtrs bitPtrs;
+
+static FILE *chunkFile = NULL;
+static stdio_bitio_buffer chunkBuf;
+
+static unsigned long ivfMemBufSize = 0;
+static char *ivfMemBuf = NULL;
+
+// word and tag dictionaries. a map is used for the tag dictionary
+// as it should never be very big (and the perfect hash function
+// sometimes has trouble with small values).
+static perf_hash_data *wordHashDict = NULL;
+static TagMapDict tagMapDict;
+
+// information about all the different levels
+static FIvfLevel ivfLevel;
+
+static OccurToDictConverter occurConvert;
+
+// information about the state of the inverted file
+static InvfStateCache invfState;
+
+static char collectFilename[512];
+
+
+void WordBitPtrs::Clear () {
+  numWords = 0;
+  numTags = 0;
+  size=0;
+  if (wordBitPtrs != NULL) delete [] wordBitPtrs;
+  wordBitPtrs = NULL;
+}
+
+WordBitPtrs::~WordBitPtrs () {
+  if (wordBitPtrs != NULL) delete [] wordBitPtrs;
+}
+
+void WordBitPtrs::SetSize (unsigned long _numWords,
+			   unsigned long _numTags){
+  Clear();
+  numWords = _numWords;
+  numTags = _numTags;
+  size = numWords + numTags + 1;
+  wordBitPtrs = new BitPtr [size];
+}
+
+
+void OccurToDictConverter::SeekStart () {
+  if (transFile == NULL) return;
+  rbs.SEEK_X (sizeof (unsigned long) * 8);
+  pos = 0;
+}
+
+unsigned long OccurToDictConverter::TranslateNum (unsigned long num) {
+  if (num < pos) SeekStart ();
+  while (pos <= num) {
+    if (pos < wordDictSize)
+      val = rbs.binary_decode (wordDictSize + 1, NULL) - 1;
+    else 
+      val = rbs.binary_decode (tagDictSize + 1, NULL) - 1;
+    ++pos;
+  }
+  return val;
+}
+
+OccurToDictConverter::OccurToDictConverter () {
+  pos = 0;
+  val = 0;
+  transFile = NULL;
+  wordDictSize = 0;
+  tagDictSize = 0;
+}
+
+OccurToDictConverter::~OccurToDictConverter () {
+  if (transFile != NULL) Close ();
+}
+
+void OccurToDictConverter::Open (char *filename, unsigned long _wordDictSize,
+				 unsigned long _tagDictSize) {
+  if (transFile != NULL) Close ();
+
+  wordDictSize = _wordDictSize;
+  tagDictSize = _tagDictSize;
+
+  transFile = open_file (filename, INVF_CHUNK_TRANS_SUFFIX, "rb",
+			 MAGIC_CHUNK_TRANS, MG_ABORT);
+  rbs.attachFile (transFile, RND_BUF_SIZE);
+  SeekStart ();
+  val = 0;
+}
+
+void OccurToDictConverter::Close () {
+  if (transFile == NULL) return;
+
+  rbs.done ();
+  fclose (transFile);
+  transFile = NULL;
+  pos = 0;
+  val = 0;
+
+  wordDictSize = 0;
+  tagDictSize = 0;
+}
+
+
+
+
+InvfStateCache::InvfStateCache () {
+  startNum = 0;
+  stateFile = NULL;
+}
+
+InvfStateCache::~InvfStateCache () {
+  if (stateFile != NULL) Close ();
+}
+  
+void InvfStateCache::Open (char *filename) {
+  if (stateFile != NULL) Close();
+
+  // open the state file
+  char path[512];
+  sprintf (path, FILE_NAME_FORMAT ".%ld", get_basepath (), filename,
+           ".invf.state", (long) getpid ());
+  if (!(stateFile = fopen (path, "wb+"))) {
+    Message ("Unable to create \"%s\"", path);
+    exit (1);
+  }
+  unlink (path); // file will be deleted after it is closed
+  // reset the buffer
+  startNum = 0;
+  ClearCache();
+}
+
+void InvfStateCache::Close () {
+  if (stateFile == NULL) return;
+  fclose (stateFile);
+  stateFile = NULL;
+  startNum = 0;
+}
+
+InvfStateRec &InvfStateCache::GetRec (unsigned long num) {
+  // see if cached
+  if ((num >= startNum) && (num < startNum + ISR_SIZE))
+    return recCache[num-startNum];
+
+  // not cached, write out this lot of records and read in
+  fseek (stateFile, startNum*sizeof (InvfStateRec), SEEK_SET);
+  fwrite ((char *) recCache, sizeof (InvfStateRec), ISR_SIZE, stateFile);
+
+  // read in the new set of records
+  ClearCache ();
+  startNum = num - (num % ISR_SIZE);
+  fseek (stateFile, startNum*sizeof (InvfStateRec), SEEK_SET);
+  fread ((char *) recCache, sizeof (InvfStateRec), ISR_SIZE, stateFile);
+
+  return recCache[num-startNum];
+}
+
+
+
+static void ClearCharBuf (char *buf, unsigned long size) {
+  char *end = buf + size;
+  while (buf != end) *buf++ = 0;
+}
+
+static void ReadWordDict (char *filename) {
+  // read in the perfect hash function for the word dictionary
+  FILE *wordHashFile = open_file (filename, INVF_DICT_HASH_SUFFIX, "rb",
+				  MAGIC_HASH, MG_ABORT);
+  if (!(wordHashDict = read_perf_hash_data (wordHashFile))) {
+    FatalError (1, "Unable to read in hash data for word dictionary");
+  }
+  fclose (wordHashFile);
+}
+
+static void ReadTagDict (char *filename, invf_dict_header &_idh) {
+  // open the file
+  FILE *dictFile = open_file (filename, INVF_DICT_SUFFIX, "rb",
+			      MAGIC_STEM_BUILD, MG_ABORT);
+
+  // seek to the start of the tag dictionary
+  fseek (dictFile, _idh.tag_dict_start, SEEK_SET);
+  
+  unsigned long tagNum;
+  dict_el thisEl;
+  for (tagNum = 0; tagNum < _idh.tag_dict_size; ++tagNum) {
+    thisEl.Read (dictFile);
+    tagMapDict[thisEl.el].tagNum = tagNum;
+  }
+  
+  fclose (dictFile);
+}
+
+static void ReadLevelFile (char *filename) {
+  FILE *f;
+  f = open_file (filename, INVF_LEVEL_SUFFIX, "rb",
+		 MAGIC_INVF_LEVELS, MG_ABORT);
+  ivfLevel.Read (f);
+  fclose (f);
+}
+
+void CheckIntOverflow (mg_ullong totalIBits, mg_ullong lastTotalIBits) {
+  if (totalIBits < lastTotalIBits) {
+    fprintf(stderr, "ERROR: The totalIBits counter (%d byte unsigned integer) has overflowed.\n", sizeof (mg_ullong));
+    if (sizeof (mg_ullong) < 8) {
+      fprintf(stderr, "       Try compiling with GCC to enable use of 8 bytes for this counter.\n");
+    }
+    fprintf(stderr, "       Build aborted.\n");
+    exit(1);
+  }
+}
+
+// assumes the inverted file state file has been opened
+static void InitInvfState (char *filename,
+			   invf_dict_header &_idh,
+			   InvfStateCache &_invfState,
+			   mg_ullong &totalIBits,
+			   bool wordLevelIndex) {
+  // read in the dictionary, setting inverted state information
+  FILE *dictFile = open_file (filename, INVF_DICT_SUFFIX, "rb",
+			      MAGIC_STEM_BUILD, MG_ABORT);
+
+  // seek to the start of the word dictionary
+  fseek (dictFile, _idh.word_dict_start, SEEK_SET);
+
+  // add the word entries
+  word_dict_el wordEl;
+  wordEl.SetNumLevels (_idh.num_levels);
+  unsigned long dictWordNum, p;
+  mg_ullong lastTotalIBits;
+  unsigned long N = _idh.num_frags;
+  for (dictWordNum=0; dictWordNum<_idh.word_dict_size; ++dictWordNum) {
+    // lastTotalIBits is used to detect integer overflow
+    lastTotalIBits = totalIBits;
+
+    // read the next word and associated information
+    wordEl.Read (dictFile, _idh.num_levels);
+
+    // update the state record
+    p = wordEl.frag_occur;
+    InvfStateRec &wisr = _invfState.GetRec (dictWordNum);
+    wisr.start = totalIBits;
+    wisr.here = totalIBits;
+    wisr.B = BIO_Bblock_Init (N, p);
+    
+    // add the length of the fragment numbers
+    totalIBits += BIO_Bblock_Bound_b (N, p, wisr.B);
+
+    // if needed, add the length of the fragment frequency information
+    if (!wordLevelIndex)
+      totalIBits += BIO_Gamma_Bound (wordEl.freq, wordEl.frag_occur);
+
+    // align next byte
+#ifdef USE_LONG_LONG
+    totalIBits = (totalIBits + 7ull) & 0xfffffffffffffff8ull;
+#else
+    totalIBits = (totalIBits + 7ul) & 0xfffffff8ul;
+#endif
+
+    CheckIntOverflow (totalIBits, lastTotalIBits);
+  }
+
+  
+  // seek to the start of the tag dictionary
+  fseek (dictFile, _idh.tag_dict_start, SEEK_SET);
+
+  // add the tag entries
+  dict_el tagEl;
+  unsigned long dictTagNum;
+  N = _idh.num_frags;
+  for (dictTagNum=0; dictTagNum<_idh.tag_dict_size; ++dictTagNum) {
+    // lastTotalIBits is used to detect integer overflow
+    lastTotalIBits = totalIBits;
+
+    // read the next tag and associated information
+    tagEl.Read (dictFile);
+
+    // update the state record
+    p = tagEl.frag_occur*2;
+    InvfStateRec &tisr = _invfState.GetRec (dictTagNum + _idh.word_dict_size);
+    tisr.start = totalIBits;
+    tisr.here = totalIBits;
+    tisr.B = BIO_Bblock_Init (N+p, p);
+    
+    // add the length of the fragment numbers (two numbers for each
+    // tag, one for start and one for end)
+    totalIBits += BIO_Bblock_Bound_b (N+p, p, tisr.B);
+
+    // align next byte
+#ifdef USE_LONG_LONG
+    totalIBits = (totalIBits + 7ull) & 0xfffffffffffffff8ull;
+#else
+    totalIBits = (totalIBits + 7ul) & 0xfffffff8ul;
+#endif
+
+    CheckIntOverflow (totalIBits, lastTotalIBits);
+  }
+
+  fclose (dictFile);
+}
+
+/*
+// assumes the chunk tag information has been placed in .first
+static void PrintChunkInfo (unsigned long chunkMem,
+			    unsigned long numChunkWords,
+			    unsigned long numChunkTags) {
+  static unsigned long chunksRead = 0;
+  ++chunksRead;
+  cout << "Chunk Number: " << chunksRead << "\n";
+  cout << "numChunkDocs " << numDocsInChunk << "\n";
+  cout << "numChunkFrags " << numFragsInChunk << "\n";
+  cout << "mem " << chunkMem << "\n";
+  cout << "numWords " << numChunkWords << "\n";
+  cout << "numTags " << numChunkTags << "\n\n";
+
+  TagMapDict::iterator tagMapHere = tagMapDict.begin();
+  TagMapDict::iterator tagMapEnd = tagMapDict.end();
+  while (tagMapHere != tagMapEnd) {
+    unsigned long tagMapNum = (*tagMapHere).second.tagNum;
+    cout << (*tagMapHere).first << " " << tagMapNum << " "
+	 << bitPtrs.GetTagBitPtr(tagMapNum).here << "\n";
+    ++tagMapHere;
+  }
+}
+*/
+
+void ReadChunk (invf_dict_header &_idh, bool wordLevelIndex) {
+  // reset globals
+  numChunkDocs = 0;
+  chunkStartFragNum = numFrags;
+
+  // read in information about this chunk
+  numDocsInChunk = chunkBuf.gamma_decode (NULL) - 1;
+  if (numDocsInChunk == 0)
+    FatalError (1, "The number of docs in the current chunk is 0");
+
+  numFragsInChunk = chunkBuf.gamma_decode (NULL) - 1;
+  unsigned long chunkMem = chunkBuf.gamma_decode (NULL) - 1;
+
+  if (chunkMem > ivfMemBufSize)
+    FatalError (1, "Chunk memory size is greater than maximum");
+  
+  unsigned long numChunkWords = chunkBuf.gamma_decode (NULL) - 1;
+  unsigned long numChunkTags = chunkBuf.gamma_decode (NULL) - 1;
+
+  
+  // reset stuff
+  ClearCharBuf (ivfMemBuf, ivfMemBufSize);
+  bitPtrs.ResetPtrs();  
+
+  // read in the entries in occurrence order storing the
+  // "chunkWordCount" in "start" and the "chunkFragCount"
+  // in "here"
+  unsigned long numOccur;
+  unsigned long wordNum;
+  for (numOccur=0; numOccur<numChunkWords; ++numOccur) {
+    wordNum = occurConvert.TranslateWord (numOccur);
+    BitPtr &wordPtr = bitPtrs.GetWordBitPtr (wordNum);
+    wordPtr.start = chunkBuf.gamma_decode (NULL) - 1;
+    if (wordPtr.start >= 2)
+      wordPtr.here = chunkBuf.gamma_decode (NULL);
+    else wordPtr.here = wordPtr.start;
+  }
+  unsigned long tagNum;
+  for (numOccur=0; numOccur<numChunkTags; ++numOccur) {
+    tagNum = occurConvert.TranslateTag (numOccur);
+    BitPtr &tagPtr = bitPtrs.GetTagBitPtr (tagNum);
+    // only chunkFragCount is encoded for tags
+    tagPtr.start = chunkBuf.gamma_decode (NULL) - 1;
+    tagPtr.here = tagPtr.start;
+  }
+
+  /*  PrintChunkInfo (chunkMem, numChunkWords, numChunkTags);*/
+  
+  // create the bit ptrs in dictionary order
+  unsigned long totalIBits = 0; // only dealing with memory
+  unsigned long chunkWordCount, chunkFragCount;
+  for (wordNum=0; wordNum<_idh.word_dict_size; ++wordNum) {
+    BitPtr &wordPtr = bitPtrs.GetWordBitPtr (wordNum);
+    chunkWordCount = wordPtr.start;
+    chunkFragCount = wordPtr.here;
+    wordPtr.start = totalIBits;
+    wordPtr.here = totalIBits;
+    wordPtr.lastFragNum = chunkStartFragNum;
+    wordPtr.lgB = 0;
+    if (chunkWordCount > 0) {
+      wordPtr.lgB = floorlog_2 (BIO_Bblock_Init_W (numFragsInChunk,
+						   chunkFragCount));
+      totalIBits += BIO_Bblock_Bound (numFragsInChunk, chunkFragCount);
+      // use unary encoding for memory buffer encoding of fragment freq
+      if (!wordLevelIndex) {
+	totalIBits += chunkWordCount;
+      }
+    }
+  }
+  for (tagNum=0; tagNum<_idh.tag_dict_size; ++tagNum) {
+    BitPtr &tagPtr = bitPtrs.GetTagBitPtr (tagNum);
+    chunkFragCount = tagPtr.here;
+    tagPtr.start = totalIBits;
+    tagPtr.here = totalIBits;
+    tagPtr.lastFragNum = chunkStartFragNum;
+    tagPtr.lgB = 0;
+    if (chunkFragCount > 0) {
+      unsigned long pTag = chunkFragCount*2;
+      tagPtr.lgB = floorlog_2 (BIO_Bblock_Init_W (numFragsInChunk+pTag,
+						  pTag));
+      unsigned long bLen = BIO_Bblock_Bound (numFragsInChunk+pTag,
+					     pTag);
+//        cout << tagNum + _idh.word_dict_size << " ";
+//        cout << "numFrags: " << numFragsInChunk
+//    	   << " chunkFragCount: " << chunkFragCount
+//    	   << " B: " << 1 << tagPtr.lgB
+//    	   << " blen: " << blen << "\n";
+      totalIBits += bLen;
+    }
+  }
+  bitPtrs.GetEndStart() = totalIBits;
+  bitPtrs.GetEndHere() = totalIBits;
+
+  if ((totalIBits + 7ul) >> 3ul > chunkMem) {
+    cerr << "totalIBits: " << totalIBits << "\n";
+    cerr << "bytes: " << ((totalIBits + 7ul) >> 3ul) << "\n";
+    cerr << "chunkMem: " << chunkMem << "\n";
+    FatalError (1, "Pointers exceed buffer size");
+  }
+}
+
+
+
+
+int init_ivf_2 (const TagInfo &/*tagInfo*/, char *filename) {
+  // read in compressed dictionary header
+  FILE *dictFile = open_file (filename, INVF_DICT_SUFFIX, "rb",
+			      MAGIC_STEM_BUILD, MG_ABORT);
+  idh.Read (dictFile);
+  fclose (dictFile);
+
+  // set the size of the bit ptrs
+  bitPtrs.SetSize (idh.word_dict_size, idh.tag_dict_size);
+
+  // open the chunk file and read in the maximum memory needed
+  // for the inverted memory buffer
+  chunkFile = open_file (filename, INVF_CHUNK_SUFFIX, "rb",
+			 MAGIC_CHUNK, MG_ABORT);
+  ReadUL (chunkFile, ivfMemBufSize);
+  chunkBuf.attachFile (chunkFile);
+
+  // allocate memory for the inverted buffer
+  ivfMemBuf = new char [ivfMemBufSize];
+  ClearCharBuf (ivfMemBuf, ivfMemBufSize);
+
+  // read in the word dictionary
+  ReadWordDict (filename);
+
+  // read in the tag dictionary
+  ReadTagDict (filename, idh);
+
+  // read in the level information
+  ReadLevelFile (filename);
+  bool wordLevelIndex = ivfLevel.indexLevel.empty();
+  
+  // set up the translation table file
+  occurConvert.Open (filename, idh.word_dict_size, idh.tag_dict_size);
+
+  // reset some globals
+  numDocs = 0;
+  numChunkDocs = 0;
+  numDocsInChunk = 0;
+  numFrags = 0;
+  numFragsInChunk = 0;
+  chunkStartFragNum = 0;
+
+  strcpy (collectFilename, filename);
+  
+  
+  // create the inverted file
+  mg_ullong totalIBits = 0;
+  FILE *invfFile = create_file (filename, INVF_SUFFIX, "wb",
+				MAGIC_INVF, MG_ABORT);
+  totalIBits += sizeof (unsigned long) * 8; // magic number
+  totalIBits += 8 * 200;                    // 200 byte gap -- why??????
+  fclose (invfFile);
+
+  // init the inverted file state cache
+  invfState.Open (filename);
+  InitInvfState (filename, idh, invfState, totalIBits, wordLevelIndex);
+
+  return COMPALLOK;
+}
+
+static void CloseTextTag (IP2TagInfo &tInfo, const UCArray &/*tagName*/) {
+  if (!tInfo.inTag) return;
+
+    // add this tag to the inverted list
+  BitPtr &tagBitPtr = bitPtrs.GetTagBitPtr (tInfo.tagNum);
+  unsigned long endFrag = numFrags;
+  int b = 1 << tagBitPtr.lgB;
+
+  /*
+  cout << (tInfo.tagNum+idh.word_dict_size) << " \"<" << tagName << ">\" "
+       << tInfo.startFrag << " " << endFrag << "\n";
+  */
+    
+  mems_bitio_buffer buffer ((u_char *) ivfMemBuf, tagBitPtr.here);
+  buffer.bblock_encode (tInfo.startFrag - tagBitPtr.lastFragNum + 1,
+			b, NULL);
+  buffer.bblock_encode (endFrag - tInfo.startFrag + 1, b, NULL);
+  tagBitPtr.lastFragNum = endFrag;
+  tagBitPtr.here = buffer.position();
+  buffer.encodeDone();
+  
+  // check for buffer overrun
+  bitPtrs.CheckTagBufOverrun (tInfo.tagNum);
+  
+  // reset information about this tag
+  tInfo.inTag = false;
+  tInfo.startFrag = 0;
+}
+
+static void ProcessOpenTag (const TextEl &el, bool &inFrag) {
+  // close tag if open
+  IP2TagInfo &tInfo = tagMapDict[el.tagName];
+  if (tInfo.inTag) CloseTextTag (tInfo, el.tagName);
+
+  // open this tag
+  tInfo.inTag = true;
+  tInfo.startFrag = numFrags;
+
+  // check for start of next fragment
+  bool wordLevelIndex = ivfLevel.indexLevel.empty();
+  if (!wordLevelIndex && el.tagName == ivfLevel.indexLevel) {
+    ++numFrags;
+    inFrag = true;
+  }
+}
+
+static void ProcessCloseTag (const TextEl &el, bool &inFrag) {
+  // check for end of fragment
+  bool wordLevelIndex = ivfLevel.indexLevel.empty();
+  if (!wordLevelIndex && el.tagName == ivfLevel.indexLevel) {
+    inFrag = false;
+  }
+
+  IP2TagInfo &tInfo = tagMapDict[el.tagName];
+  CloseTextTag (tInfo, el.tagName);
+}
+
+static void ProcessText (const TextEl &el, bool &inFrag) {
+  // make sure this text is to be indexed
+  bool wordLevelIndex = ivfLevel.indexLevel.empty();
+  if (!wordLevelIndex && !inFrag) return;
+
+  const unsigned char *textHere = &(el.text[0]);
+  const unsigned char *textEnd = &(el.text[el.text.size() - 1]);
+  unsigned char mgWord[MAXSTEMLEN + 1];
+  
+  if (!inaword_mgpp (textHere, textEnd))
+    ParseNonindexWord (textHere, textEnd);
+
+  
+  // Alternately parse off words and non-words from the input
+
+  while (textHere <= textEnd) {
+    textHere = ParseIndexMGWord (textHere, textEnd, mgWord);
+    textHere = ParseNonindexWord (textHere, textEnd);
+
+    if (mgWord[0] > 0) {
+      if (wordLevelIndex) ++numFrags;
+
+      unsigned long wordNum = perf_hash (wordHashDict, mgWord);
+
+      /*
+      cout << wordNum << " \"";
+      cout.write (mgWord+1, *mgWord);
+      cout << "\" " << numFrags << "\n";
+      */
+      
+      // add this word to the inverted list
+      BitPtr &wordBitPtr = bitPtrs.GetWordBitPtr (wordNum);
+      unsigned long fragNum = numFrags;
+      int b = 1 << wordBitPtr.lgB;
+  
+      mems_bitio_buffer buffer ((u_char *) ivfMemBuf, wordBitPtr.here);
+
+      // note: this assumes that fragments don't carry over between
+      // chunks (which they don't because all tags are closed at the
+      // end of each document and chunks are based on document
+      // boundaries), i.e. the first fragment number must be greater
+      // than the starting fragment number of the chunk.
+      if (fragNum > wordBitPtr.lastFragNum) {
+	buffer.bblock_encode ((fragNum - wordBitPtr.lastFragNum - 1) + 1,
+			      b, NULL);
+	if (!wordLevelIndex) buffer.encodeBit (1); // freq = 1
+	
+      } else if (!wordLevelIndex) {
+	// add one to the frequency count for this word
+	buffer.seek (buffer.position()-1);
+	buffer.encodeBit (0); // unary encoding -- last = 1
+	buffer.encodeBit (1);
+      }
+      
+      wordBitPtr.lastFragNum = fragNum;
+      wordBitPtr.here = buffer.position();
+      buffer.encodeDone();
+      
+      // check for buffer overrun
+      bitPtrs.CheckWordBufOverrun (wordNum);
+    }
+  }
+}
+
+// combine the in memory inverted buffer with the disk
+// based inverted file
+static void DiskMerge (char *filename) {
+  bool wordLevelIndex = ivfLevel.indexLevel.empty();
+
+      // make sure we have something to process
+  if (numChunkDocs <= 0) return;
+    
+  // open the inverted file
+  FILE *invfFile = open_file (filename, INVF_SUFFIX, "rb+",
+			      MAGIC_INVF, MG_ABORT);
+  random_bitio_buffer invfOutBuf (invfFile);
+
+  // set up to decode the entries in memory
+  mems_bitio_buffer memInBuf ((u_char *) ivfMemBuf, 0);
+
+  // write out the word information
+  unsigned long wordNum;
+  int b;
+  unsigned long currFragNum;
+  unsigned long delta;
+  unsigned long currFreq;
+  for (wordNum=0; wordNum<idh.word_dict_size; ++wordNum) {
+    // go to the end of the last inverted file entry
+    InvfStateRec &wordDiskState = invfState.GetRec (wordNum);
+    invfOutBuf.SEEK_X (wordDiskState.here);
+
+    // go to the start of the inverted chunk info in memory
+    BitPtr &wordBitPtr = bitPtrs.GetWordBitPtr (wordNum);
+    memInBuf.seek(wordBitPtr.start);
+
+    // decode each entry and re-write to disk
+    currFragNum = chunkStartFragNum;
+    while (memInBuf.position() < wordBitPtr.here) {
+      // decode word entry
+      b = 1 << wordBitPtr.lgB;
+      delta = memInBuf.bblock_decode (b, NULL);
+      currFragNum += delta;
+      if (!wordLevelIndex) currFreq = memInBuf.unary_decode (NULL);
+      else currFreq = 1;
+
+      // recode on disk
+      invfOutBuf.bblock_encode (currFragNum-wordDiskState.lastFragNum,
+				wordDiskState.B, NULL);
+      if (!wordLevelIndex) invfOutBuf.gamma_encode (currFreq, NULL);
+      wordDiskState.lastFragNum = currFragNum;
+    }
+
+    wordDiskState.here = invfOutBuf.TELL_X();
+  }
+
+  // write out the tag information
+  unsigned long tagNum;
+  unsigned long currTagStart;
+  unsigned long currTagEnd;
+  for (tagNum=0; tagNum<idh.tag_dict_size; ++tagNum) {
+    // go to the end of the last inverted file entry
+    InvfStateRec &tagDiskState = invfState.GetRec (tagNum+idh.word_dict_size);
+    invfOutBuf.SEEK_X (tagDiskState.here);
+
+    // go to the start of the inverted chunk info in memory
+    BitPtr &tagBitPtr = bitPtrs.GetTagBitPtr (tagNum);
+    memInBuf.seek(tagBitPtr.start);
+
+    // decode each entry and re-write to disk
+    currTagEnd = chunkStartFragNum;
+    while (memInBuf.position() < tagBitPtr.here) {
+      // decode tag entry
+      b = 1 << tagBitPtr.lgB;
+      delta = memInBuf.bblock_decode (b, NULL) - 1;
+      currTagStart = currTagEnd + delta;
+      delta = memInBuf.bblock_decode (b, NULL) - 1;
+      currTagEnd = currTagStart + delta;
+
+      // recode on disk
+      invfOutBuf.bblock_encode (currTagStart-tagDiskState.lastFragNum+1,
+				tagDiskState.B, NULL);
+      invfOutBuf.bblock_encode (currTagEnd-currTagStart+1,
+				tagDiskState.B, NULL);
+
+      tagDiskState.lastFragNum = currTagEnd;
+    }
+
+    tagDiskState.here = invfOutBuf.TELL_X();
+  }
+
+  memInBuf.done();
+
+  invfOutBuf.encodeDone();
+  fclose (invfFile);
+}
+
+
+int process_ivf_2 (const TagInfo &/*tagInfo*/, const TextElArray &doc) {
+  bool wordLevelIndex = ivfLevel.indexLevel.empty();
+  bool inFrag = false;
+  if (wordLevelIndex) inFrag = true; // unconditional
+  
+  // get next chunk information if need to. the chunk information
+  // is needed before the first document is processed
+  if (numChunkDocs >= numDocsInChunk) ReadChunk (idh, wordLevelIndex);
+
+  // process each text element
+  TextElArray::const_iterator here = doc.begin();
+  TextElArray::const_iterator end = doc.end();
+  while (here != end) {
+    // process this element
+    if ((*here).elType == OpenTagE) ProcessOpenTag (*here, inFrag);
+    else if ((*here).elType == CloseTagE) ProcessCloseTag (*here, inFrag);
+    else ProcessText (*here, inFrag);
+    
+    ++here;
+  }
+
+  // close off any unclosed tags
+  TagMapDict::iterator tdHere = tagMapDict.begin();
+  TagMapDict::iterator tdEnd = tagMapDict.end();
+  while (tdHere != tdEnd) {
+    CloseTextTag ((*tdHere).second, (*tdHere).first);
+    ++tdHere;
+  }
+  
+  // we've processed one more document
+  ++numDocs;
+  ++numChunkDocs;
+
+  // merge the memory based inverted file with the one on
+  // disk if this is the end of this chunk
+  if (numChunkDocs >= numDocsInChunk) DiskMerge (collectFilename);
+  
+  return COMPALLOK;
+}
+
+
+static void CondenseInvfFile (char *filename, unsigned long &bytesOutput) {
+  FILE *inInvfFile = open_file (filename, INVF_SUFFIX, "rb",
+				MAGIC_INVF, MG_ABORT);
+  FILE *outInvfFile = open_file (filename, INVF_SUFFIX, "rb+",
+				 MAGIC_INVF, MG_ABORT);
+
+  // skip the magic number
+  fseek (outInvfFile, sizeof (unsigned long), SEEK_SET);
+  
+  // write the inverted file header -- use defaults for most things
+  invf_file_header ifh;
+  ifh.no_of_words = idh.word_dict_size;
+  ifh.no_of_tags = idh.tag_dict_size;
+  ifh.word_level_index = (ivfLevel.indexLevel.empty()) ? 1 : 0;
+  ifh.Write (outInvfFile);
+
+  bytesOutput = ftell (outInvfFile);
+
+  // process each meaningful byte in the file
+  unsigned long numEntries = ifh.no_of_words + ifh.no_of_tags;
+  unsigned long entryNum;
+  mg_ullong lastStart = 0;
+  for (entryNum = 0; entryNum < numEntries; ++entryNum) {
+    InvfStateRec &stateRec = invfState.GetRec (entryNum);
+
+    // overrun check
+    if (stateRec.start < lastStart)
+      FatalError (1, "Inverted file Buffer overrun");
+    lastStart = stateRec.start;
+    
+    unsigned long oldEntryStart = stateRec.start >> 3;
+    unsigned long oldEntryStartOver = stateRec.start & 7; // should be 0
+    unsigned long oldEntryEnd = (stateRec.here + 7) >> 3;  // byte after end
+    unsigned long oldEntryEndOver = stateRec.here & 7;
+
+    fseek (inInvfFile, oldEntryStart, SEEK_SET);
+
+    stateRec.here -= stateRec.start;
+    stateRec.start = (mg_ullong)bytesOutput * 8 + oldEntryStartOver;
+    stateRec.here += stateRec.start;
+    while (oldEntryStart < oldEntryEnd) {
+      unsigned char c = getc (inInvfFile);
+      if (oldEntryStart == oldEntryEnd - 1) {
+	u_char ands[8] =
+	{0xff, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
+	c &= ands[oldEntryEndOver];
+      }
+      putc (c, outInvfFile);
+      ++bytesOutput;
+      ++oldEntryStart;
+    }
+  }  
+
+  fclose (inInvfFile);
+
+#ifdef __WIN32__
+  if (_chsize (_fileno (outInvfFile), bytesOutput) != 0)
+    Message ("Could not truncate invf.");
+#else
+  ftruncate (fileno (outInvfFile), bytesOutput);
+#endif
+
+  fclose (outInvfFile);
+}
+
+static void OutputInvfIdx (char *filename, unsigned long invfNumBytes) {
+  FILE *invfIdxFile = create_file (filename, INVF_IDX_SUFFIX, "wb",
+				   MAGIC_INVI, MG_ABORT);
+
+  // process each meaningful byte in the file
+  unsigned long numEntries = idh.word_dict_size + idh.tag_dict_size;
+  unsigned long entryNum;
+  for (entryNum = 0; entryNum < numEntries; ++entryNum) {
+    InvfStateRec &stateRec = invfState.GetRec (entryNum);
+
+    // assumes that inverted entries start at beginning of each byte
+    if (!WriteUL (invfIdxFile, (stateRec.start >> 3))) break;
+  }
+
+  WriteUL (invfIdxFile, invfNumBytes);
+
+  fclose (invfIdxFile);
+}
+
+
+int done_ivf_2 (const TagInfo &/*tagInfo*/, char *filename) {
+  // close most open files
+  if (chunkFile != NULL) {
+    chunkBuf.done();
+    fclose (chunkFile);
+    chunkFile = NULL;
+  }
+  occurConvert.Close();
+  
+  // free allocated memory
+  bitPtrs.Clear();
+  if (ivfMemBuf != NULL) { delete [] ivfMemBuf; ivfMemBuf = NULL; }
+  free_perf_hash (wordHashDict);
+  wordHashDict = NULL;
+  tagMapDict.erase (tagMapDict.begin(), tagMapDict.end());
+
+  // condense the inverted file and truncate it
+  // this function also writes out the inverted header
+  unsigned long invfNumBytes = 0;
+  CondenseInvfFile (filename, invfNumBytes);
+
+  OutputInvfIdx (filename, invfNumBytes);
+
+  // close the rest of the open files
+  invfState.Close ();
+  
+  return COMPALLOK;
+}
Index: /indexers/branches/3.03a/mgpp/text/locallib.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/locallib.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/locallib.cpp	(revision 14757)
@@ -0,0 +1,218 @@
+/**************************************************************************
+ *
+ * locallib.cpp -- Misc functions
+ * Copyright (C) 1994  Gary Eddy, Alistair Moffat and Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+
+#include "memlib.h"
+#include "bitio_gen.h"
+#include "huffman.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "locallib.h"
+#include "text.h"
+
+int 
+vecentropy (int *A, int n)
+{
+  int total = 0, i;
+  double bits = 0.0;
+
+  for (i = 0; i < n; ++i)
+    total += A[i];
+  for (i = 0; i < n; ++i)
+    if (A[i])
+      bits += A[i] * log2 (1.0 * total / A[i]);
+  return ((int) (bits + 0.9999));
+
+}
+
+static void 
+siftdown (int *A, int i, int n)
+{
+  int ms, t;
+
+  while (2 * i + 1 <= n - 1)
+    {
+      if (2 * i + 1 == n - 1 || A[2 * i + 1] < A[2 * i + 2])
+	ms = 2 * i + 1;
+      else
+	ms = 2 * i + 2;
+      if (A[i] > A[ms])
+	{
+	  t = A[i];
+	  A[i] = A[ms];
+	  A[ms] = t;
+	}
+      i = ms;
+    }
+}
+
+static void 
+buildheap (int *A, int n)
+{
+  int i;
+  for (i = n / 2 - 1; i >= 0; --i)
+    siftdown (A, i, n);
+}
+
+int 
+huffcodebits (unsigned long *A, int n)
+{
+  int i, j, tot = 0, bits = 0, v1, v2, *B;
+
+  B = (int *) Xmalloc (n * sizeof (int));
+  j = 0;
+  for (i = 0; i < n; ++i)
+    {
+      if (A[i])
+	{
+	  tot += (B[j++] = A[i]);
+	}
+    }
+  n = j;
+
+  if (n == 0 || tot == 0)
+    return (0);
+
+  buildheap (B, n);
+  while (n > 1)
+    {
+      v1 = B[0];
+      B[0] = B[n - 1];
+      --n;
+      siftdown (B, 0, n);
+      v2 = B[0];
+      B[0] = v1 + v2;
+      siftdown (B, 0, n);
+      bits += v1 + v2;
+    }
+  Xfree (B);
+  return (bits);
+}
+
+
+int 
+modelbits (unsigned long *A, int n)
+{
+  int i, bits = 0, last, N = 0;
+
+  last = -1;
+  for (i = 0; i < n; ++i)
+    {
+      if (A[i])
+	{
+	  bits += BIO_Gamma_Length (i - last) + BIO_Gamma_Length (A[i]);
+	  last = i;
+	  ++N;
+	}
+    }
+  if (N == 0)
+    return (0);
+  bits += BIO_Gamma_Length (N);
+  return (bits);
+}
+
+
+
+
+
+/* Find the next prime number larger than p */
+int 
+prime (int p)
+{
+  int limit;
+  p += (p & 1) + 1;
+  limit = (int) sqrt ((double) p) + 1;
+  do
+    {
+      int j;
+      while (limit * limit < p)
+	++limit;
+      for (j = 3; j <= limit && p % j; j += 2)
+	;			/* NULLBODY */
+      if (j > limit)
+	break;
+      p += 2;
+    }
+  while (1);
+  return (p);
+}
+
+
+
+int Read_cdh (FILE * f, compression_dict_header * cdh, u_long * /*mem*/,
+	      u_long * disk) {
+  if (disk)
+    (*disk) += sizeof (*cdh);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  if (fread (cdh, sizeof (*cdh), 1, f) == 1)
+    {
+      int i;
+      NTOHUL(cdh->dict_type);
+      NTOHUL(cdh->novel_method);
+      for (i = 0; i < TEXT_PARAMS; ++i)
+	NTOHUL(cdh->params[i]);
+      NTOHUL(cdh->num_words[0]);
+      NTOHUL(cdh->num_words[1]);
+      NTOHUL(cdh->num_word_chars[0]);
+      NTOHUL(cdh->num_word_chars[1]);
+      NTOHUL(cdh->lookback);
+      return 0;
+    }
+  else
+    return -1;
+}
+
+
+int 
+Read_cfh (FILE * f, comp_frags_header * cfh, u_long * mem, u_long * disk)
+{
+  int i;  /* [RPAP - Jan 97: Endian Ordering] */
+
+  if (Read_Huffman_Data (f, &cfh->hd, mem, disk) == -1)
+    return -1;
+  if (fread (&cfh->uncompressed_size,
+	     sizeof (cfh->uncompressed_size), 1, f) != 1)
+    return -1;
+  NTOHUL(cfh->uncompressed_size);  /* [RPAP - Jan 97: Endian Ordering] */
+
+  if (disk)
+    (*disk) += sizeof (cfh->uncompressed_size);
+
+  memset (cfh->huff_words_size, '\0', sizeof (cfh->huff_words_size));
+
+  if ((int)fread (cfh->huff_words_size + cfh->hd.mincodelen,
+	     sizeof (*cfh->huff_words_size),
+	     cfh->hd.maxcodelen - cfh->hd.mincodelen + 1, f) !=
+      cfh->hd.maxcodelen - cfh->hd.mincodelen + 1)
+    return -1;
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = cfh->hd.mincodelen; i < cfh->hd.maxcodelen + 1; ++i)
+    NTOHUL(cfh->huff_words_size[i]);
+
+  if (disk)
+    (*disk) += sizeof (*cfh->huff_words_size) *
+      (cfh->hd.maxcodelen - cfh->hd.mincodelen + 1);
+  return 0;
+}
+
Index: /indexers/branches/3.03a/mgpp/text/locallib.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/locallib.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/locallib.h	(revision 14757)
@@ -0,0 +1,45 @@
+/**************************************************************************
+ *
+ * locallib.h -- Misc functions
+ * Copyright (C) 1994  Gary Eddy, Alistair Moffat and Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef LOCALLIB_H
+#define LOCALLIB_H
+
+#include "sysfuncs.h"
+
+#include "text.h"
+
+#define NUMOF(a) (sizeof(a)/sizeof((a)[0]))
+
+int vecentropy (int *A, int n);
+
+int huffcodebits (unsigned long *A, int n);
+
+int modelbits (unsigned long *A, int n);
+
+int prime (int p);
+
+
+int Read_cdh (FILE * f, compression_dict_header * cdh, u_long * mem, u_long * disk);
+
+int Read_cfh (FILE * f, comp_frags_header * cfh, u_long * mem, u_long * disk);
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/mg.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mg.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mg.h	(revision 14757)
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * mg.h -- General header file
+ * Copyright (C) 1994  Neil Sharman, Alistair Moffat and Lachlan Andrew
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+
+#ifndef H_MG
+#define H_MG
+
+
+#define COMPALLOK	(0)
+#define COMPERROR	(-1)
+
+#define MAXSTRING       3000000
+#define BUFFERSIZE      (MAXSTRING+30000)
+
+#define	MAXLN	65536
+#define WORDS           1
+#define NONWORDS        0
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/mg.special.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mg.special.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mg.special.cpp	(revision 14757)
@@ -0,0 +1,58 @@
+/**************************************************************************
+ *
+ * mg.special.cpp -- Special pass for mg_passes
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+#include "sysfuncs.h"
+#include "mg.h"
+#include "build.h"
+
+int init_special (const TagInfo &/*tagInfo*/, char * /*FileName*/) {
+  return COMPALLOK;
+}
+
+int process_special (const TagInfo &/*tagInfo*/, const TextElArray &doc) {
+  // print out the document
+  TextElArray::const_iterator here = doc.begin();
+  TextElArray::const_iterator end = doc.end();
+  while (here != end) {
+    if ((*here).elType == OpenTagE) {
+      cout << "** OpenTag  \"" << (*here).tagName << "\"\tText \""
+	   << (*here).text << "\"\n"; 
+    } else if ((*here).elType == CloseTagE) {
+      cout << "** CloseTag \"" << (*here).tagName << "\"\tText \""
+	   << (*here).text << "\"\n";
+    } else {
+      cout << "** Text     \"" << (*here).text << "\"\n";
+    }
+    
+    ++here;
+  }
+  
+  return COMPALLOK;
+}
+
+int done_special (const TagInfo &/*tagInfo*/, char * /*FileName*/) {
+  return COMPALLOK;
+}
Index: /indexers/branches/3.03a/mgpp/text/mg_errors.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mg_errors.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mg_errors.cpp	(revision 14757)
@@ -0,0 +1,72 @@
+/**************************************************************************
+ *
+ * mg_errors.cpp -- Error related stuff for mgquery
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+#include "sysfuncs.h"
+#include "memlib.h"
+
+#include "mg_errors.h"
+
+int mg_errno = MG_NOERROR;
+
+char *mg_errorstrs[] =
+{
+  "No error",
+  "Out of memory",
+  "File \"%s\" not found",
+  "Bad magic number in \"%s\"",
+  "Error reading \"%s\"",
+  "MG_BUFTOOSMALL",
+  "Files required for level 2 and 3 inversion are missing"};
+
+
+/* [RJM 07/98: Memory Leak] -- rest of file */
+
+static char null_data[] = "";
+char *mg_error_data = null_data;
+
+
+void MgErrorData (char *s)
+{
+  /* free the current error string, unless it is the null string */
+  if ((mg_error_data != NULL) && (mg_error_data != null_data)) {
+    delete []mg_error_data;
+    mg_error_data = null_data;
+  }
+
+  /* make a copy of the string */
+  mg_error_data = Xstrdup (s);
+
+  /* if the alloc failed set the error to the null string */
+  if (!mg_error_data) mg_error_data = null_data;
+}
+
+
+void MgErrorDeinit (void)
+{
+  /* free the current error string, unless it is the null string */
+  if ((mg_error_data != NULL) && (mg_error_data != null_data)) {
+    delete []mg_error_data;
+    mg_error_data = null_data;
+  }
+}
Index: /indexers/branches/3.03a/mgpp/text/mg_errors.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mg_errors.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mg_errors.h	(revision 14757)
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * mg_errors.h -- Error related stuff for mgquery
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+
+extern int mg_errno;
+extern char *mg_error_data;
+extern char *mg_errorstrs[];
+
+
+#define MG_NOERROR 0
+#define MG_NOMEM 1
+#define MG_NOFILE 2
+#define MG_BADMAGIC 3
+#define MG_READERR 4
+#define MG_BUFTOOSMALL 5
+#define MG_INVERSION 6
+
+void MgErrorData (char *s);
+void MgErrorDeinit (void);
Index: /indexers/branches/3.03a/mgpp/text/mg_files.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mg_files.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mg_files.cpp	(revision 14757)
@@ -0,0 +1,274 @@
+/**************************************************************************
+ *
+ * mg_files.cpp -- Routines for handling files for the auxillary programs
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "messages.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+
+
+/* This must contain a valid path without a trailing slash */
+static char *basepath = NULL;
+
+/* This sets the base path for all file operations */
+void 
+set_basepath (const char *bp)
+{
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+  basepath = "";
+#else
+  char *s;
+  /* Free the memory for the base path if it has already been allocated */
+  if (basepath)
+    {
+      delete []basepath;
+      basepath = NULL;
+    }
+
+  if (!bp || *bp == '\0')
+    bp = ".";
+
+  s = strrchr (bp, '/');
+  if (s && *(s + 1) == '\0')
+    {
+      basepath = new char[strlen (bp) + 2];
+      if (!basepath)
+	return;
+      strcpy (basepath, bp);
+      strcat (basepath, ".");
+    }
+  else
+    basepath = Xstrdup (bp);
+#endif
+}
+
+
+
+/* return the currently defined basepath */
+char *
+get_basepath (void)
+{
+  if (!basepath)
+    set_basepath (getenv ("MGDATA"));
+  return basepath;
+}
+
+
+
+/* This generates the name of a file. It places the name in the buffer
+   specified or if that is NULL it uses a static buffer. */
+char *
+make_name (const char *name, const char *suffix, char *buffer)
+{
+  static char path[512];
+  if (!buffer)
+    buffer = path;
+  if (!basepath)
+    set_basepath (getenv ("MGDATA"));
+  sprintf (buffer, FILE_NAME_FORMAT, basepath, name, suffix);  /* [RPAP - Feb 97: WIN32 Port] */
+  return buffer;
+}
+
+
+/* [JFG - Mar 06: Accent folding patch] */
+/* This generates a suffixe for a file name. It places the name in the
+   buffer specified or if that is NULL, it uses a static buffer.
+   Please do not specify buffers under 512 or the data to be written. */
+char *
+make_suffix (const char *suffix_format, const char suffix_arg, char *buffer)
+{
+  static char suffix[512]; 
+  if (!buffer)
+    buffer = suffix;
+  sprintf (buffer, suffix_format, suffix_arg);
+  return buffer;
+}
+ 
+
+
+/* This will open the specified file and check its magic number.
+   Mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *
+open_named_file (const char *name, const char *mode,
+		 u_long magic_num, int err_mode)
+{
+  unsigned long magic;
+  FILE *f = NULL;
+  char *err;
+  f = fopen (name, mode);
+
+  if (!f)
+    {
+      err = "Unable to open \"%s\"";
+      goto error;
+    }
+
+  if (magic_num)
+    {
+      if (fread (&magic, sizeof (magic), 1, f) != 1)
+	{
+	  err = "No magic number \"%s\"";
+	  goto error;
+	}
+
+      NTOHUL(magic);  /* [RPAP - Jan 97: Endian Ordering] */
+
+      if (!IS_MAGIC (magic))
+	{
+	  err = "No MG magic number \"%s\"";
+	  goto error;
+	}
+
+      if (magic != magic_num)
+	{
+	  err = "Wrong MG magic number \"%s\"";
+	  goto error;
+	}
+    }
+  return f;
+
+error:
+  if (f)
+    fclose (f);
+  if (err_mode == MG_ABORT)
+    FatalError (1, err, name);
+  if (err_mode == MG_MESSAGE)
+    Message (err, name);
+  return NULL;
+}
+
+
+
+/* This will open the specified file and check its magic number.
+   Mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *
+open_file (const char *name, const char *suffix, const char *mode,
+	   u_long magic_num, int err_mode)
+{
+  char path[512];
+  if (!basepath)
+    set_basepath (getenv ("MGDATA"));
+  sprintf (path, FILE_NAME_FORMAT, basepath, name, suffix);  /* [RPAP - Feb 97: WIN32 Port] */
+  return open_named_file (path, mode, magic_num, err_mode);
+}
+
+
+
+
+
+
+/* This will create the specified file and set its magic number.
+
+   Mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *
+create_named_file (const char *name, const char *mode,
+		   u_long magic_num, int err_mode)
+{
+  FILE *f = NULL;
+  char *err;
+  f = fopen (name, mode);
+
+  if (!f)
+    {
+      err = "Unable to open \"%s\"";
+      goto error;
+    }
+
+  if (magic_num)
+    HTONUL(magic_num);  /* [RPAP - Jan 97: Endian Ordering] */
+    if (fwrite (&magic_num, sizeof (magic_num), 1, f) != 1)
+      {
+	err = "Couldn't write magic number \"%s\"";
+	goto error;
+      }
+
+  return f;
+
+error:
+  if (f)
+    fclose (f);
+  if (err_mode == MG_ABORT)
+    FatalError (1, err, name);
+  if (err_mode == MG_MESSAGE)
+    Message (err, name);
+  return NULL;
+}
+
+
+
+
+
+
+
+/* This will create the specified file and set its magic number.
+
+   Mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *
+create_file (const char *name, const char *suffix, const char *mode,
+	     u_long magic_num, int err_mode)
+{
+  char path[512];
+  if (!basepath)
+    set_basepath (getenv ("MGDATA"));
+  sprintf (path, FILE_NAME_FORMAT, basepath, name, suffix);  /* [RPAP - Feb 97: WIN32 Port] */
+  return create_named_file (path, mode, magic_num, err_mode);
+}
Index: /indexers/branches/3.03a/mgpp/text/mg_files.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mg_files.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mg_files.h	(revision 14757)
@@ -0,0 +1,329 @@
+/**************************************************************************
+ *
+ * mg_files.h -- Routines for handling files for the auxillary programs
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef MG_FILES_H
+#define MG_FILES_H
+
+#include "sysfuncs.h"
+
+/* Magic numbers for the different types of files */
+
+#define GEN_MAGIC(a,b,c,d) ((unsigned long)(((a)<<24) + ((b)<<16) + \
+					    ((c)<<8) + (d)))
+
+#define MAGIC_XXXX		GEN_MAGIC('M','G', 0 , 0)
+#define MAGIC_STATS_DICT	GEN_MAGIC('M','G','S','D')
+#define MAGIC_AUX_DICT		GEN_MAGIC('M','G','A','D')
+#define MAGIC_FAST_DICT		GEN_MAGIC('M','G','F','D')
+#define MAGIC_DICT		GEN_MAGIC('M','G','D', 0 )
+#define MAGIC_STEM_BUILD	GEN_MAGIC('M','G','S', 0 )
+#define MAGIC_HASH		GEN_MAGIC('M','G','H', 0 )
+#define MAGIC_STEM		GEN_MAGIC('M','G','s', 0 )
+#define MAGIC_CHUNK		GEN_MAGIC('M','G','C', 0 )
+#define MAGIC_CHUNK_TRANS	GEN_MAGIC('M','G','c', 0 )
+#define MAGIC_TEXT		GEN_MAGIC('M','G','T', 0 )
+#define MAGIC_TEXI		GEN_MAGIC('M','G','t', 0 )
+#define MAGIC_TEXT_LEVELS	GEN_MAGIC('M','G','t','L')
+#define MAGIC_TEXI_WGT		GEN_MAGIC('M','G','t','W')
+#define MAGIC_INVF		GEN_MAGIC('M','G','I', 0 )
+#define MAGIC_INVF_LEVELS	GEN_MAGIC('M','G','I','L')
+#define MAGIC_INVI		GEN_MAGIC('M','G','i', 0 )
+#define MAGIC_WGHT		GEN_MAGIC('M','G','W', 0 )
+#define MAGIC_WGHT_APPROX	GEN_MAGIC('M','G','w', 0 )
+#define MAGIC_PARAGRAPH		GEN_MAGIC('M','G','P', 0 )
+#define MAGIC_STEM_GEN(x)	GEN_MAGIC('M', 'G', 's', x)
+#define IS_MAGIC(a) ((((u_long)(a)) & 0xffff0000) == MAGIC_XXXX)
+
+
+/* err_mode values for open_file and create_file */
+#define MG_ABORT 0
+#define MG_MESSAGE 1
+#define MG_CONTINUE 2
+
+
+
+
+
+/* File suffixes */
+
+
+/* The compression dictionary built by txt.pass1 */
+#ifdef SHORT_SUFFIX
+# define TEXT_STATS_DICT_SUFFIX	 ".tsd"
+#else
+# define TEXT_STATS_DICT_SUFFIX	 ".text.stats"
+#endif
+
+/* The compression dictionary built by text.pass1 and comp_dict.process */
+#ifdef SHORT_SUFFIX
+# define TEXT_DICT_SUFFIX	 ".td"
+#else
+# define TEXT_DICT_SUFFIX	 ".text.dict"
+#endif
+
+/* The compression dictionary built by mg_make_fast_dict */
+#ifdef SHORT_SUFFIX
+# define TEXT_DICT_FAST_SUFFIX	 ".tdf"
+#else
+# define TEXT_DICT_FAST_SUFFIX	 ".text.dict.fast"
+#endif
+
+/* The auxilary dictionary built by text.pass2 */
+#ifdef SHORT_SUFFIX
+# define TEXT_DICT_AUX_SUFFIX	 ".tda"
+#else
+# define TEXT_DICT_AUX_SUFFIX	 ".text.dict.aux"
+#endif
+
+/* The compressed text build by text.pass2 */
+#ifdef SHORT_SUFFIX
+# define TEXT_SUFFIX		 ".t"
+#else
+# define TEXT_SUFFIX		 ".text"
+#endif
+
+/* The combined compressed text index and document weight file */
+#ifdef SHORT_SUFFIX
+# define TEXT_IDX_WGT_SUFFIX	 ".tiw"
+#else
+# define TEXT_IDX_WGT_SUFFIX	 ".text.idx.wgt"
+#endif
+
+/* The compressed text index file */
+#ifdef SHORT_SUFFIX
+# define TEXT_IDX_SUFFIX	 	".ti"
+#else
+# define TEXT_IDX_SUFFIX	 	".text.idx"
+#endif
+
+/* The document levels in the text */
+#ifdef SHORT_SUFFIX
+# define TEXT_LEVEL_SUFFIX	 	".tl"
+#else
+# define TEXT_LEVEL_SUFFIX	 	".text.level"
+#endif
+
+/* The dictionary of stemmed words build by invf.pass1 and ivf.pass1 */
+#ifdef SHORT_SUFFIX
+# define INVF_DICT_SUFFIX         ".id"
+#else
+# define INVF_DICT_SUFFIX         ".invf.dict"
+#endif
+
+/* The dictionary of stemmed words build by stem.process */
+#ifdef SHORT_SUFFIX
+# define INVF_DICT_BLOCKED_SUFFIX ".idb"
+#else
+# define INVF_DICT_BLOCKED_SUFFIX ".invf.dict.blocked"
+#endif
+
+/* The exact document weights file build by make.weights, invf.pass2,
+   or ivf.pass2 */
+#ifdef SHORT_SUFFIX
+# define WEIGHTS_SUFFIX           ".w"
+#else
+# define WEIGHTS_SUFFIX           ".weight"
+#endif
+
+/* The approximate weights file built by make.weights */
+#ifdef SHORT_SUFFIX
+# define APPROX_WEIGHTS_SUFFIX    ".wa"
+#else
+# define APPROX_WEIGHTS_SUFFIX    ".weight.approx"
+#endif
+
+/* The inverted file build by invf.pass2 or ivf.pass2 */
+#ifdef SHORT_SUFFIX
+# define INVF_SUFFIX              ".i"
+#else
+# define INVF_SUFFIX              ".invf"
+#endif
+
+/* The level information for the inverted text */
+#ifdef SHORT_SUFFIX
+# define INVF_LEVEL_SUFFIX              ".il"
+#else
+# define INVF_LEVEL_SUFFIX              ".invf.level"
+#endif
+
+/* The inverted file index build by invf.pass2 or ivf.pass2 */
+#ifdef SHORT_SUFFIX
+# define INVF_IDX_SUFFIX          ".ii"
+#else
+# define INVF_IDX_SUFFIX          ".invf.idx"
+#endif
+
+/* The inverted file chunk descriptor built by ivf.pass1 */
+#ifdef SHORT_SUFFIX
+# define INVF_CHUNK_SUFFIX        ".ic"
+#else
+# define INVF_CHUNK_SUFFIX        ".invf.chunk"
+#endif
+
+/* The word index translation file built by ivf.pass1 */
+#ifdef SHORT_SUFFIX
+# define INVF_CHUNK_TRANS_SUFFIX  ".ict"
+#else
+# define INVF_CHUNK_TRANS_SUFFIX  ".invf.chunk.trans"
+#endif
+
+/* The hashed stemmed dictionary built by make.perf_hash */
+#ifdef SHORT_SUFFIX
+# define INVF_DICT_HASH_SUFFIX    ".idh"
+#else
+# define INVF_DICT_HASH_SUFFIX    ".invf.dict.hash"
+#endif
+
+/* The paragraph descriptior file built by invf.pass1 or ivf.pass1 */
+#ifdef SHORT_SUFFIX
+# define INVF_PARAGRAPH_SUFFIX    ".ip"
+#else
+# define INVF_PARAGRAPH_SUFFIX    ".invf.paragraph"
+#endif
+
+/* The trace file build by mg.builder. */
+#ifdef SHORT_SUFFIX
+# define TRACE_SUFFIX             ".trc"
+#else
+# define TRACE_SUFFIX             ".trace"
+#endif
+
+/* The compression stats file build by mg.builder. */
+#ifdef SHORT_SUFFIX
+# define COMPRESSION_STATS_SUFFIX ".cs"
+#else
+# define COMPRESSION_STATS_SUFFIX ".compression.stats"
+#endif
+
+/* [RPAP - Jan 97: Stem Index Change] */
+/* [JFG - Mar 06: Accent folding patch] 
+ * Use the pattern with make_suffix */
+/* The casefolded index into the stemmed dictionary */
+#ifdef SHORT_SUFFIX
+# define INVF_DICT_BLOCKED_SUFFIX_PAT ".ib%d"
+#else
+# define INVF_DICT_BLOCKED_SUFFIX_PAT ".invf.dict.blocked.%d"
+#endif
+
+
+/* [RPAP - Feb 97: WIN32 Port] */
+#ifdef __WIN32__
+#define FILE_NAME_FORMAT "%s%s%s"
+#else
+#define FILE_NAME_FORMAT "%s/%s%s"
+#endif
+
+
+/* This sets the base path for all file operations */
+void set_basepath (const char *bp);
+
+
+/* return the currently defined basepath */
+char *get_basepath (void);
+
+
+
+
+/* This generates the name of a file. It places the name in the buffer
+   specified or if that is NULL it uses a static buffer. */
+char *make_name (const char *name, const char *suffix, char *buffer);
+
+/* [JFG - Mar 06: Accent folding patch] */
+/* This generates the suffix of a file. It places the name in the buffer
+   specified or if that is NULL it uses a static buffer. */
+char *make_suffix (const char *suffix_format, const char suffix_arg, char *buffer);
+
+
+
+
+
+/* This will open the specified file and check its magic number.
+   Mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *open_named_file (const char *name, const char *mode,
+		       u_long magic_num, int err_mode);
+
+
+
+
+/* This will open the specified file and check its magic number.
+
+   err_mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *open_file (const char *name, const char *suffix, const char *mode,
+		 u_long magic_num, int err_mode);
+
+
+
+
+
+/* This will create the specified file and set its magic number.
+
+   Mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *create_named_file (const char *name, const char *mode,
+			 u_long magic_num, int err_mode);
+
+
+
+/* This will create the specified file and set its magic number.
+
+   err_mode may take on the following values
+   MG_ABORT    : causes an error message to be generated and the
+   program aborted if there is an error.
+   MG_MESSAGE  : causes a message to be generated and a NULL value to
+   be returned if there is an error.
+   MG_CONTINUE : causes a NULL value to be returned if there is an error.
+
+   On success if returns the FILE *. On failure it will return a NULL value
+   and possibly generate an error message, or it will exit the program with
+   an error message.   */
+FILE *create_file (const char *name, const char *suffix, const char *mode,
+		   u_long magic_num, int err_mode);
+
+
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/mgpp_compression_dict.1
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_compression_dict.1	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_compression_dict.1	(revision 14757)
@@ -0,0 +1,188 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.\"------------------------------------------------------------
+.TH mgpp_compression_dict 1 \*(Dt CITRI
+.SH NAME
+mgpp_compression_dict \- build a compression dictionary.
+.SH SYNOPSIS
+.B mgpp_compression_dict
+[
+.B \-h
+]
+[
+.BR \-C " |"
+.BR \-P " |"
+.B  \-S
+]
+.if n .ti +9n
+[
+.BR \-0 " |"
+.BR \-1 " |"
+.BR \-2 " |"
+.B  \-3
+]
+[
+.BR \-H " |"
+.BR \-B " |"
+.BR \-D " |"
+.BR \-Y " |"
+]
+.if n .ti +9n
+.if t .ti +.5i
+[
+.BI \-l " lookback"
+]
+[
+.BI \-k " mem"
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mgpp_compression_dict
+builds a compression dictionary based on the statistics gathered
+during the first pass over the text.  The options to the program are
+mainly concerned with limiting the amount of memory the dictionary
+will use and with how the text compressor will cope with any novel
+words found during the compression phase.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.B \-C
+Build a complete dictionary from the statistics file.  If during the
+text compression phase a novel word is found, then the compressor will
+produce an error message and stop.
+.TP
+.B \-P
+Build a partial dictionary from the statistics file.  This dictionary
+assumes that the statistics file are based on the entire text.  The
+statistics of words not includes in the dictionary are used to
+calculate the escape probability.  If novel words are being coded
+character by character, then there may not be a Huffman code for every
+possible character.  This means that the compressor may fail if a novel
+word contains a novel character.
+.TP
+.B \-S
+Build a seed dictionary from the statistics file.  This dictionary
+assumes that the statistics file is based on only a portion of the
+text to be compressed.  The probability of a novel word is based on the
+number of words that have only occurred once.  If novel words are being
+coded character by character, then the Huffman codes for characters are
+based on the frequency of characters in the dictionary.
+.TP
+.B \-0
+All words from the statistics file are included in the built
+dictionary.
+.TP
+.B \-1
+Words are included in the dictionary until the dictionary reaches the
+desired size.  Words are selected for the dictionary based on the order
+they occurred in the source text.
+.TP
+.B \-2
+Words are included in the dictionary until the dictionary reaches the
+desired size.  The most frequent words are included in the dictionary
+first; where there is a tie for frequency, the shortest word is
+included first.
+.TP
+.B \-3
+Words are included in the dictionary until the dictionary reaches the
+desired size.  The most frequent words are included in the dictionary
+first; where there is a tie for frequency, the shortest word is
+included first.  Words are the shuffled back and forth between the
+`keep' and `discard' lists to find the `optimal' set of words that
+should be in the dictionary.
+.TP
+.B \-H
+This specifies that novel words will be coded character by character
+using Huffman codes.
+.TP
+.B \-B
+This specifies that an auxiliary dictionary will be built by the
+compressor.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using binary codes.  The binary code represents their occurrence
+position in the auxiliary dictionary.
+.TP
+.B \-D
+This specifies that an auxiliary dictionary will be built by the
+compressor.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using delta codes.  The delta code represents their occurrence position
+in the auxiliary dictionary.
+.TP
+.B \-Y
+This specifies that an auxiliary dictionary will be built by the
+compressor.  Each novel word found will be placed at the end of the
+auxiliary dictionary.  Novel words will be coded in the compressed text
+using a combination of gamma and binary codes.  The code represents
+their occurrence position in the auxiliary dictionary.  This generally
+produces better compression than
+.B \-B
+or
+.BR \-D .
+.TP
+.BI \-l " lookback"
+The generated dictionary is designed to be front coded when it is
+loaded into memory.  Under normal circumstances, a front-coded
+dictionary would require scanning from the beginning in order to find
+any particular word.  However, every
+.I lookback
+words in the dictionary, the whole word is stored and a pointer to that
+word maintained.  E.g., if
+.I lookback
+is 4, then every fourth word is stored in its entirety.
+.TP
+.BI \-k " mem"
+This limits the amount of memory to use for the generated
+dictionary.  Words are selected for the dictionary based of the text
+statistics, and whether
+.BR \-0 , " \-1" , " \-2"
+or
+.B \-3
+is specified.  The memory is calculated assuming a lookback of 0,
+irrespective of what actual lookback is specified.  This means that if
+a non-zero lookback is given, the dictionary will actually occupy
+less space than specified by
+.BR \-k .
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the mgpp
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.text.stats
+Statistics about the source text.
+.TP
+.B *.text.dict
+Compression dictionary for the source text.
+.SH "SEE ALSO"
+.na
+.BR mgpp_fast_comp_dict (1),
+.BR mgpp_invf_dict (1),
+.BR mgpp_passes (1),
+.BR mgpp_perf_hash_build (1),
+.BR mgpp_stem_idx (1),
+.BR mgpp_weights_build (1)
Index: /indexers/branches/3.03a/mgpp/text/mgpp_compression_dict.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_compression_dict.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_compression_dict.cpp	(revision 14757)
@@ -0,0 +1,1021 @@
+/**************************************************************************
+ *
+ * mgpp_compression_dict.cpp -- Routines for creating compression dictionary
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+/* getopt is in posix.2, so cygwin should have it in unistd, but doesn't */
+#if defined (__WIN32__) || defined (__CYGWIN__)
+# include "getopt_old.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "messages.h"
+#include "local_strings.h"
+#include "bitio_gen.h"
+#include "bitio_m_stdio.h"
+#include "mgheap.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "locallib.h"
+#include "invf.h"
+#include "text.h"
+#include "words.h"
+#include "mg.h"
+#include "WordData.h"
+
+#define MAXBITS (sizeof(unsigned long) * 8)
+
+#define is_power_of_two(a) ((a) != 0 && (((a) & ((a)-1)) == 0))
+
+#define MAX_RECALCULATIONS 100
+
+typedef struct DictWordData : public WordData
+  {
+    float saving;
+    float char_bit_cost;
+    u_long num_trans;
+    u_char *word;
+  }
+DictWordData;
+
+static DictWordData *Words[2];
+static u_long Num[2];
+static u_long chars[2];
+
+#define KIND(p) (((p) >= Words[0] && (p) < Words[0] + Num[0]) ? 0 : 1)
+#define IsWord(p) (((p) >= Words[1] && (p) < Words[1] + Num[1]) ? 1 : 0)
+#define IsNonWord(p) (((p) >= Words[0] && (p) < Words[0] + Num[0]) ? 1 : 0)
+
+
+typedef struct DictData
+  {
+    DictWordData **wd;
+    u_long num_wds;
+    u_long chars;
+  }
+DictData;
+
+typedef DictData DictInfo[2];
+
+static DictInfo keep, discard, all;
+static compression_stats_header csh;
+
+static char *file_name = "";
+static u_long novel_method = MG_NOVEL_HUFFMAN_CHARS;
+
+
+static void ReadInWords (char *);
+static void Select_on (int k, heap_comp hc);
+static void Method3 (int k);
+static void Select_all (void);
+static u_long WriteOutWords (char *, u_long, int);
+static int DecFreqIncWL (void *a, void *b);
+static int OccuranceOrder (void *a, void *b);
+
+
+
+int main (int argc, char **argv)
+{
+  int ch;
+  char type = 'C';
+  char mode = '0';
+  int lookback = 2;
+  double k = 0;
+  u_long mem_reqd;
+  opterr = 0;
+  msg_prefix = argv[0];
+  while ((ch = getopt (argc, argv, "0123CPSf:d:l:hk:HDY")) != -1)
+    switch (ch)
+      {
+      case 'H':
+	novel_method = MG_NOVEL_HUFFMAN_CHARS;
+	break;
+      case 'D':
+	novel_method = MG_NOVEL_DELTA;
+	break;
+      case 'Y':
+	novel_method = MG_NOVEL_HYBRID;
+	break;
+      case 'f':		/* input file */
+	file_name = optarg;
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 'C':
+      case 'P':
+      case 'S':
+	type = ch;
+	break;
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+	mode = ch;
+	break;
+      case 'l':
+	lookback = atoi (optarg);
+	if (!is_power_of_two (lookback))
+	  FatalError (1, "The lookback value must be a power of 2");
+	lookback = floorlog_2 (lookback);
+	break;
+      case 'k':
+	k = atof (optarg) * 1024;
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-l lookback] [-f input_file]"
+	"[-d data directory] [-h] [-0|-1|-2|-3] [-C|-P|-S] [-k mem (Kb)]\n",
+		 argv[0]);
+	exit (1);
+      }
+
+  ReadInWords (file_name);
+
+  if (type == 'C')
+    {
+      Select_all ();
+      mem_reqd = WriteOutWords (file_name, MG_COMPLETE_DICTIONARY, lookback);
+    }
+  else
+    {
+      switch (mode)
+	{
+	case '0':
+	  Select_all ();
+	  break;
+	case '1':
+#ifndef SILENT
+	  Message ("Dictionary limit of %.2f Kb", k / 1024);
+#endif
+	  Select_on ((int) k, OccuranceOrder);
+	  break;
+	case '2':
+#ifndef SILENT
+	  Message ("Dictionary limit of %.2f Kb", k / 1024);
+#endif
+	  Select_on ((int) k, DecFreqIncWL);
+	  break;
+	case '3':
+#ifndef SILENT
+	  Message ("Dictionary limit of %.2f Kb", k / 1024);
+#endif
+	  Method3 ((int) k);
+	  break;
+	}
+      if (type == 'P')
+	{
+	  mem_reqd = WriteOutWords (file_name, MG_PARTIAL_DICTIONARY, lookback);
+	}
+      else
+	{
+	  mem_reqd = WriteOutWords (file_name, MG_SEED_DICTIONARY, lookback);
+	}
+    }
+
+#ifndef SILENT
+  Message ("Num words           : %8u -> %8u\n", Num[1], keep[1].num_wds);
+  Message ("Num non-words       : %8u -> %8u\n", Num[0], keep[0].num_wds);
+  Message ("Chars of words      : %8u -> %8u\n", chars[1], keep[1].chars);
+  Message ("Chars of non-words  : %8u -> %8u\n", chars[0], keep[0].chars);
+  Message ("Mem usage           : %8u -> %8u\n",
+	   (Num[0] + Num[1]) * sizeof (char *) + chars[0] + chars[1],
+	     (keep[0].num_wds + keep[1].num_wds) * sizeof (char *) +
+	   keep[0].chars + keep[1].chars);
+  Message ("Actual mem required : %8u\n", mem_reqd);
+#endif
+  return (0);
+}
+
+
+
+
+static void 
+ReadInWords (char *filename)
+{
+  FILE *f;
+  unsigned long i;
+  f = open_file (filename, TEXT_STATS_DICT_SUFFIX, "rb",
+		 MAGIC_STATS_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  fread (&csh, sizeof (csh), 1, f);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(csh.num_docs);
+  NTOHD(csh.num_bytes);
+
+  for (i = 0; i < 2; ++i)
+    {
+      frags_stats_header fsh;
+      char *buf;
+      DictWordData *wd;
+      chars[i] = 0;
+
+      fread (&fsh, sizeof (fsh), 1, f);
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(fsh.num_frags);
+      NTOHUL(fsh.mem_for_frags);
+
+      Num[i] = all[i].num_wds = fsh.num_frags;
+
+      /* The +1 on the following line is to leave room for the esc code. */
+      all[i].wd = (DictWordData **) Xmalloc (sizeof (DictWordData *) * Num[i] + 1);
+
+      buf = (char *) Xmalloc (fsh.mem_for_frags);
+      wd = Words[i] = (DictWordData *) Xmalloc (sizeof (DictWordData) * Num[i]);
+      unsigned int j;
+      for (j = 0; j < Num[i]; ++j, ++wd)
+	{
+	  int len;
+
+	  // read docCount and wordCount
+	  wd->read(f);
+
+	  // read an mgString
+	  len = fgetc (f);
+	  wd->word = (u_char *) buf;
+	  *buf++ = len;
+	  fread (buf, len, 1, f);
+	  buf += len;
+	  all[i].wd[j] = wd;
+	}
+      chars[i] = fsh.mem_for_frags - fsh.num_frags;
+    }
+  fclose (f);
+}
+
+
+static void 
+Alloc_keep_discard (void)
+{
+  keep[0].num_wds = 0;
+  keep[0].wd = (DictWordData **) Xmalloc ((Num[0] + 1) * sizeof (DictWordData *));
+  keep[1].num_wds = 0;
+  keep[1].wd = (DictWordData **) Xmalloc ((Num[1] + 1) * sizeof (DictWordData *));
+  discard[0].num_wds = 0;
+  discard[0].wd = (DictWordData **) Xmalloc ((Num[0] + 1) * sizeof (DictWordData *));
+  discard[1].num_wds = 0;
+  discard[1].wd = (DictWordData **) Xmalloc ((Num[1] + 1) * sizeof (DictWordData *));
+}
+
+
+static int 
+sort_comp (const void *a, const void *b)
+{
+  DictWordData *aa = *(DictWordData **) a;
+  DictWordData *bb = *(DictWordData **) b;
+  return casecompare (aa->word, bb->word);  /* [RPAP - Jan 97: Stem Index Change] */
+}
+
+
+
+static void 
+SortAndCount_DictData (DictData * dd)
+{
+  unsigned int i;
+  DictWordData **wd;
+  qsort (dd->wd, dd->num_wds, sizeof (DictWordData *), sort_comp);
+  dd->chars = 0;
+  wd = dd->wd;
+  for (i = 0; i < dd->num_wds; ++i, ++wd)
+    dd->chars += (*wd)->word[0];
+}
+
+
+static void 
+Select_all (void)
+{
+  unsigned int i;
+  Alloc_keep_discard ();
+  keep[0].num_wds = Num[0];
+  for (i = 0; i < Num[0]; ++i)
+    keep[0].wd[i] = Words[0] + i;
+  keep[1].num_wds = Num[1];
+  for (i = 0; i < Num[1]; ++i)
+    keep[1].wd[i] = Words[1] + i;
+  SortAndCount_DictData (&keep[0]);
+  SortAndCount_DictData (&keep[1]);
+}
+
+
+
+
+static int 
+DecFreqIncWL (void *a, void *b)
+{
+  DictWordData *aa = *(DictWordData **) a;
+  DictWordData *bb = *(DictWordData **) b;
+  if (aa->docCount > bb->docCount)
+    return -1;
+  else if (aa->docCount < bb->docCount)
+    return 1;
+  else
+    return bb->word[0] - aa->word[0];
+}
+
+
+static int 
+OccuranceOrder (void *a, void *b)
+{
+  DictWordData *aa = *(DictWordData **) a;
+  DictWordData *bb = *(DictWordData **) b;
+  if (aa->words() > bb->words())
+    return 1;
+  else if (aa->words() < bb->words())
+    return -1;
+  else
+    return 0;
+}
+
+
+static void 
+Select_on (int k, heap_comp hc)
+{
+  int i, num, mem;
+  DictWordData **wd;
+
+  Alloc_keep_discard ();
+
+  num = Num[0] + Num[1];
+  wd = (DictWordData **) Xmalloc (num * sizeof (DictWordData *));
+  for (i = 0; (unsigned int)i < Num[0]; ++i)
+    wd[i] = Words[0] + i;
+  for (i = 0; (unsigned int)i < Num[1]; ++i)
+    wd[i + Num[0]] = Words[1] + i;
+
+  heap_build (wd, sizeof (*wd), num, hc);
+
+  mem = 0;
+  while (k > mem && num)
+    {
+      int idx;
+      DictWordData *word = wd[0];
+#ifdef DEBUG
+      fprintf (stderr, "%4d:%4d:%8d :%8d :%8d : \"%s\"\n",
+	       keep[0].num_wds, keep[1].num_wds,
+	       mem, word->documents(), word->word, word2str (word->word));
+#endif
+      mem += sizeof (u_char *) + word->word[0];
+      heap_deletehead (wd, sizeof (*wd), &num, hc);
+      idx = KIND (word);
+      keep[idx].wd[keep[idx].num_wds++] = word;
+    }
+
+  for (i = 0; i < num; ++i)
+    {
+      DictWordData *word = wd[i];
+      int idx = KIND (word);
+      discard[idx].wd[discard[idx].num_wds++] = word;
+    }
+  SortAndCount_DictData (&keep[0]);
+  SortAndCount_DictData (&keep[1]);
+  SortAndCount_DictData (&discard[0]);
+  SortAndCount_DictData (&discard[1]);
+
+  assert (keep[0].num_wds + discard[0].num_wds == Num[0]);
+  assert (keep[1].num_wds + discard[1].num_wds == Num[1]);
+
+}
+
+
+
+static int 
+BigSaving (void *a, void *b)
+{
+  DictWordData *aa = *(DictWordData **) a;
+  DictWordData *bb = *(DictWordData **) b;
+  return (aa->saving > bb->saving) ? -1 : (aa->saving < bb->saving);
+}
+
+static int 
+SmallSaving (void *a, void *b)
+{
+  DictWordData *aa = *(DictWordData **) a;
+  DictWordData *bb = *(DictWordData **) b;
+  return (aa->saving < bb->saving) ? -1 : (aa->saving > bb->saving);
+}
+
+
+static void 
+CalcCharCounts (DictWordData ** wd, int num,
+		char *char_lens[2], char *len_lens[2],
+		u_long escape[2])
+{
+  long char_freqs[2][256];
+  long len_freqs[2][16];
+  huff_data hd;
+  int i;
+  escape[0] = 0;
+  escape[1] = 0;
+  memset (char_freqs, '\0', sizeof (char_freqs));
+  memset (len_freqs, '\0', sizeof (len_freqs));
+  for (i = 0; i < num; ++i, ++wd)
+    {
+      u_long freq = (*wd)->documents();
+      u_char *buf = (*wd)->word;
+      int len = *buf++;
+      int idx = KIND (*wd);
+      len_freqs[idx][len] += freq;
+      escape[idx] += freq;
+      for (; len; --len, ++buf)
+	char_freqs[idx][(u_long) (*buf)] += freq;
+    }
+  Generate_Huffman_Data (256, char_freqs[0], &hd, NULL);
+  char_lens[0] = hd.clens;
+  Generate_Huffman_Data (256, char_freqs[1], &hd, NULL);
+  char_lens[1] = hd.clens;
+
+  Generate_Huffman_Data (16, len_freqs[0], &hd, NULL);
+  len_lens[0] = hd.clens;
+  Generate_Huffman_Data (16, len_freqs[1], &hd, NULL);
+  len_lens[1] = hd.clens;
+}
+
+
+
+
+
+inline void CalcBitCostForWordData(DictWordData **word, int num,
+				   double freqs_trans[2], u_long escape[2],
+				   char * char_lens[2], char *len_lens[2], 
+				   double esc[2], int num_trans)
+{ 
+  int j;
+
+  for (j = 0; j < num; ++j, ++word)
+    {
+      float   cbc, wbc;
+      u_char *buf = (*word)->word;
+      int     len = *buf++;
+      u_long  freq = (*word)->documents();
+      int     idx = KIND (*word);
+
+      cbc = len_lens[idx][len];
+      for (; len; --len, ++buf)
+	cbc += char_lens[idx][(u_long) (*buf)];
+
+      (*word)->char_bit_cost = (cbc + esc[idx]) * freq;
+
+      wbc = -log2 (freq / (freqs_trans[idx] + escape[idx])) * freq;
+
+      (*word)->saving = ((*word)->char_bit_cost - wbc) /
+	(sizeof (char *) + (*word)->word[0]);
+
+      (*word)->num_trans = num_trans;
+    }
+}
+
+
+
+void 
+CalcBitCost (DictWordData ** discard_word, int discard_num,
+	     DictWordData ** keep_word, int keep_num, double freqs_trans[2],
+	     u_long escape[2], int num_trans)
+{
+  char *char_lens[2];
+  char *len_lens[2];
+  double esc[2];
+  CalcCharCounts (discard_word, discard_num, char_lens, len_lens, escape);
+  esc[0] = -log2 (escape[0] / (freqs_trans[0] + escape[0]));
+  esc[1] = -log2 (escape[1] / (freqs_trans[1] + escape[1]));
+  CalcBitCostForWordData(discard_word, discard_num, freqs_trans, escape,
+			 char_lens, len_lens, esc, num_trans);
+  CalcBitCostForWordData(keep_word, keep_num, freqs_trans, escape,
+			 char_lens, len_lens, esc, num_trans);
+  Xfree (char_lens[0]);
+  Xfree (char_lens[1]);
+  Xfree (len_lens[0]);
+  Xfree (len_lens[1]);
+}
+
+inline void m3_transferWord(DictWordData **toHeap, int *toNum, heap_comp toSaving,
+			    DictWordData **fromHeap, int *fromNum, heap_comp fromSaving,
+			    int *num_trans, double freqs_trans[], int *mem, double *total,
+			    int *count)
+{
+  /* Transfer the word at the top of the keep heap to the
+     discard heap. */
+  DictWordData *word = fromHeap[0];
+  int idx = KIND (word);
+  heap_deletehead (fromHeap, sizeof (word), fromNum, fromSaving);
+  toHeap[*toNum] = word;
+  heap_additem (toHeap, sizeof (word), toNum, toSaving);
+  freqs_trans[idx] -= word->documents();
+  *mem = (*mem) - sizeof (u_char *) + word->word[0];
+  *num_trans += 1;
+  *total += word->saving;
+  *count += 1;
+#ifdef DEBUG
+  fprintf (stderr,
+	   "KEEP -> DISCARD %8d :%8d :%8.0f :%8.0f : \"%s\"\n",
+	   *mem, word->documents(), word->char_bit_cost,
+	   word->saving, word2str (word->word));
+#endif
+}
+
+inline void m3_storeWord(DictWordData **wordHeap, int wordNum, int num_trans, 
+			 double freqs_trans[], u_long escape[], heap_comp hc)
+{
+  DictWordData *word = wordHeap[0];
+  int idx = KIND (word);
+  float wbc;
+#ifdef DEBUG1
+  fprintf (stderr, "KEEP \"%s\" %.2f ->", word2str (word->word),
+	   word->saving);
+#endif
+  wbc = -log2 (word->documents() / (freqs_trans[idx] + escape[idx])) *
+    word->documents();
+  word->saving = (word->char_bit_cost - wbc) /
+    (sizeof (char *) + word->word[0]);
+#ifdef DEBUG1
+  fprintf (stderr, " %.2f\n", word->saving);
+#endif
+  word->num_trans = num_trans;
+  heap_changedhead (wordHeap, sizeof (word), wordNum, hc);
+}
+
+
+static void 
+Method3 (int k)
+{
+  int i, keep_num, discard_num, mem, num_trans, recalc_reqd;
+  int keep_to_discard = 0;
+  int discard_to_keep = 0;
+  int recalcs = 0;
+  double freqs_trans[2], total;
+  u_long escape[2];
+  DictWordData **keep_heap, **discard_heap;
+
+  freqs_trans[0] = freqs_trans[1] = 0;
+  num_trans = 0;
+
+  discard_num = Num[0] + Num[1];
+  discard_heap = (DictWordData **) Xmalloc (discard_num * sizeof (DictWordData *));
+
+  keep_num = 0;
+  keep_heap = (DictWordData **) Xmalloc (discard_num * sizeof (DictWordData *));
+
+
+  for (i = 0; (unsigned int)i < Num[0]; ++i)
+    discard_heap[i] = Words[0] + i;
+  for (i = 0; (unsigned int)i < Num[1]; ++i)
+    discard_heap[i + Num[0]] = Words[1] + i;
+
+  heap_build (discard_heap, sizeof (*discard_heap), discard_num, DecFreqIncWL);
+
+  mem = 0;
+  while (k > mem && discard_num)
+    {
+      DictWordData *word = discard_heap[0];
+      mem += sizeof (u_char *) + word->word[0];
+      heap_deletehead (discard_heap, sizeof (word), &discard_num, DecFreqIncWL);
+      keep_heap[keep_num++] = word;
+      freqs_trans[KIND (word)] += word->documents();
+      ++num_trans;
+    }
+
+  CalcBitCost (discard_heap, discard_num, keep_heap, keep_num,
+	       freqs_trans, escape, num_trans);
+  heap_build (discard_heap, sizeof (*discard_heap), discard_num, BigSaving);
+  heap_build (keep_heap, sizeof (*keep_heap), keep_num, SmallSaving);
+
+  total = 0;
+  recalc_reqd = 0;
+  while (keep_num && discard_num)
+    {
+      if ((keep_num && keep_heap[0]->num_trans < (unsigned)num_trans) ||
+	  (discard_num && discard_heap[0]->num_trans < (unsigned)num_trans))
+	{
+	  if (keep_num && keep_heap[0]->num_trans < (unsigned)num_trans)
+	    {
+	      m3_storeWord(keep_heap, keep_num, num_trans, freqs_trans, escape, SmallSaving);
+	    }
+
+	  if (discard_num && discard_heap[0]->num_trans < (unsigned)num_trans)
+	    {
+	      m3_storeWord(discard_heap, discard_num, num_trans, freqs_trans, escape, BigSaving);
+	    }
+	}
+      else if (keep_heap[0]->saving < discard_heap[0]->saving)
+	{
+	  assert (keep_num && discard_num);
+	  if (keep_num && mem + sizeof (char *) + discard_heap[0]->word[0] > (unsigned)k)
+	    {
+	      /* Transfer the word at the top of the keep heap to the
+	         discard heap. */
+	      m3_transferWord(discard_heap, &discard_num, BigSaving,
+			      keep_heap, &keep_num, SmallSaving,
+			      &num_trans, freqs_trans, &mem, &total, &keep_to_discard);
+	    }
+	  else
+	    {
+	      /* Transfer the word at the top of the discard heap to the
+	         keep heap. */
+	      m3_transferWord(keep_heap, &keep_num, SmallSaving,
+			      discard_heap, &discard_num, BigSaving,
+			      &num_trans, freqs_trans, &mem, &total, &discard_to_keep);
+	    }
+
+	  recalc_reqd = 1;
+
+	}
+      else
+	{
+	  if (recalc_reqd == 0)
+	    break;
+#ifdef DEBUG1
+	  fprintf (stderr, "--------------\n");
+#endif
+	  if (recalcs == MAX_RECALCULATIONS)
+	    break;
+	  CalcBitCost (discard_heap, discard_num, keep_heap, keep_num,
+		       freqs_trans, escape, num_trans);
+	  heap_build (discard_heap, sizeof (*discard_heap),
+		      discard_num, BigSaving);
+	  heap_build (keep_heap, sizeof (keep_heap), keep_num, SmallSaving);
+	  recalc_reqd = 0;
+	  ++recalcs;
+	}
+    }
+
+  Alloc_keep_discard ();
+
+  for (i = 0; i < discard_num; ++i)
+    {
+      DictWordData *word = discard_heap[i];
+      int idx = KIND (word);
+      assert (IsWord (word) || IsNonWord (word));
+      discard[idx].wd[discard[idx].num_wds++] = word;
+    }
+  for (i = 0; i < keep_num; ++i)
+    {
+      DictWordData *word = keep_heap[i];
+      int idx = KIND (word);
+      assert (IsWord (word) || IsNonWord (word));
+      keep[idx].wd[keep[idx].num_wds++] = word;
+    }
+  SortAndCount_DictData (&keep[0]);
+  SortAndCount_DictData (&keep[1]);
+  SortAndCount_DictData (&discard[0]);
+  SortAndCount_DictData (&discard[1]);
+
+  assert (keep[0].num_wds + discard[0].num_wds == Num[0]);
+  assert (keep[1].num_wds + discard[1].num_wds == Num[1]);
+#ifndef SILENT
+  Message ("Keep -> Discard        : %8d", keep_to_discard);
+  Message ("Discard -> Keep        : %8d", discard_to_keep);
+  Message ("Huffman Recalculations : %8d", recalcs);
+  if (recalcs == MAX_RECALCULATIONS)
+    Message ("WARNING: The number of recalculations == %d", MAX_RECALCULATIONS);
+#endif
+}
+
+
+
+
+
+
+
+
+
+
+/****************************************************************************
+ *****									*****
+ *****			Dictionary saving code				*****
+ *****									*****
+ ****************************************************************************/
+
+
+
+static void 
+Write_cdh (FILE * f, compression_dict_header * cdh)
+{
+  /* [RPAP - Jan 97: Endian Ordering] */
+  int i;
+  compression_dict_header tmp = *cdh;
+  HTONUL(tmp.dict_type);
+  HTONUL(tmp.novel_method);
+  for (i = 0; i < TEXT_PARAMS; ++i)
+    HTONUL(tmp.params[i]);
+  HTONUL(tmp.num_words[0]);
+  HTONUL(tmp.num_words[1]);
+  HTONUL(tmp.num_word_chars[0]);
+  HTONUL(tmp.num_word_chars[1]);
+  HTONUL(tmp.lookback);
+
+  fwrite (&tmp, sizeof (tmp), 1, f);
+}
+
+
+static void 
+Write_words (FILE * f, DictData * dd)
+{
+  unsigned int i;
+  u_char *curr, *prev = NULL;
+  for (i = 0; i < dd->num_wds; ++i)
+    {
+      int len;
+      curr = dd->wd[i]->word;
+      if (prev)
+	/* look for prefix match with prev string */
+	len = prefixlen (prev, curr);
+      else
+	len = 0;
+      fputc ((len << 4) + (curr[0] - len), f);
+      fwrite (curr + len + 1, sizeof (u_char), curr[0] - len, f);
+      prev = curr;
+    }
+
+}
+
+
+static int 
+Uncompressed_size (DictData * dd)
+{
+  unsigned int i, us;
+  for (us = i = 0; i < dd->num_wds; ++i)
+    us += dd->wd[i]->word[0];
+  return us;
+}
+
+
+static u_long 
+Write_data (FILE * f, DictData * dd, int lookback)
+{
+  u_long mem_reqd;
+  huff_data *hd;
+  int i; 
+  u_long us = dd->num_wds;
+  long *freqs;
+  u_long huff_words_size[MAX_HUFFCODE_LEN + 1];
+  u_long lencounts[MAX_HUFFCODE_LEN + 1];
+  u_char *lastword[MAX_HUFFCODE_LEN + 1];
+
+  if (!(freqs = new long [dd->num_wds]))
+    FatalError (1, "Unable to allocate memory for freqs");
+
+  for (i = 0; (unsigned)i < dd->num_wds; ++i)
+    {
+      freqs[i] = dd->wd[i]->documents();
+      us += dd->wd[i]->word[0];
+    }
+
+  if (!(hd = Generate_Huffman_Data (dd->num_wds, freqs, NULL, NULL)))
+    FatalError (1, "Unable to allocate memory for huffman data");
+
+  delete []freqs;
+  freqs = NULL;
+
+  if (Write_Huffman_Data (f, hd) == -1)
+    FatalError (1, "Unable to write huffman data");
+
+  HTONUL(us);  /* [RPAP - Jan 97: Endian Ordering] */
+  fwrite (&us, sizeof (us), 1, f);
+  NTOHUL(us);  /* [RPAP - Jan 97: Endian Ordering] */
+
+
+/* Calculate the amount of memory that will be required to store the text for
+   each different huffman code len. Every 1<<lookback words for each different
+   codelen length will not be prefixed by previous strings. */
+
+
+  memset (&huff_words_size, '\0', sizeof (huff_words_size));
+  memset (&lencounts, '\0', sizeof (lencounts));
+
+  mem_reqd = 0;
+
+  for (i = 0; (unsigned)i < dd->num_wds; ++i)
+    {
+      int codelen = hd->clens[i];
+      u_char *word = dd->wd[i]->word;
+
+      if (!codelen)
+	FatalError (1, "The length of a code for a word was zero");
+
+      huff_words_size[codelen] += word[0] + 1;
+      mem_reqd += word[0] + (lookback != 0);
+#if 0
+      if ((lencounts[codelen] & ((1 << lookback) - 1)) == 0)
+	lastword[codelen] = word;
+      else
+	huff_words_size[codelen] -= prefixlen (lastword[codelen], word);
+#else
+      if ((lencounts[codelen] & ((1 << lookback) - 1)) != 0)
+	{
+	  int save = prefixlen (lastword[codelen], word);
+	  mem_reqd -= save;
+	  huff_words_size[codelen] -= save;
+	}
+      else
+	{
+	  mem_reqd += sizeof (u_char *);
+	}
+      lastword[codelen] = word;
+#endif
+      ++lencounts[codelen];
+    }
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = hd->mincodelen; i < hd->maxcodelen + 1; ++i)
+    HTONUL(huff_words_size[i]);
+
+  fwrite (huff_words_size + hd->mincodelen, sizeof (*huff_words_size),
+	  hd->maxcodelen - hd->mincodelen + 1, f);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  for (i = hd->mincodelen; i < hd->maxcodelen + 1; ++i)
+    NTOHUL(huff_words_size[i]);
+
+  Write_words (f, dd);
+
+  delete []hd->clens;
+  delete hd;
+
+  return mem_reqd;
+}
+
+
+
+static void 
+Write_charfreqs (FILE * f, DictData * dd, int words,
+		 int zero_freq_permitted)
+{
+  unsigned int j;
+  long freqs[256];
+  DictWordData **wd = dd->wd;
+  huff_data *hd;
+
+  memset (freqs, '\0', sizeof (freqs));
+
+  for (j = 0; j < dd->num_wds; ++j, ++wd)
+    {
+      u_char *buf = (*wd)->word;
+      int len = *buf++;
+      for (; len; --len, ++buf)
+	freqs[(u_long) (*buf)] += (*wd)->documents();
+    }
+
+  if (!zero_freq_permitted)
+    for (j = 0; j < 256; ++j)
+      if (!freqs[j] && PESINAWORD (j) == words)
+	freqs[j] = 1;
+
+  if (!(hd = Generate_Huffman_Data (256, freqs, NULL, NULL)))
+    FatalError (1, "Unable to allocate memory for huffman data");
+
+  if (Write_Huffman_Data (f, hd) == -1)
+    FatalError (1, "Unable to write huffman data");
+
+  delete []hd->clens;
+  delete hd;
+}
+
+
+
+
+static void 
+Write_wordlens (FILE * f, DictData * dd, int zero_freq_permitted)
+{
+  unsigned int j;
+  long freqs[16];
+  DictWordData **wd = dd->wd;
+  huff_data *hd;
+
+  memset (freqs, '\0', sizeof (freqs));
+
+  for (j = 0; j < dd->num_wds; ++j, ++wd)
+    freqs[(*wd)->word[0]] += (*wd)->documents();
+
+  if (!zero_freq_permitted)
+    for (j = 0; j < 16; ++j)
+      if (!freqs[j])
+	freqs[j] = 1;
+
+  if (!(hd = Generate_Huffman_Data (16, freqs, NULL, NULL)))
+    FatalError (1, "Unable to allocate memory for huffman data");
+
+  if (Write_Huffman_Data (f, hd) == -1)
+    FatalError (1, "Unable to write huffman data");
+
+
+  delete []hd->clens;
+  delete hd;
+}
+
+
+
+static u_long 
+WriteOutWords (char *file_name, u_long type, int lookback)
+{
+  FILE *f;
+  int i;
+  u_long mem_reqd = 0;
+
+  compression_dict_header cdh;
+  f = create_file (file_name, TEXT_DICT_SUFFIX, "w+b",
+		   MAGIC_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  memset (&cdh, '\0', sizeof(cdh));
+
+  cdh.dict_type = type;
+  cdh.novel_method = (type == MG_SEED_DICTIONARY) ? novel_method :
+    MG_NOVEL_HUFFMAN_CHARS;
+
+  cdh.num_words[1] = keep[1].num_wds;
+  cdh.num_words[0] = keep[0].num_wds;
+  cdh.num_word_chars[1] = Uncompressed_size (&keep[1]);
+  cdh.num_word_chars[0] = Uncompressed_size (&keep[0]);
+  cdh.lookback = lookback;
+
+  Write_cdh (f, &cdh);
+
+  for (i = 0; i < 2; ++i)
+    switch (type)
+      {
+      case MG_COMPLETE_DICTIONARY:
+	{
+	  mem_reqd += Write_data (f, &keep[i], lookback);
+	}
+	break;
+      case MG_PARTIAL_DICTIONARY:
+	{
+	  if (keep[i].num_wds)
+	    {
+	      int j;
+	      DictWordData esc;
+	      esc.docCount = 0;
+	      esc.word = (u_char *) "";
+	      keep[i].wd[keep[i].num_wds++] = &esc;
+	      for (j = 0; (unsigned)j < discard[i].num_wds; ++j)
+		esc.docCount += discard[i].wd[j]->documents();
+	      if (!esc.docCount)
+		++esc.docCount;
+	      mem_reqd += Write_data (f, &keep[i], lookback);
+	    }
+	  Write_charfreqs (f, &discard[i], i, 1);
+	  Write_wordlens (f, &discard[i], 1);
+	}
+	break;
+      case MG_SEED_DICTIONARY:
+	{
+	  if (keep[i].num_wds)
+	    {
+	      int j;
+	      DictWordData esc;
+	      esc.docCount = 0;
+	      esc.word = (u_char *) "";
+	      keep[i].wd[keep[i].num_wds++] = &esc;
+	      for (j = 0; (unsigned)j < all[i].num_wds; ++j)
+		if (all[i].wd[j]->documents() == 1)
+		  ++esc.docCount;
+	      if (!esc.docCount)
+		++esc.docCount;
+	      mem_reqd += Write_data (f, &keep[i], lookback);
+	    }
+	  switch (novel_method)
+	    {
+	    case MG_NOVEL_HUFFMAN_CHARS:
+	      Write_charfreqs (f, &all[i], i, 0);
+	      Write_wordlens (f, &all[i], 0);
+	      break;
+	    case MG_NOVEL_DELTA:
+	      break;
+	    case MG_NOVEL_HYBRID:
+	      break;
+	    default:
+	      FatalError (1, "Bad novel method");
+	    }
+	}
+	break;
+      }
+  fclose (f);
+  return mem_reqd;
+}
Index: /indexers/branches/3.03a/mgpp/text/mgpp_decompress_text.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_decompress_text.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_decompress_text.cpp	(revision 14757)
@@ -0,0 +1,100 @@
+/**************************************************************************
+ *
+ * mgpp_decompress_text.cpp -- 
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+/* getopt is in posix.2, so cygwin should have it in unistd, but doesn't */
+#if defined (__WIN32__) || defined (__CYGWIN__)
+# include "getopt_old.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "UCArray.h"
+#include "sysfuncs.h"
+#include "TextGet.h"
+#include "messages.h"
+#include "mg_files.h"
+
+int main (int argc, char **argv) {
+  int ch;
+  char *filename = "";
+  char *basePath = "";
+  UCArray level;
+  SetCStr (level, "Document", 8);
+
+  opterr = 0;
+  msg_prefix = argv[0];
+
+  // process the command line arguments
+  while ((ch = getopt (argc, argv, "f:d:K:h")) != -1) {
+    switch (ch) {
+    case 'f':		/* input file */
+      filename = optarg;
+      break;
+    case 'd':
+      basePath = optarg;
+      set_basepath (optarg);
+      break;
+    case 'K':
+      SetCStr (level, optarg, strlen(optarg));
+      break;
+    case 'h':
+    case '?':
+      fprintf (stderr, "usage: %s [-h] [-K level] [-d directory] -f name\n",
+	       argv[0]);
+      exit (1);
+    }
+  }
+
+  // load up the text information
+  TextData td;
+  if (!td.LoadData (basePath, filename)) {
+    FatalError (1, "Couldn't load text information for \"%s\"", filename);
+  }
+  
+  // output each document in the level
+//    cout << td.levels << "\n";
+  
+  TextLevelInfo levelInfo = td.levels.levelInfo[level];
+  unsigned long docNum = 1;
+  UCArray docText;
+  while (docNum <= levelInfo.numEntries) {
+//      TextIdx docIdx;
+//      if (GetDocIdx (td, level, docNum, docIdx)) {
+//        cout << "doc: " << docNum << "\n";
+//        cout << docIdx;
+//      }
+    
+    if (!GetDocText (td, level, docNum, docText)) {
+      FatalError (1, "Error while trying to get document %u", docNum);
+    }
+
+    cout << docText << "\n";
+    
+    ++docNum;
+  }
+  
+  return 0;
+}
+
+
Index: /indexers/branches/3.03a/mgpp/text/mgpp_fast_comp_dict.1
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_fast_comp_dict.1	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_fast_comp_dict.1	(revision 14757)
@@ -0,0 +1,69 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.\"------------------------------------------------------------
+.TH mgpp_fast_comp_dict 1 \*(Dt CITRI
+.SH NAME
+mgpp_fast_comp_dict \- build a fast loading compression dictionary
+.SH SYNOPSIS
+.B mgpp_fast_comp_dict
+[
+.B \-h
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mgpp_fast_comp_dict
+builds a fast-loading compression dictionary from the standard
+compression dictionary.  The new dictionary has the property that
+.BR mgppquery (1)
+can load it in very quickly, making the startup time for
+.BR mgppquery (1)
+much shorter.  The new dictionary is larger on disk than the original,
+but they are no different when it comes to memory usage.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the mgpp
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.text.dict
+Compression dictionary.
+.TP
+.B *.text.dict.fast
+Fast loading compression dictionary.
+.TP
+.B *.text.dict.aux
+Auxiliary compression dictionary.
+.SH "SEE ALSO"
+.na
+.BR mgpp_compression_dict (1),
+.BR mgpp_invf_dict (1),
+.BR mgpp_passes (1),
+.BR mgpp_perf_hash_build (1),
+.BR mgpp_stem_idx (1),
+.BR mgpp_weights_build (1)
Index: /indexers/branches/3.03a/mgpp/text/mgpp_fast_comp_dict.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_fast_comp_dict.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_fast_comp_dict.cpp	(revision 14757)
@@ -0,0 +1,707 @@
+/**************************************************************************
+ *
+ * mgpp_fast_comp_dict.cpp -- Program to generate a fast compression dictionary
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+/* getopt is in posix.2, so cygwin should have it in unistd, but doesn't */
+#if defined (__WIN32__) || defined (__CYGWIN__)
+# include "getopt_old.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "sysfuncs.h"
+#include "huffman.h"
+#include "messages.h"
+#include "memlib.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "local_strings.h"
+#include "mg.h"
+#include "text.h"
+#include "invf.h"
+#include "mg_files.h"
+#include "locallib.h"
+#include "words.h"
+
+
+
+#define ALIGN_SIZE(p,t) (((p) + (sizeof(t)-1)) & (~(sizeof(t)-1)))
+
+#define WORDNO(p, base) ((((char*)(p))-((char*)(base)))/sizeof(u_char*))
+#define FIXUP(p) (fixup[WORDNO(p,buffer)/8] |= (1<<(WORDNO(p, buffer) & 7)))
+
+#define IS_FIXUP(p) ((fixup[WORDNO(p,buffer)/8] & (1<<(WORDNO(p, buffer) & 7))) != 0)
+
+#define FIXUP_VALS(vals) do {						\
+	int i;								\
+	for (i=0; i < MAX_HUFFCODE_LEN+1; ++i)				\
+	  FIXUP(&vals[i]);						\
+      } while(0)
+
+
+
+static u_long mem_for_comp_dict (char *filename);
+static void load_comp_dict (char *filename);
+static void save_fast_dict (char *filename);
+static void unfixup_buffer (void);
+
+
+static void *buffer;
+static void *cur;
+static u_char *fixup;
+static u_long mem, fixup_mem;
+
+int main (int argc, char **argv)
+{
+  int ch;
+  char *filename = "";
+  opterr = 0;
+  msg_prefix = argv[0];
+  while ((ch = getopt (argc, argv, "f:d:h")) != -1)
+    switch (ch)
+      {
+      case 'f':		/* input file */
+	filename = optarg;
+	break;
+      case 'd':
+	set_basepath (optarg);
+	break;
+      case 'h':
+      case '?':
+	fprintf (stderr, "usage: %s [-f input_file] [-d data directory] [-h]\n",
+		 argv[0]);
+	exit (1);
+      }
+
+  mem = mem_for_comp_dict (filename);
+
+  fixup_mem = (ALIGN_SIZE (mem, u_char *) / sizeof (u_char *) + 7) / 8;
+
+  cur = buffer = Xmalloc (mem);
+  memset (buffer, 0, mem);
+  fixup = (u_char *) Xmalloc (fixup_mem);
+  memset (fixup, 0, fixup_mem);
+
+#ifndef SILENT
+  Message ("Estimated memory for fast_dict %u", mem);
+  Message ("Estimated memory for fixups %u", fixup_mem);
+#endif
+
+  load_comp_dict (filename);
+
+#ifndef SILENT
+  Message ("Actual memory for fast_dict %u", (char *) cur - (char *) buffer);
+#endif
+
+  if ((u_long) cur > (u_long) buffer + mem)
+    FatalError (1, "The buffer was not big enough for the dictionary");
+
+  {
+    /* [RPAP - Jan 97: Endian Ordering] */
+    compression_dict *cd = (compression_dict *) buffer;
+    int i, which;
+
+    /* cfh */
+    for (which = 0; which <= 1; ++which)
+      {
+	int j;
+	
+	HTONSI(cd->cfh[which]->hd.num_codes);
+	HTONSI(cd->cfh[which]->hd.mincodelen);
+	HTONSI(cd->cfh[which]->hd.maxcodelen);
+	for (j = 0; j < MAX_HUFFCODE_LEN + 1; ++j)
+	  {
+	    HTONSI(cd->cfh[which]->hd.lencount[j]);
+	    HTONUL(cd->cfh[which]->hd.min_code[j]);
+	  }
+	HTONUL(cd->cfh[which]->uncompressed_size);
+	for (j = 0; j < MAX_HUFFCODE_LEN + 1; ++j)
+	  HTONUL(cd->cfh[which]->huff_words_size[j]);
+      }
+    HTONUL(cd->MemForCompDict);
+    /* ad */
+    if (cd->cdh.novel_method == MG_NOVEL_DELTA ||
+	cd->cdh.novel_method == MG_NOVEL_HYBRID)
+      for (which = 0; which <= 1; ++which)
+	{
+	  int j;
+	  
+	  HTONUL(cd->ad->afh[which].num_frags);
+	  HTONUL(cd->ad->afh[which].mem_for_frags);
+	  for (j = 0; j < 33; ++j)
+	    {
+	      HTONSI(cd->ad->blk_start[which][j]);
+	      HTONSI(cd->ad->blk_end[which][j]);
+	    }
+	}
+    /* cdh */
+    HTONUL(cd->cdh.dict_type);
+    HTONUL(cd->cdh.novel_method);
+    for (i = 0; i < TEXT_PARAMS; ++i)
+      HTONUL(cd->cdh.params[which]);
+    HTONUL(cd->cdh.num_words[0]);
+    HTONUL(cd->cdh.num_words[1]);
+    HTONUL(cd->cdh.num_word_chars[0]);
+    HTONUL(cd->cdh.num_word_chars[1]);
+    HTONUL(cd->cdh.lookback);
+    HTONSI(cd->fast_loaded);
+  }
+
+  unfixup_buffer ();
+
+  save_fast_dict (filename);
+
+  return (0);
+}
+
+
+
+static void 
+unfixup_buffer ()
+{
+  u_long *p;
+  for (p = (u_long *) buffer; (u_long) p < (u_long) cur; ++p)
+    {
+      if (IS_FIXUP (p))
+	*p = *p - (u_long) buffer;
+    }
+}
+
+
+
+
+static u_long 
+mem_for_aux_dict (compression_dict_header * /*cdh*/, char *filename)
+{
+  int i;
+  u_long mem = sizeof (auxiliary_dict);
+  FILE *aux;
+
+  aux = open_file (filename, TEXT_DICT_AUX_SUFFIX, "rb",
+		   MAGIC_AUX_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  for (i = 0; i <= 1; ++i)
+    {
+      aux_frags_header afh;
+      fread (&afh, sizeof (afh), 1, aux);
+      NTOHUL(afh.num_frags);  /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(afh.mem_for_frags);  /* [RPAP - Jan 97: Endian Ordering] */
+      mem += afh.num_frags * sizeof (u_char *);
+      mem = ALIGN_SIZE (mem + afh.mem_for_frags, u_char *);
+      fseek (aux, afh.mem_for_frags, SEEK_CUR);
+    }
+  fclose (aux);
+
+  return mem;
+}
+
+
+
+static u_long 
+mem_for_words (FILE * dict, compression_dict_header * cdh,
+	       comp_frags_header * cfh)
+{
+  u_long mem = 0;
+  long i, lookback;
+  int ptrs_reqd = 0;
+  int mem_reqd = 0;
+
+  lookback = cdh->lookback;
+
+  for (i = cfh->hd.mincodelen; i <= cfh->hd.maxcodelen; ++i)
+    {
+      ptrs_reqd += (cfh->hd.lencount[i] + ((1 << lookback) - 1)) >> lookback;
+      mem_reqd += cfh->huff_words_size[i];
+    }
+
+  mem += ptrs_reqd * sizeof (u_char *);
+  mem += (MAX_HUFFCODE_LEN + 1) * sizeof (u_char **);
+  mem += mem_reqd;
+
+  for (i = 0; i < cfh->hd.num_codes; ++i)
+    {
+      register int val;
+      for (val = getc (dict) & 0xf; val; --val)
+	getc (dict);
+    }
+  return ALIGN_SIZE (mem, u_char *);
+}
+
+static u_long mem_skip_hd(FILE *dict, u_long mem)
+{ huff_data hd;
+
+  mem += sizeof (hd);
+  Read_Huffman_Data (dict, &hd, NULL, NULL);
+  if (hd.clens)
+    delete []hd.clens;
+  mem += hd.num_codes * sizeof (unsigned long);
+  mem += (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *);
+  return mem;
+}
+
+static u_long mem_read_cfh(FILE *dict, compression_dict_header *cdh, comp_frags_header *cfh, 
+			   u_long mem)
+{
+  mem += sizeof (comp_frags_header);
+  Read_cfh (dict, cfh, NULL, NULL);
+
+  /* Don't need to count the space for the clens of the huffman data */
+
+  mem += mem_for_words (dict, cdh, cfh);
+  if (cfh->hd.clens)
+    delete []cfh->hd.clens;
+
+  return mem;
+}
+
+
+static u_long 
+mem_for_comp_dict (char *filename)
+{
+  u_long mem = sizeof (compression_dict);
+  compression_dict_header cdh;
+  comp_frags_header cfh;
+  FILE *dict;
+  int which;
+  int i;  /* [RPAP - Jan 97: Endian Ordering] */
+
+  dict = open_file (filename, TEXT_DICT_SUFFIX, "rb",
+		    MAGIC_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  fread (&cdh, sizeof (cdh), 1, dict);
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(cdh.dict_type);
+  NTOHUL(cdh.novel_method);
+  for (i = 0; i < TEXT_PARAMS; ++i)
+    NTOHUL(cdh.params[i]);
+  NTOHUL(cdh.num_words[0]);
+  NTOHUL(cdh.num_words[1]);
+  NTOHUL(cdh.num_word_chars[0]);
+  NTOHUL(cdh.num_word_chars[1]);
+  NTOHUL(cdh.lookback);
+
+  for (which = 0; which < 2; ++which)
+    switch (cdh.dict_type)
+      {
+      case MG_COMPLETE_DICTIONARY:
+	{
+	  mem = mem_read_cfh(dict, &cdh, &cfh, mem);
+	}
+	break;
+      case MG_PARTIAL_DICTIONARY:
+	{
+	  // huff_data hd;
+	  if (cdh.num_words[which])
+	    {
+	      mem = mem_read_cfh(dict, &cdh, &cfh, mem);
+	    }
+
+	  mem = mem_skip_hd(dict, mem);
+	  mem = mem_skip_hd(dict, mem);
+	}
+	break;
+      case MG_SEED_DICTIONARY:
+	{
+	  // huff_data hd;
+	  if (cdh.num_words[which])
+	    {
+	      mem = mem_read_cfh(dict, &cdh, &cfh, mem);
+	    }
+	  switch (cdh.novel_method)
+	    {
+	    case MG_NOVEL_HUFFMAN_CHARS:
+	      mem = mem_skip_hd(dict, mem);
+	      mem = mem_skip_hd(dict, mem);
+	      break;
+	    case MG_NOVEL_DELTA:
+	      break;
+	    case MG_NOVEL_HYBRID:
+	      break;
+	    }
+	  break;
+	}
+      }
+  fclose (dict);
+
+  if (cdh.novel_method == MG_NOVEL_DELTA ||
+      cdh.novel_method == MG_NOVEL_HYBRID)
+    mem += mem_for_aux_dict (&cdh, filename);
+
+  return ALIGN_SIZE (mem, u_char *);
+}
+
+
+
+void *
+getmem (u_long size, int align)
+{
+  void *res;
+  cur = (void *) (((u_long) cur + (align - 1)) & (~(align - 1)));
+  res = cur;
+  cur = (char *) cur + size;
+  if ((u_long) cur > (u_long)buffer + mem)
+    FatalError (1, "The buffer was not big enough for the dictionary");
+  return res;
+}
+
+
+
+
+
+
+
+
+
+
+
+static auxiliary_dict *
+LoadAuxDict (compression_dict_header * cdh,
+	     char *filename)
+{
+  auxiliary_dict *ad;
+  int i;
+  FILE *aux;
+
+  aux = open_file (filename, TEXT_DICT_AUX_SUFFIX, "rb",
+		   MAGIC_AUX_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  ad = (auxiliary_dict *) getmem (sizeof (auxiliary_dict), sizeof (u_char *));
+
+  for (i = 0; i <= 1; ++i)
+    {
+      unsigned int j;
+      u_char *pos;
+
+      fread (&ad->afh[i], sizeof (aux_frags_header), 1, aux);
+
+      /* [RPAP - Jan 97: Endian Ordering] */
+      NTOHUL(ad->afh[i].num_frags);
+      NTOHUL(ad->afh[i].mem_for_frags);
+
+      ad->word_data[i] = (u_char *) getmem (ad->afh[i].mem_for_frags, 1);
+      FIXUP (&ad->word_data[i]);
+
+      ad->words[i] = (u_char **) getmem (ad->afh[i].num_frags * sizeof (u_char *),
+			     sizeof (u_char *));
+      FIXUP (&ad->words[i]);
+
+      fread (ad->word_data[i], ad->afh[i].mem_for_frags, sizeof (u_char), aux);
+
+      pos = ad->word_data[i];
+      for (j = 0; j < ad->afh[i].num_frags; ++j)
+	{
+	  ad->words[i][j] = pos;
+	  FIXUP (&ad->words[i][j]);
+	  pos += *pos + 1;
+	}
+      if (cdh->novel_method == MG_NOVEL_HYBRID)
+	{
+	  int num;
+	  num = 1;
+	  ad->blk_start[i][0] = 0;
+	  ad->blk_end[i][0] = cdh->num_words[i] - 1;
+	  while (num < 33)
+	    {
+	      ad->blk_start[i][num] = ad->blk_end[i][num - 1] + 1;
+	      ad->blk_end[i][num] = ad->blk_start[i][num] +
+		(ad->blk_end[i][num - 1] - ad->blk_start[i][num - 1]) * 2;
+	      ++num;
+	    }
+	}
+    }
+  fclose (aux);
+  return (ad);
+}
+
+
+
+
+
+static u_char ***
+ReadInWords (FILE * dict, compression_dict * cd,
+	     comp_frags_header * cfh, u_char ** escape)
+{
+  int i, lookback;
+  int ptrs_reqd = 0;
+  int mem_reqd = 0;
+  int num_set[MAX_HUFFCODE_LEN + 1];
+  u_char *next_word[MAX_HUFFCODE_LEN + 1];
+  u_char **vals;
+  u_char ***values;
+  u_char word[MAXWORDLEN + 1];
+  u_char last_word[MAX_HUFFCODE_LEN + 1][MAXWORDLEN + 1];
+
+  lookback = cd->cdh.lookback;
+
+  for (i = cfh->hd.mincodelen; i <= cfh->hd.maxcodelen; ++i)
+    {
+      ptrs_reqd += (cfh->hd.lencount[i] + ((1 << lookback) - 1)) >> lookback;
+      mem_reqd += cfh->huff_words_size[i];
+    }
+
+  vals = (u_char **) getmem (ptrs_reqd * sizeof (*vals), sizeof (u_char *));
+
+  values = (u_char ***) getmem ((MAX_HUFFCODE_LEN + 1) * sizeof (u_char **), sizeof (u_char **));
+
+  next_word[0] = (u_char *) getmem (mem_reqd, sizeof (char));
+
+  cd->MemForCompDict += ptrs_reqd * sizeof (*vals) +
+    (MAX_HUFFCODE_LEN + 1) * sizeof (u_char **) +
+    mem_reqd;
+
+  values[0] = vals;
+  FIXUP (&values[0]);
+  values[0][0] = next_word[0];
+  FIXUP (&values[0][0]);
+  for (i = 1; i <= cfh->hd.maxcodelen; ++i)
+    {
+      int next_start = (values[i - 1] - vals) +
+      ((cfh->hd.lencount[i - 1] + ((1 << lookback) - 1)) >> lookback);
+      values[i] = &vals[next_start];
+      FIXUP (&values[i]);
+      next_word[i] = next_word[i - 1] + cfh->huff_words_size[i - 1];
+      values[i][0] = next_word[i];
+      FIXUP (&values[i][0]);
+    }
+
+  memset (num_set, '\0', sizeof (num_set));
+
+  for (i = 0; i < cfh->hd.num_codes; ++i)
+    {
+      register int val, copy;
+      register int len = cfh->hd.clens[i];
+      val = getc (dict);
+      copy = (val >> 4) & 0xf;
+      val &= 0xf;
+
+      fread (word + copy + 1, sizeof (u_char), val, dict);
+      *word = val + copy;
+
+      if ((num_set[len] & ((1 << lookback) - 1)) == 0)
+	{
+	  values[len][num_set[len] >> lookback] = next_word[len];
+	  FIXUP (&values[len][num_set[len] >> lookback]);
+	  memcpy (next_word[len], word, *word + 1);
+	  if (escape && i == cfh->hd.num_codes - 1)
+	    {
+	      *escape = next_word[len];
+	      FIXUP (escape);
+	    }
+	  next_word[len] += *word + 1;
+	}
+      else
+	{
+	  copy = prefixlen (last_word[len], word);
+	  memcpy (next_word[len] + 1, word + copy + 1, *word - copy);
+	  *next_word[len] = (copy << 4) + (*word - copy);
+	  if (escape && i == cfh->hd.num_codes - 1)
+	    {
+	      *escape = next_word[len];
+	      FIXUP (escape);
+	    }
+	  next_word[len] += (*word - copy) + 1;
+	}
+      memcpy (last_word[len], word, *word + 1);
+      ++num_set[len];
+    }
+  if (cfh->hd.clens)
+    delete []cfh->hd.clens;
+  cfh->hd.clens = NULL;
+  return values;
+}
+
+
+static unsigned long **
+Generate_Fast_Huffman_Vals (huff_data * data, u_long * mem)
+{
+  int i;
+  unsigned long *fcode[MAX_HUFFCODE_LEN + 1];
+  unsigned long **values;
+  unsigned long *vals;
+
+  if (!data)
+    return (NULL);
+  vals = (unsigned long *) getmem (data->num_codes * sizeof (*vals), sizeof (long *));
+  values = (unsigned long **) getmem ((MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *),
+		   sizeof (long *));
+
+  memset (values, '\0', (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *));
+
+  if (mem)
+    *mem += data->num_codes * sizeof (*vals) +
+      (MAX_HUFFCODE_LEN + 1) * sizeof (unsigned long *);
+
+  fcode[0] = values[0] = &vals[0];
+  FIXUP (&values[0]);
+  for (i = 1; i <= data->maxcodelen; ++i)
+    {
+      fcode[i] = values[i] = &vals[(values[i - 1] - vals) + data->lencount[i - 1]];
+      FIXUP (&values[i]);
+    }
+
+  for (i = 0; i < data->num_codes; ++i)
+    if (data->clens[i])
+      *fcode[(int) (data->clens[i])]++ = i;
+  return (values);
+}
+
+
+static void load_read_huffman(FILE *dict, compression_dict *cd, int which)
+{
+  huff_data *hd;
+  u_long   **vals;
+
+  hd = (huff_data *) getmem (sizeof (huff_data), sizeof (char *));
+  cd->MemForCompDict += sizeof (huff_data);
+  Read_Huffman_Data (dict, hd, &cd->MemForCompDict, NULL);
+  vals = Generate_Fast_Huffman_Vals (hd, &cd->MemForCompDict);
+  cd->chars_huff[which] = hd;
+  FIXUP (&cd->chars_huff[which]);
+  cd->chars_vals[which] = vals;
+  FIXUP (&cd->chars_vals[which]);
+  if (hd->clens)
+    delete []hd->clens;
+  hd->clens = NULL;
+}
+
+static void load_read_words(FILE *dict, compression_dict *cd, int which, int fixescape)
+{
+  cd->cfh[which] = (comp_frags_header *) getmem (sizeof (*cd->cfh[which]), sizeof (u_char *));
+  cd->MemForCompDict += sizeof (*cd->cfh[which]);
+  Read_cfh (dict, cd->cfh[which], &cd->MemForCompDict, NULL);
+
+  cd->values[which] = ReadInWords (dict, cd, cd->cfh[which], NULL);
+  FIXUP (&cd->cfh[which]);
+  FIXUP (&cd->values[which]);
+  if (fixescape)
+    { FIXUP(&cd->escape[which]);
+    }
+  else
+    {
+      cd->escape[which] = NULL;
+    }
+}
+
+static void 
+load_comp_dict (char *filename)
+{
+  FILE *dict;
+  int which;
+  compression_dict *cd;
+
+  cd = (compression_dict *) getmem (sizeof (compression_dict), sizeof (u_char *));
+  cd->fast_loaded = 1;
+
+  dict = open_file (filename, TEXT_DICT_SUFFIX, "rb",
+		    MAGIC_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  Read_cdh (dict, &cd->cdh, NULL, NULL);
+
+  for (which = 0; which < 2; ++which)
+    switch (cd->cdh.dict_type)
+      {
+      case MG_COMPLETE_DICTIONARY:
+	{
+	  load_read_words(dict, cd, which, 0);
+	}
+	break;
+      case MG_PARTIAL_DICTIONARY:
+	{
+	  if (cd->cdh.num_words[which])
+	    {
+	      load_read_words(dict, cd, which, 1);
+	    }
+
+	  load_read_huffman(dict, cd, which);
+	  load_read_huffman(dict, cd, which);
+	}
+	break;
+      case MG_SEED_DICTIONARY:
+	{
+	  if (cd->cdh.num_words[which])
+	    {
+	      load_read_words(dict, cd, which, 1);
+	    }
+	  switch (cd->cdh.novel_method)
+	    {
+	    case MG_NOVEL_HUFFMAN_CHARS:
+	      load_read_huffman(dict, cd, which);
+	      load_read_huffman(dict, cd, which);
+	      break;
+	    case MG_NOVEL_DELTA:
+	      break;
+	    case MG_NOVEL_HYBRID:
+	      break;
+	    }
+	  break;
+	}
+      }
+  fclose (dict);
+
+
+  if (cd->cdh.novel_method == MG_NOVEL_DELTA ||
+      cd->cdh.novel_method == MG_NOVEL_HYBRID)
+    {
+      cd->ad = LoadAuxDict (&cd->cdh, filename);
+      FIXUP (&cd->ad);
+    }
+}
+
+static void 
+save_fast_dict (char *filename)
+{
+  FILE *fdict;
+
+  fdict = create_file (filename, TEXT_DICT_FAST_SUFFIX, "wb",
+		       MAGIC_FAST_DICT, MG_ABORT);  /* [RPAP - Feb 97: WIN32 Port] */
+
+  {
+    u_long *p;
+    for (p = (u_long *) buffer; (u_long) p < (u_long) cur; ++p)
+      {
+	if (IS_FIXUP (p))
+	  HTONUL(*p);
+      }
+  }
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(mem);
+  HTONUL(fixup_mem);
+
+  fwrite (&mem, sizeof (mem), 1, fdict);
+  fwrite (&fixup_mem, sizeof (fixup_mem), 1, fdict);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(mem);
+  NTOHUL(fixup_mem);
+
+  fwrite (buffer, sizeof (u_char), mem, fdict);
+  fwrite (fixup, sizeof (u_char), fixup_mem, fdict);
+
+  fclose (fdict);
+}
Index: /indexers/branches/3.03a/mgpp/text/mgpp_invf_dict.1
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_invf_dict.1	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_invf_dict.1	(revision 14757)
@@ -0,0 +1,79 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.\"------------------------------------------------------------
+.TH mgpp_invf_dict 1 \*(Dt CITRI
+.SH NAME
+mgpp_invf_dict \- build an `on-disk' stemmed dictionary
+.SH SYNOPSIS
+.B mgpp_invf_dict
+[
+.B \-h
+]
+[
+.BI \-b " entries-per-block"
+]
+.if n .ti +13n
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mgpp_invf_dict
+builds an `on-disk' stemmed dictionary from the
+compressed stemmed dictionary that can be used during querying.
+Each entry in the dictionary contains the disk
+pointer to the associated inverted file entry, and various other pieces
+of information about the stemmed word. The dictionary is blocked with
+each block containing the same number of entries (not the same size).
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectoryyyyyyyy\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-b " entries-per-block"
+The dictionary is stored in blocks on disk; this option is used to 
+specify the number of entries per block. The default is 16.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the mgpp
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.dict
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict.blocked
+The `on-disk' stemmed dictionary.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.SH "SEE ALSO"
+.na
+.BR mgpp_compression_dict (1),
+.BR mgpp_fast_comp_dict (1),
+.BR mgpp_passes (1),
+.BR mgpp_perf_hash_build (1),
+.BR mgpp_stem_idx (1),
+.BR mgpp_weights_build (1)
Index: /indexers/branches/3.03a/mgpp/text/mgpp_invf_dict.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_invf_dict.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_invf_dict.cpp	(revision 14757)
@@ -0,0 +1,237 @@
+/**************************************************************************
+ *
+ * mgpp_invf_dict.cpp -- Program to build the blocked stemmed dictionary
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+/* getopt is in posix.2, so cygwin should have it in unistd, but doesn't */
+#if defined (__WIN32__) || defined (__CYGWIN__)
+# include "getopt_old.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "sysfuncs.h"
+#include "messages.h"
+#include "mg_files.h"
+#include "invf.h"
+
+static void process_files (char *filename, unsigned long entriesPerBlock) {
+  // open the dictionary
+  FILE *dictFile = open_file (filename, INVF_DICT_SUFFIX, "rb",
+			      MAGIC_STEM_BUILD, MG_ABORT);
+  invf_dict_header idh;
+  idh.Read (dictFile);
+
+  // open the inverted index file
+  FILE *invfIdxFile = open_file (filename, INVF_IDX_SUFFIX, "rb",
+				 MAGIC_INVI, MG_ABORT);
+
+  // create the blocked dictionary
+  FILE *blockDictFile = create_file (filename, INVF_DICT_BLOCKED_SUFFIX, "wb",
+				     MAGIC_STEM, MG_ABORT);
+  block_dict_header bdh;
+  bdh.lookback = idh.lookback;
+  bdh.word_dict_start = idh.word_dict_start;
+  bdh.word_dict_size = idh.word_dict_size;
+  bdh.tag_dict_start = idh.tag_dict_start;
+  bdh.tag_dict_size = idh.tag_dict_size;
+  bdh.num_docs = idh.num_docs;
+  bdh.num_frags = idh.num_frags;
+  bdh.num_words = idh.num_words;
+  bdh.total_bytes = idh.total_bytes;
+  bdh.index_string_bytes = idh.index_string_bytes;
+  bdh.num_levels = idh.num_levels;
+  bdh.Write (blockDictFile);
+
+  
+  // write out the word part of the dictionary
+
+  bdh.entries_per_wblk = entriesPerBlock;
+  bdh.max_wblk_size = 0;
+  bdh.wblk_start = ftell (blockDictFile);
+  
+  fseek (dictFile, idh.word_dict_start, SEEK_SET);
+
+  block_idx wordIdx;
+  word_block_dict_el wordBlockEl;
+  wordBlockEl.SetNumLevels (idh.num_levels);
+  
+  
+  unsigned long wordNum;
+  unsigned long wordInvfPtr;
+  UCArray lastEl;
+  word_dict_el wordEl;
+  wordEl.SetNumLevels (idh.num_levels);
+  for (wordNum=0; wordNum<idh.word_dict_size; ++wordNum) {
+    // read in the next word and inverted file pointer
+    wordEl.Read (dictFile, idh.num_levels);
+    ReadUL (invfIdxFile, wordInvfPtr);
+
+    // remember this word (and position) if this is the start
+    // of a new block
+    if (wordNum % entriesPerBlock == 0) {
+      block_idx_info elIdx;
+      elIdx.el = wordEl.el;
+      elIdx.block_ptr = ftell (blockDictFile);
+
+      // see if this block is the longest so far
+      if (wordIdx.size() > 0) {
+	unsigned long blockLen = elIdx.block_ptr -
+	  (*(wordIdx.end()-1)).block_ptr;
+	if (blockLen > bdh.max_wblk_size) bdh.max_wblk_size = blockLen;
+      }
+      
+      wordIdx.push_back (elIdx);
+      lastEl.erase (lastEl.begin(), lastEl.end()); // output full word
+    }
+
+    // copy the information for this word
+    wordBlockEl.el = wordEl.el;
+    wordBlockEl.frag_occur = wordEl.frag_occur;
+    wordBlockEl.freq = wordEl.freq;
+    wordBlockEl.invf_ptr = wordInvfPtr;
+    unsigned long tempI;
+    for (tempI=0; tempI<idh.num_levels; ++tempI)
+      wordBlockEl.levelFreqs[tempI] = wordEl.levelFreqs[tempI];
+
+    // write out the word
+    wordBlockEl.Write (blockDictFile, &lastEl, idh.num_levels);
+
+    lastEl = wordBlockEl.el;
+  }
+
+
+  // write out the tag part of the dictionary
+
+  bdh.entries_per_tblk = entriesPerBlock;
+  bdh.max_tblk_size = 0;
+  bdh.tblk_start = ftell (blockDictFile);
+  
+  fseek (dictFile, idh.tag_dict_start, SEEK_SET);
+
+  block_idx tagIdx;
+  block_dict_el tagBlockEl;
+  
+  unsigned long tagNum;
+  unsigned long tagInvfPtr;
+  dict_el tagEl;
+  lastEl.erase (lastEl.begin(), lastEl.end());
+  for (tagNum=0; tagNum<idh.tag_dict_size; ++tagNum) {
+    // read in the next tag and inverted file pointer
+    tagEl.Read (dictFile);
+    ReadUL (invfIdxFile, tagInvfPtr);
+
+    // remember this tag (and position) if this is the start
+    // of a new block
+    if (tagNum % entriesPerBlock == 0) {
+      block_idx_info elIdx;
+      elIdx.el = tagEl.el;
+      elIdx.block_ptr = ftell (blockDictFile);
+
+      // see if this block is the longest so far
+      if (tagIdx.size() > 0) {
+	unsigned long blockLen = elIdx.block_ptr -
+	  (*(tagIdx.end()-1)).block_ptr;
+	if (blockLen > bdh.max_tblk_size) bdh.max_tblk_size = blockLen;
+      }
+      
+      tagIdx.push_back (elIdx);
+      lastEl.erase (lastEl.begin(), lastEl.end()); // output full word
+    }
+
+    // copy the information for this tag
+    tagBlockEl.el = tagEl.el;
+    tagBlockEl.frag_occur = tagEl.frag_occur;
+    tagBlockEl.freq = tagEl.freq;
+    tagBlockEl.invf_ptr = tagInvfPtr;
+
+    // write out the tag
+    tagBlockEl.Write (blockDictFile, &lastEl);
+
+    lastEl = tagBlockEl.el;
+  }
+
+
+  // write out the element indexes
+  bdh.num_wblks = wordIdx.size();
+  bdh.wblk_idx_start = ftell (blockDictFile);
+  WriteBlockIdx (blockDictFile, wordIdx);
+  
+  bdh.num_tblks = tagIdx.size();
+  bdh.tblk_idx_start = ftell (blockDictFile);
+  WriteBlockIdx (blockDictFile, tagIdx);
+
+  // write out the blocked dictionary header
+  fseek (blockDictFile, sizeof(unsigned long), SEEK_SET);
+  bdh.Write (blockDictFile);
+
+
+  // close open files
+  fclose (blockDictFile);
+  fclose (invfIdxFile);
+  fclose (dictFile);
+  
+  // print out information
+#ifndef SILENT
+  Message ("Max word block size = %d\n", bdh.max_wblk_size);
+  Message ("Max tag block size = %d\n", bdh.max_tblk_size);
+  Message ("Number of word blocks written = %d\n", bdh.num_wblks);
+  Message ("Number of tag blocks written = %d\n", bdh.num_tblks);
+#endif
+}
+
+
+int main (int argc, char **argv) {
+  unsigned long entriesPerBlock = 16;
+  char *filename = "";
+  int ch;
+  msg_prefix = argv[0];
+  opterr = 0;
+
+  while ((ch = getopt (argc, argv, "f:d:b:h")) != -1) {
+    switch (ch) {
+    case 'f':		// input file
+      filename = optarg;
+      break;
+    case 'd':
+      set_basepath (optarg);
+      break;
+    case 'b':
+      entriesPerBlock = atoi (optarg);
+      break;
+    case 'h':
+    case '?':
+      fprintf (stderr, "usage: %s [-f input_file] "
+	       "[-d data directory] [-b entries-per-block] "
+	       "[-h]\n", argv[0]);
+      exit (1);
+    }
+  }
+
+  process_files (filename, entriesPerBlock);
+  return 0;
+}
Index: /indexers/branches/3.03a/mgpp/text/mgpp_invf_dict_dump.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_invf_dict_dump.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_invf_dict_dump.cpp	(revision 14757)
@@ -0,0 +1,141 @@
+/**************************************************************************
+ *
+ * mgpp_invf_dict_dump.cpp -- Program to printthe various inverted dictionaries
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+/* getopt is in posix.2, so cygwin should have it in unistd, but doesn't */
+#if defined (__WIN32__) || defined (__CYGWIN__)
+# include "getopt_old.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "sysfuncs.h"
+#include "messages.h"
+#include "mg_files.h"
+#include "invf.h"
+
+static void process_files (char *filename,
+			   bool printHeader,
+			   bool printWords,
+			   bool printTags) {
+  // open the dictionary
+  FILE *dictFile = open_file (filename, INVF_DICT_SUFFIX, "rb",
+			      MAGIC_STEM_BUILD, MG_ABORT);
+  invf_dict_header idh;
+  idh.Read (dictFile);
+
+  // print the information from the inverted dictionary file header
+  if (printHeader) {
+    cout << "lookback: " << idh.lookback << "\n";
+    cout << "word_dict_start: " << idh.word_dict_start << "\n";
+    cout << "word_dict_size: " << idh.word_dict_size << "\n";
+    cout << "tag_dict_start: " << idh.tag_dict_start << "\n";
+    cout << "tag_dict_size: " << idh.tag_dict_size << "\n";
+    cout << "num_docs: " << idh.num_docs << "\n";
+    cout << "num_frags: " << idh.num_frags << "\n";
+    cout << "num_words: " << idh.num_words << "\n";
+    cout << "total_bytes: " << idh.total_bytes << "\n";
+    cout << "index_string_bytes: " << idh.index_string_bytes << "\n";
+    cout << "num_levels: " << idh.num_levels << "\n";
+
+    cout << "\n";
+  }
+
+
+  if (printWords) {
+    fseek (dictFile, idh.word_dict_start, SEEK_SET);
+    
+    unsigned long wordNum;
+    word_dict_el wordEl;
+    wordEl.SetNumLevels (idh.num_levels);
+    for (wordNum=0; wordNum<idh.word_dict_size; ++wordNum) {
+      wordEl.Read (dictFile, idh.num_levels);
+      cout << "\"" << wordEl.el << "\"\n";// (" << wordNum << ")\n";
+    }
+    
+    cout << "\n";
+  }
+
+  // write out the tag part of the dictionary
+  if (printTags) {
+    fseek (dictFile, idh.tag_dict_start, SEEK_SET);
+    
+    unsigned long tagNum;
+    dict_el tagEl;
+    for (tagNum=0; tagNum<idh.tag_dict_size; ++tagNum) {
+      // read in the next tag and inverted file pointer
+      tagEl.Read (dictFile);
+      
+      cout << "\"" << tagEl.el << "\" (" << tagNum << ")\n";
+    }
+  }
+  
+  // close open files
+  fclose (dictFile);
+}
+
+
+int main (int argc, char **argv) {
+  char *filename = "";
+  int ch;
+  msg_prefix = argv[0];
+  opterr = 0;
+
+  bool printHeader = false;
+  bool printWords = false;
+  bool printTags = false;
+
+  while ((ch = getopt (argc, argv, "f:d:rwth")) != -1) {
+    switch (ch) {
+    case 'f':		// input file
+      filename = optarg;
+      break;
+    case 'd':
+      set_basepath (optarg);
+      break;
+    case 'r':
+      printHeader = true;
+      break;
+    case 'w':
+      printWords = true;
+      break;
+    case 't':
+      printTags = true;
+      break;
+    case 'h':
+    case '?':
+      fprintf (stderr, "usage: %s [-h] [-r] [-w] [-t] [-f input_file] "
+	       "[-d data directory]\n(-rwt:print header, words, tags)\n", 
+	       argv[0]);
+      exit (1);
+    }
+  }
+
+  process_files (filename, printHeader, printWords, printTags);
+  return 0;
+}
Index: /indexers/branches/3.03a/mgpp/text/mgpp_invf_dump.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_invf_dump.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_invf_dump.cpp	(revision 14757)
@@ -0,0 +1,244 @@
+/**************************************************************************
+ *
+ * mgpp_invf_dump.cpp -- Program to dump uot an inverted fil
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+/* getopt is in posix.2, so cygwin should have it in unistd, but doesn't */
+#if defined (__WIN32__) || defined (__CYGWIN__)
+# include "getopt_old.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "sysfuncs.h"
+#include "messages.h"
+#include "bitio_m_stdio.h"
+#include "bitio_gen.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+
+#include "mg_files.h"
+#include "locallib.h"
+#include "words.h"
+#include "invf.h"
+#include "WordData.h"
+
+static void PrintInvfWord (FILE *invfFile,
+			   invf_dict_header &idh,
+			   invf_file_header &ifh,
+			   word_dict_el &wordEl,
+			   unsigned long wordStart,
+			   bool printFrags) {
+  cout << wordEl.frag_occur << " \"" << wordEl.el << "\"\n";
+  
+  if (printFrags) {
+    // seek to the appropriate place in the inverted file
+    fseek (invfFile, wordStart, SEEK_SET);
+    
+    stdio_bitio_buffer buffer(invfFile);
+    
+    unsigned long B = BIO_Bblock_Init (idh.num_frags, wordEl.frag_occur);
+    unsigned long fragNum = 0;
+    unsigned long i;
+    for (i=0; i<wordEl.frag_occur; ++i) {
+      unsigned long delta = buffer.bblock_decode (B, NULL);
+      fragNum += delta;
+      cout << " " << fragNum;
+      
+      if (!ifh.word_level_index ) {
+	unsigned long count = buffer.gamma_decode (NULL);
+	cout << "(" << count << ")";
+      } else {
+	cout << "(1)";
+      }
+    }
+    
+    cout << "\n";
+  
+    buffer.done();
+  }
+}
+
+static void PrintInvfTag (FILE *invfFile,
+			  invf_dict_header &idh,
+			  invf_file_header &/*ifh*/,
+			  dict_el &tagEl,
+			  unsigned long tagStart,
+			  bool printFrags) {
+  cout << tagEl.frag_occur << " \"<" << tagEl.el << ">\"\n";
+  
+  if (printFrags) {
+    // seek to the appropriate place in the inverted file
+    fseek (invfFile, tagStart, SEEK_SET);
+    
+    stdio_bitio_buffer buffer(invfFile);
+    
+    unsigned long pTag = tagEl.frag_occur*2;
+    unsigned long B = BIO_Bblock_Init (idh.num_frags+pTag, pTag);
+    unsigned long fragNum = 0;
+    unsigned long i;
+    for (i=0; i<tagEl.frag_occur; ++i) {
+      unsigned long delta = buffer.bblock_decode (B, NULL)-1;
+      fragNum += delta;
+      cout << " " << fragNum;
+      cout << "-";
+      delta = buffer.bblock_decode (B, NULL)-1;
+      fragNum += delta;
+      cout << fragNum;
+    }
+    
+    cout << "\n";
+    
+    buffer.done();
+  }
+}
+
+static void PrintHeaderInfo (invf_dict_header &idh,
+			     invf_file_header &ifh) {
+  cerr << "Lookback:         " << idh.lookback << "\n";
+  cerr << "Word Dict Size:   " << idh.word_dict_size << "\n";
+  cerr << "Tag Dict Size:    " << idh.tag_dict_size << "\n";
+  cerr << "Num Documents:    " << idh.num_docs << "\n";
+  cerr << "Num Fragments:    " << idh.num_frags << "\n";
+  cerr << "Num Words:        " << idh.num_words << "\n";
+
+  cerr << "Skip Mode:        " << ifh.skip_mode << "\n";
+  cerr << "Word Level Index: " << ifh.word_level_index << "\n";
+
+  cerr << "\n";
+}
+
+
+static void process_files (char *filename,
+			   bool printHeader,
+			   bool printWords,
+			   bool printTags,
+			   bool printFrags) {
+  // open the dictionary
+  FILE *dictFile = open_file (filename, INVF_DICT_SUFFIX, "rb",
+			MAGIC_STEM_BUILD, MG_ABORT);
+  invf_dict_header idh;
+  idh.Read (dictFile);
+
+  // open the inverted file
+  FILE *invfFile = open_file (filename, INVF_SUFFIX, "rb",
+			MAGIC_INVF, MG_ABORT);
+  
+  invf_file_header ifh;
+  ifh.Read (invfFile);
+
+  if (ifh.skip_mode != SKIP_MODE_NO_SKIPS)
+    FatalError (1, "The invf file contains skips. Unable to dump.");
+
+  // print out header information
+  if (printHeader) {
+    PrintHeaderInfo (idh, ifh);
+  }
+
+  // open the inverted index
+  FILE *invfIdxFile = open_file (filename, INVF_IDX_SUFFIX, "rb",
+				 MAGIC_INVI, MG_ABORT);
+
+  // go to the start of the word dictionary
+  fseek (dictFile, idh.word_dict_start, SEEK_SET);
+
+  // process all the words
+  if (printWords) {
+    unsigned long wordNum;
+    unsigned long wordStart;
+    word_dict_el wordEl;
+    wordEl.SetNumLevels (idh.num_levels);
+    for (wordNum=0; wordNum<idh.word_dict_size; ++wordNum) {
+      wordEl.Read (dictFile, idh.num_levels);
+      ReadUL (invfIdxFile, wordStart);
+      PrintInvfWord (invfFile, idh, ifh, wordEl, wordStart, printFrags);
+    }
+  }
+
+  // process all the tags
+  if (printTags) {
+    unsigned long tagNum;
+    unsigned long tagStart;
+    dict_el tagEl;
+    for (tagNum=0; tagNum<idh.tag_dict_size; ++tagNum) {
+      tagEl.Read (dictFile);
+      ReadUL (invfIdxFile, tagStart);
+      PrintInvfTag (invfFile, idh, ifh, tagEl, tagStart, printFrags);
+    }
+  }
+  // close the open files
+  fclose (invfIdxFile);
+  fclose (invfFile);
+  fclose (dictFile);
+}
+
+
+int main (int argc, char **argv) {
+  char *dir_name, *filename = "";
+  int ch;
+  msg_prefix = argv[0];
+  dir_name = getenv ("MGDATA");
+  opterr = 0;
+
+  bool printHeader = false;
+  bool printWords = false;
+  bool printTags = false;
+  bool printFrags = false;
+  
+  msg_prefix = argv[0];
+  while ((ch = getopt (argc, argv, "hrwtnf:d:")) != -1) {
+    switch (ch) {
+    case 'f':		// input file
+      filename = optarg;
+      break;
+    case 'd':
+      set_basepath(optarg);
+      break;
+    case 'r':
+      printHeader = true;
+      break;
+    case 'w':
+      printWords = true;
+      break;
+    case 'n':
+      printFrags = true;
+      break;
+    case 't':
+      printTags = true;
+      break;
+    case 'h':
+    case '?':
+      fprintf (stderr, "usage: %s [-h] [-r] [-w] [-t] [-n] [-f input_file]"
+	       "[-d data directory]\n(-rwnt:print header, words, tags, fragnums)\n", 
+	       argv[0]);
+      exit (1);
+    }
+  }
+  
+  process_files (filename, printHeader, printWords, printTags, printFrags);
+
+  return 0;
+}
Index: /indexers/branches/3.03a/mgpp/text/mgpp_passes.1
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_passes.1	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_passes.1	(revision 14757)
@@ -0,0 +1,323 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.\"------------------------------------------------------------
+.TH mgpp_passes 1 \*(Dt CITRI
+.SH NAME
+mgpp_passes \- builds mgpp databases
+.SH SYNOPSIS
+.B mgpp_passes
+[
+.BI \-J " doc-tag"
+]
+[
+.BI \-K " level-tag"
+]
+.if n .ti +10n
+[
+.BI \-L " index-level"
+]
+[
+.BI \-m " invf-mem-buffer"
+]
+.if n .ti +10n
+[
+.B \-T1
+]
+[
+.B \-T2
+]
+[
+.B \-I1
+]
+[
+.B \-I2
+]
+[
+.B \-S
+]
+[
+.B \-C
+]
+.if n .ti +10n
+[
+.B \-h
+]
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+[
+.I filename(s)
+]
+.SH DESCRIPTION
+.B mgpp_passes
+is the program that does most of the work when building mgpp
+database systems.  The input documents can come from either
+.I stdin
+or from a list of files on the command line.  In general,
+.B mgpp_passes
+must be run twice to build a database, first with the
+.B \-T1
+and
+.B \-I1
+options, and second with the
+.B \-T2
+and
+.B \-I2
+options.  Several other programs must be run in order to get an
+mgpp database.  The
+.SB EXAMPLE
+section below gives an example of how to build a complete
+mgpp database.
+.SH OPTIONS
+Options may appear in any order, but the
+.IR filename(s) ,
+if specified, must be last.
+.TP "\w'\fB\-C\fP \fIcompstatpointt\fP'u+2n"
+.BI \-J " doc-tag"
+Specifies the SGML tag that encloses each document.  Text appearing
+outside this tag is ignored.  The document tag defines the highest
+level document that can be queried and printed.  The default document
+tag is 'Document'.
+.TP
+.BI \-K " level-tag"
+Specifies the SGML tag of a sub document level.  A level tag must
+enclose all text enclosed by the document tag.  Levels can be
+queried and printed as if they were separate documents.  Multiple
+document levels can be specified (the document tag is always
+added as a document level).
+.TP
+.BI \-L " index-level"
+Specifies the SGML tag enclosing the smallest indexed element.  The
+index level should be no larger than the smallest document 
+level.  An empty string can be used to specify a word level index 
+(which is the default).
+.TP
+.BI \-m " invf-mem-buffer"
+Maximum amount of memory to use for the pass-2 file inversion in
+megabytes.  This option is only useful when used in conjunction with
+the option
+.BR \-I1 .
+The larger this value, the faster the pass-2 inversion will proceed.
+The default value is 5 MB.
+.TP
+.B \-T1
+Generate the
+.I *.text.stats
+file.
+.TP
+.B \-T2
+Generate the
+.IR *.text ,
+.IR *.text.idx ,
+.IR *.text.level ,
+and possibly the
+.I *.text.dict.aux
+files.  Using this option requires that the
+.I *.text.dict
+file be present.
+.TP
+.B \-I1
+Generate the
+.IR *.invf.dict ,
+.IR *.invf.level ,
+.IR *.invf.chunk ,
+and
+.I *.invf.chunk.trans
+files.
+.TP
+.B \-I2
+Generate the
+.I *.invf
+and
+.I *.invf.idx
+files.  Using this option requires
+that the
+.IR *.invf.dict.hash ,
+.IR *.invf.level ,
+.IR *.invf.chunk ,
+and
+.I *.invf.chunk.trans
+files be present.  The
+.I *.invf.dict.hash
+file is generated by
+.BR mgpp_perf_hash_build (1)
+from the
+.I *.invf.dict
+file.
+.TP
+.B \-S
+This option causes a special pass to be executed.  It is up to a user
+to modify
+.I mg.special.c
+in the source code to do something with the documents it is given.
+.TP 
+.B \-C
+This activates the compatibility parsing mode.  When using this
+mode documents are separated by control-B and paragraphs are separated
+by control-C.  Internally these are converted to documents surrounded
+by 'Document' tags and paragraphs surrounded by 'Paragraph' tags.
+.TP
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection is to be
+written.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection that will be
+created.
+.TP
+.I filename(s)
+This specifies the source text. If this is not specified, then the
+program expects the source text from
+.IR stdin .
+.SH EXAMPLE
+What follows is a UNIX
+.BR csh (1)
+script as an example of how to build an mgpp document collection.
+.LP
+.nf
+.DT
+.ft B
+.I #! /bin/csh
+.I
+# The first argument on the command line specifies the
+.I
+#   source of the text
+set source = ($1)
+.PP
+.I
+# The second argument is the name of the collection
+set text = ($2)
+.PP
+.I
+# Create *.text.stats, *.invf.dict, *.invf.level
+.I
+#   *.invf.chunk and *.invf.chunks.trans
+${source} | mgpp_passes -T1 -I1 -f ${text}
+.PP
+.I
+# Create *.text.dict
+mgpp_compression_dict -f ${text}
+.PP
+.I
+# Create *.invf.dict.hash
+mgpp_perf_hash_build -f ${text}
+.PP
+.I
+# Create *.text, *.text.idx, *.text.level
+.I
+#   *.invf and *.invf.idx
+${source} | mgpp_passes -T2 -I2 -f ${text}
+.PP
+.I
+# Create *.text.weight and *.weight.approx
+mgpp_weights_build -f ${text}
+.PP
+.I
+# Create *.invf.dict.blocked
+mgpp_invf_dict -f ${text}
+.PP
+.I
+# Create *.invf.dict.blocked.1
+mgpp_stem_idx -s 1 -f ${text}
+.PP
+.I
+# Create *.invf.dict.blocked.2
+mgpp_stem_idx -s 2 -f ${text}
+.PP
+.I
+# Create *.invf.dict.blocked.3
+mgpp_stem_idx -s 3 -f ${text}
+.PP
+.I
+# Create *.text.dict.fast
+mgpp_fast_comp_dict -f ${text}
+.ft R
+.fi
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the mgpp
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 22
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.chunk
+Inverted file chunk descriptor file.  When the inverted file is
+created it is created in chunks that use no more than a set amount of
+memory.  This file describes those chunks.
+.TP
+.B *.invf.chunk.trans
+Word-occurrence-order to lexical-order translation file.  The
+.B *.invf.chunk
+file is written in word-occurrence order but is required by
+.B \-I2
+to be in lexical order.
+.TP
+.B *.invf.dict
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict.blocked
+Compressed stemmed dictionary with index into the dictionary.
+.TP
+.B *.invf.dict.blocked.n
+Transformation dictionary from words stemmed with method 
+.B n
+to unstemmed words.
+.TP
+.B *.invf.dict.hash
+Data for an order-preserving perfect hash function.
+.TP
+.B *.invf.idx
+The index into the inverted file.
+.TP
+.B *.invf.level
+Information about the document levels needed for querying.
+.TP
+.B *.text
+Compressed text.
+.TP
+.B *.text.dict
+Compressed compression dictionary.
+.TP
+.B *.text.dict.fast
+A fast loading version of the compressed compression dictionary.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.text.level
+Information about the document levels needed for text decompression.
+.TP
+.B *.text.stats
+Statistics about the text.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.B *.weight.approx
+The approximate weights file.
+.SH "SEE ALSO"
+.na
+.BR mgpp_compression_dict (1),
+.BR mgpp_fast_comp_dict (1),
+.BR mgpp_invf_dict (1),
+.BR mgpp_perf_hash_build (1),
+.BR mgpp_stem_idx (1),
+.BR mgpp_weights_build (1)
Index: /indexers/branches/3.03a/mgpp/text/mgpp_passes.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_passes.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_passes.cpp	(revision 14757)
@@ -0,0 +1,274 @@
+/**************************************************************************
+ *
+ * mgpp_passes.cpp -- Driver for the various passes
+ * Copyright (C) 1994  Neil Sharman
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
+#pragma warning(disable:4786)
+#endif
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+#include "sysfuncs.h"
+
+#ifdef HAVE_MALLINFO
+# include <malloc.h> 
+#endif
+
+#if defined __WIN32__
+# include <io.h>
+# include "getopt_old.h"
+# define close _close
+# define open _open
+#elif defined __CYGWIN__
+#include "getopt_old.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "memlib.h"
+#include "messages.h"
+#include "longlong.h"
+#include "mg_files.h"
+#include "mg.h"
+#include "build.h"
+#include "text.h"
+#include "stemmer.h"
+#include "FileBuf.h"
+#include "TextEl.h"
+#include "TagInfo.h"
+#include "words.h"
+#define MAX_PASSES 5
+
+#define SPECIAL 1
+#define TEXT_PASS_1 2
+#define TEXT_PASS_2 4
+#define IVF_PASS_1 8
+#define IVF_PASS_2 16
+
+#define MIN_BUF 8192
+
+
+unsigned long invf_buffer_size = 5 * 1024 * 1024;	/* 5Mb */
+
+static char Passes = 0;
+static char **files = NULL;
+static int num_files = 0;
+
+
+struct pass_data {
+  char *name;
+  int (*init) (const TagInfo &tagInfo, char *);
+  int (*process) (const TagInfo &tagInfo, const TextElArray &doc);
+  int (*done) (const TagInfo &tagInfo, char *);
+};
+
+
+static pass_data PassData[MAX_PASSES] = {
+  {"special", init_special, process_special, done_special},
+  {"text.pass1", init_text_1, process_text_1, done_text_1},
+  {"text.pass2", init_text_2, process_text_2, done_text_2},
+  {"ivf.pass1", init_ivf_1, process_ivf_1, done_ivf_1},
+  {"ivf.pass2", init_ivf_2, process_ivf_2, done_ivf_2},
+};
+
+static char *usage_str = "\nUSAGE:\n"
+"  %s [-J doc-tag] [-K level-tag] [-L index-level]\n"
+"  %*s [-m invf-memory] [-T1] [-T2] [-I1] [-I2] [-S]\n"
+"  %*s [-C] [-h] [-d directory] [-M maxnumeric] -f name\n\n";
+
+
+
+static void Usage (char *err) {
+  if (err) Message (err);
+  fprintf (stderr, usage_str, msg_prefix, strlen (msg_prefix), "",
+	   strlen (msg_prefix), "");
+  exit (1);
+}
+
+
+
+
+int OpenNextFile (int in_fd) {
+  if (in_fd > 0) close (in_fd);
+  if (num_files == 0) return (-1);
+  if ((in_fd = open (files[0], O_RDONLY)) == -1)
+    FatalError (1, "Cannot open %s", files[0]);
+  ++files;
+  --num_files;
+  return (in_fd);
+}
+
+
+static void Driver (int in_fd, char *file_name,
+		    const TagInfo &tagInfo, bool compatMode) {
+  //  cout << tagInfo;
+
+  int pass;
+
+  unsigned long numBytes = 0;
+  unsigned long numDocs = 0;
+
+  // initialise all the passes
+  for (pass = 0; pass < MAX_PASSES; ++pass) {
+    if (Passes & (1 << pass)) {
+      if (PassData[pass].init (tagInfo, file_name) == COMPERROR)
+	FatalError (1, "Error during init of \"%s\"", PassData[pass].name);
+    }
+  }
+
+  
+  // set up various variables
+  FileBuf buf;
+  TextElArray doc;
+  unsigned long docLen = 0;
+
+  // read and process each file (start with an open file)
+  do {
+    
+    // read and process each document in this file
+    buf.SetFD (in_fd);
+    while (ReadDoc (buf, tagInfo.docTag, doc, docLen, compatMode)) {
+
+      // give this document to each pass
+      for (pass = 0; pass < MAX_PASSES; ++pass) {
+	if (Passes & (1 << pass)) {
+	  if (PassData[pass].process (tagInfo, doc) == COMPERROR)
+	    FatalError(1,"Error during processing of \"%s\"",PassData[pass].name);
+	}
+      }
+      
+      // another document has been processed
+      numBytes += docLen;
+      ++numDocs;
+    }
+    
+  } while ((in_fd = OpenNextFile (in_fd)) > 0);
+
+  
+  // do done for each pass
+  for (pass = 0; pass < MAX_PASSES; ++pass) {
+    if (Passes & (1 << pass)) {
+      if (PassData[pass].done (tagInfo, file_name) == COMPERROR)
+	FatalError (1, "Error during done of \"%s\"", PassData[pass].name);
+    }
+  }
+}
+
+int main (int argc, char **argv) {
+  int ch, in_fd, maxnum;
+  char *filename = NULL;
+  bool compatMode = false;
+  TagInfo tagInfo;
+  tagInfo.SetDocTag ("Document");
+  
+  msg_prefix = argv[0];
+
+  opterr = 0;
+  while ((ch=getopt(argc, argv, "J:K:L:M:f:d:m:I:T:SCh"))!=-1){
+    switch (ch) {
+    case 'J':
+      tagInfo.SetDocTag (optarg);
+      break;
+    case 'K':
+      tagInfo.AddLevelTag (optarg);
+      break;
+    case 'L':
+      tagInfo.SetIndexLevel (optarg);
+      break;
+    case 'M':
+      maxnum = atoi(optarg);
+      if (4 < maxnum < 512) {
+	MAXNUMERIC = maxnum;
+      }
+      break;
+    case 'f':
+      filename = optarg;
+      break;
+    case 'd':
+      set_basepath (optarg);
+      break;
+    case 'm':
+      invf_buffer_size = (int) (atof (optarg) * 1024 * 1024);
+      break;
+    case 'I':
+      if (*optarg == '1')
+	Passes |= IVF_PASS_1;
+      else if (*optarg == '2')
+	Passes |= IVF_PASS_2;
+      else
+	Usage ("Invalid pass number");
+      break;
+    case 'T':
+      if (*optarg == '1')
+	Passes |= TEXT_PASS_1;
+      else if (*optarg == '2')
+	Passes |= TEXT_PASS_2;
+      else
+	Usage ("Invalid pass number");
+      break;
+    case 'S':
+      Passes |= SPECIAL;
+      break;
+    case 'C':
+      compatMode = true;
+      break;
+    case 'h':
+    case '?':
+      Usage (NULL);
+    }
+  }
+
+  if (!filename || *filename == '\0')
+    FatalError (1, "A document collection name must be specified.");
+
+  if ((Passes & (IVF_PASS_1 | IVF_PASS_2)) == (IVF_PASS_1 | IVF_PASS_2))
+    FatalError (1, "I1 and I2 cannot be done simultaneously.");
+
+  if ((Passes & (TEXT_PASS_1 | TEXT_PASS_2)) == (TEXT_PASS_1 | TEXT_PASS_2))
+    FatalError (1, "T1 and T2 cannot be done simultaneously.");
+
+  if (!Passes)
+    FatalError (1, "S, T1, T2, I1 or I2 must be specified.");
+
+  if (optind < argc) {
+    if ((in_fd = open (argv[optind], O_RDONLY)) == -1)
+      FatalError (1, "Cannot open %s", argv[optind]);
+    files = &argv[optind + 1];
+    num_files = argc - (optind + 1);
+    
+  } else in_fd = 0;  // stdin
+
+  
+  if (compatMode) tagInfo.SetDocTag ("Document");
+
+  // a document tag is also a level tag
+  tagInfo.levelTags.insert (tagInfo.docTag); 
+  
+  Driver (in_fd, filename, tagInfo, compatMode);
+
+  return (0);
+}
Index: /indexers/branches/3.03a/mgpp/text/mgpp_passes_4jni.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_passes_4jni.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_passes_4jni.cpp	(revision 14757)
@@ -0,0 +1,316 @@
+/**************************************************************************
+ *
+ * mgpp_passes.cpp -- Driver for the various passes
+ * Copyright (C) 1994  Neil Sharman
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
+#pragma warning(disable:4786)
+#endif
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+#include "sysfuncs.h"
+
+#ifdef HAVE_MALLINFO
+# include <malloc.h> 
+#endif
+
+#if defined __WIN32__
+# include <io.h>
+# include "getopt_old.h"
+# define close _close
+# define open _open
+#elif defined __CYGWIN__
+#include "getopt_old.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "memlib.h"
+#include "messages.h"
+#include "longlong.h"
+#include "mg_files.h"
+#include "mg.h"
+#include "build.h"
+#include "text.h"
+#include "stemmer.h"
+#include "FileBuf.h"
+#include "TextEl.h"
+#include "TagInfo.h"
+
+#include "mgpp_passes_4jni.h"
+
+#define MAX_PASSES 5
+
+#define SPECIAL 1
+#define TEXT_PASS_1 2
+#define TEXT_PASS_2 4
+#define IVF_PASS_1 8
+#define IVF_PASS_2 16
+
+#define MIN_BUF 8192
+
+
+unsigned long invf_buffer_size = 5 * 1024 * 1024;	/* 5Mb */
+
+static char Passes = 0;
+static char **files = NULL;
+static int num_files = 0;
+
+TagInfo tagInfo;
+char *filename = NULL;
+
+unsigned long numBytes = 0;
+unsigned long numDocs = 0;
+int mgpp_passes_exit_value = 0;
+
+struct pass_data {
+  char *name;
+  int (*init) (const TagInfo &tagInfo, char *);
+  int (*process) (const TagInfo &tagInfo, const TextElArray &doc);
+  int (*done) (const TagInfo &tagInfo, char *);
+};
+
+
+static pass_data PassData[MAX_PASSES] = {
+  {"special", init_special, process_special, done_special},
+  {"text.pass1", init_text_1, process_text_1, done_text_1},
+  {"text.pass2", init_text_2, process_text_2, done_text_2},
+  {"ivf.pass1", init_ivf_1, process_ivf_1, done_ivf_1},
+  {"ivf.pass2", init_ivf_2, process_ivf_2, done_ivf_2},
+};
+
+
+/* clear all the settings from one mgpp_passes run to the next */
+void clear_variables() {
+  tagInfo.Clear();
+  tagInfo.SetDocTag ("Document");
+  Passes = 0;
+  invf_buffer_size = 5 * 1024 * 1024;
+  numBytes = 0;
+  numDocs = 0;
+  mgpp_passes_exit_value = 0;
+}
+
+/* ################################################## */
+/* the following are methods to set all the variables that used to be
+   set by command line args */
+
+/* -S, -T1, -T2, -I1, -I2, args to mg_passes */
+void add_pass (char pass_type, char pass_num) {
+
+  switch(pass_type) {
+  case 'S':
+    Passes |= SPECIAL;
+    break;
+  case 'I':
+    if (pass_num == '1')
+      Passes |= IVF_PASS_1;
+    else if (pass_num == '2')
+      Passes |= IVF_PASS_2;
+    else
+      fprintf(stderr, "Invalid pass number %c for pass type %c\n", pass_num, pass_type);
+    break;
+  case 'T':
+    if (pass_num == '1')
+      Passes |= TEXT_PASS_1;
+    else if (pass_num == '2')
+      Passes |= TEXT_PASS_2;
+    else
+      fprintf(stderr, "Invalid pass number %c for pass type %c\n", pass_num, pass_type);
+    break;
+  }
+}
+
+/* -m arg to mgpp_passes */
+void set_inversion_limit(int limit) {
+  invf_buffer_size = limit * 1024 * 1024;
+}
+
+/* -J arg to mgpp_passes */
+void set_document_tag(const char *tag_name) {
+  tagInfo.SetDocTag (tag_name);
+
+  // a doc tag is also a level tag
+  tagInfo.AddLevelTag(tag_name);
+
+}
+
+/* -K arg to mgpp_passes */
+void add_level_tag(const char *tag_nam) {
+  tagInfo.AddLevelTag(tag_nam);
+}
+
+/* -L arg to mgpp_passes */
+void set_index_level(const char *tag_name) {
+  tagInfo.SetIndexLevel(tag_name);
+}
+
+// is this enough???
+/* -f arg to mgpp_passes */
+void set_filename(const char * filen) {
+  if (filename) {
+    Xfree (filename);
+    filename = NULL;
+  }
+  filename = Xstrdup (filen);  
+}
+ 
+
+/* ############################################### */
+/* The old driver method has been split into 3:
+init_driver, process_document (called numdocs times), 
+finalise_driver.
+The above set vars methods should all be called before init_driver.
+*/
+
+void init_driver () {
+
+  if (!filename || *filename == '\0') {
+    mgpp_passes_exit_value = 1;
+    FatalError (1, "A document collection name must be specified.");
+  }
+  if ((Passes & (IVF_PASS_1 | IVF_PASS_2)) == (IVF_PASS_1 | IVF_PASS_2)) {
+    mgpp_passes_exit_value = 1;
+    FatalError (1, "I1 and I2 cannot be done simultaneously.");
+  }
+  if ((Passes & (TEXT_PASS_1 | TEXT_PASS_2)) == (TEXT_PASS_1 | TEXT_PASS_2)) {
+    mgpp_passes_exit_value = 1;
+    FatalError (1, "T1 and T2 cannot be done simultaneously.");
+  }
+  if (!Passes) {
+    mgpp_passes_exit_value = 1;
+    FatalError (1, "S, T1, T2, I1 or I2 must be specified.");
+  }
+  
+  // initialise all the passes
+  for (int pass = 0; pass < MAX_PASSES; pass++) {
+    if (Passes & (1 << pass)) {
+      if (PassData[pass].init (tagInfo, filename) == COMPERROR) {
+	mgpp_passes_exit_value = 1;
+	FatalError (1, "Error during init of \"%s\"", PassData[pass].name);
+      }
+    }
+  }
+
+}
+
+void process_document(u_char *buffer, int len) {
+  
+  TextElArray doc;
+  unsigned long doc_len =  0;
+
+  while(ReadDoc(&buffer, tagInfo.docTag, doc, doc_len, false)) {
+    // give this document to each pass
+    for (int pass = 0; pass < MAX_PASSES; pass++) {
+      if (Passes & (1 << pass)) {
+	if (PassData[pass].process (tagInfo, doc) == COMPERROR) {
+	  mgpp_passes_exit_value = 1;
+	  FatalError(1,"Error during processing of \"%s\"",PassData[pass].name);
+	}
+      }
+    }
+    
+    // another document has been processed
+    numBytes += doc_len;
+    numDocs++;
+    cout << "doc_len = "<<doc_len<<endl;
+  }
+}    
+
+void finalise_driver () {
+  
+  // do done for each pass
+  for (int pass = 0; pass < MAX_PASSES; pass++) {
+    if (Passes & (1 << pass)) {
+      if (PassData[pass].done (tagInfo, filename) == COMPERROR) {
+	mgpp_passes_exit_value = 1;
+	FatalError (1, "Error during done of \"%s\"", PassData[pass].name);
+      }
+    }
+  }  
+}
+
+int get_exit_value() {
+  return mgpp_passes_exit_value;
+}
+  /*
+static void Driver (int in_fd, char *file_name,
+		    const TagInfo &tagInfo, bool compatMode) {
+  //  cout << tagInfo;
+
+  int pass;
+
+  unsigned long numBytes = 0;
+  unsigned long numDocs = 0;
+
+  // initialise all the passes
+  for (pass = 0; pass < MAX_PASSES; pass++) {
+    if (Passes & (1 << pass)) {
+      if (PassData[pass].init (tagInfo, file_name) == COMPERROR)
+	FatalError (1, "Error during init of \"%s\"", PassData[pass].name);
+    }
+  }
+
+  
+  // set up various variables
+  FileBuf buf;
+  TextElArray doc;
+  unsigned long docLen = 0;
+
+  // read and process each file (start with an open file)
+  do {
+    
+    // read and process each document in this file
+    buf.SetFD (in_fd);
+    while (ReadDoc (buf, tagInfo.docTag, doc, docLen, compatMode)) {
+
+      // give this document to each pass
+      for (pass = 0; pass < MAX_PASSES; pass++) {
+	if (Passes & (1 << pass)) {
+	  if (PassData[pass].process (tagInfo, doc) == COMPERROR)
+	    FatalError(1,"Error during processing of \"%s\"",PassData[pass].name);
+	}
+      }
+      
+      // another document has been processed
+      numBytes += docLen;
+      numDocs++;
+    }
+    
+  } while ((in_fd = OpenNextFile (in_fd)) > 0);
+
+  
+  // do done for each pass
+  for (pass = 0; pass < MAX_PASSES; pass++) {
+    if (Passes & (1 << pass)) {
+      if (PassData[pass].done (tagInfo, file_name) == COMPERROR)
+	FatalError (1, "Error during done of \"%s\"", PassData[pass].name);
+    }
+  }
+}
+
+  */
Index: /indexers/branches/3.03a/mgpp/text/mgpp_passes_4jni.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_passes_4jni.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_passes_4jni.h	(revision 14757)
@@ -0,0 +1,62 @@
+/**************************************************************************
+ *
+ * mgpp_passes_4jni.h -- modified mgpp_passes for use from jni
+ * Copyright (C) 2004 New Zealand Digital Library, http://www.nzdl.org
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+#ifndef H_MGPP_PASSES_4JNI
+#define H_MGPP_PASSES_4JNI
+
+
+/* clear all the settings from one mgpp_passes run to the next */
+void clear_variables();
+
+/* -S, -T1, -T2, -I1, -I2, args to mg_passes */
+void add_pass (char pass_type, char pass_num);
+
+/* -m arg to mg_passes */
+void set_inversion_limit(int limit);
+
+/* -J arg to mgpp_passes */
+void set_document_tag(const char * tag_name);
+
+/* -K arg to mgpp_passes */
+void add_level_tag(const char * tag_name);
+
+/* -L arg to mgpp_passes */
+void set_index_level(const char * tag_name);
+
+/* -f arg to mgpp_passes */
+void set_filename(const char * filen);
+
+/* The old driver method has been split into 3:
+init_driver, process_document (called numdocs times), 
+finalise_driver.
+The above set vars methods should all be called before init_driver.
+*/
+
+void init_driver ();
+
+void process_document(u_char *buffer, int len);
+
+void finalise_driver();
+
+int get_exit_value();
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/mgpp_perf_hash_build.1
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_perf_hash_build.1	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_perf_hash_build.1	(revision 14757)
@@ -0,0 +1,72 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.\"------------------------------------------------------------
+.TH mgpp_perf_hash_build 1 \*(Dt CITRI
+.SH NAME
+mgpp_perf_hash_build \- generate an order-preserving hash function for the stemmed dictionary
+.SH SYNOPSIS
+.B mgpp_perf_hash_build
+[
+.B \-h
+]
+[
+.BI \-r " rndseed"
+]
+[
+.BI \-d  " directory"
+]
+.if n .ti +9n
+.BI \-f " name"
+.SH DESCRIPTION
+.B mgpp_perf_hash_build
+generates an order-preserving hashing function from the compressed
+stemmed dictionary and writes it out to disk.
+.BR mgpp_passes (1)
+will make use of the hash function when it builds the inverted file.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-r " rndseed"
+This specifies the random seed to be used in the generation of the
+hash function; it must be an integer.  If this is not specified, the
+current time will be used as the random seed.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the mg
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf.dict
+Stemmed dictionary.
+.TP
+.B *.invf.dict.hash
+Data for a order-preserving perfect hash function.
+.SH "SEE ALSO"
+.na
+.BR mgpp_compression_dict (1),
+.BR mgpp_fast_comp_dict (1),
+.BR mgpp_invf_dict (1),
+.BR mgpp_passes (1),
+.BR mgpp_stem_idx (1),
+.BR mgpp_weights_build (1)
Index: /indexers/branches/3.03a/mgpp/text/mgpp_perf_hash_build.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_perf_hash_build.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_perf_hash_build.cpp	(revision 14757)
@@ -0,0 +1,146 @@
+/**************************************************************************
+ *
+ * mgpp_perf_hash_build.cpp -- Program to build a perfect hash function
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+/* getopt is in posix.2, so cygwin should have it in unistd, but doesn't */
+#if defined (__WIN32__) || defined (__CYGWIN__)
+# include "getopt_old.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "messages.h"
+#include "local_strings.h"
+#include "perf_hash.h"
+#include "netorder.h"
+
+#include "mg_files.h"
+#include "invf.h"
+#include "locallib.h"
+#include "words.h"
+#include "mg.h"
+
+#define POOL_SIZE 1024*1024
+
+static void ProcessFiles (char *filename, int r) {
+  FILE *dictFile, *hashFile;
+  unsigned long i;
+  invf_dict_header idh;
+  perf_hash_data *phd;
+  u_char *pool;
+  unsigned long pool_left;
+  u_char **starts;
+
+  // read in the dictionary
+  dictFile = open_file (filename, INVF_DICT_SUFFIX, "rb",
+			MAGIC_STEM_BUILD, MG_ABORT);
+  if (dictFile==NULL) {
+    FatalError(1, "unable to open file");
+  }
+  idh.Read (dictFile);
+
+  //cerr << idh.lookback<<" "<<idh.word_dict_start<<endl;
+  // go to the start of the word dictionary
+  fseek (dictFile, idh.word_dict_start, SEEK_SET);
+  
+  if (!(pool = (u_char *) Xmalloc (POOL_SIZE)))
+    FatalError (1, "Out of memory");
+  pool_left = POOL_SIZE;
+
+  if (!(starts = (u_char **) Xmalloc (sizeof (u_char *) * idh.word_dict_size)))
+    FatalError (1, "Out of memory");
+  //cerr << "size= "<< idh.word_dict_size<<endl;
+  word_dict_el wordEl;
+  wordEl.SetNumLevels (idh.num_levels);
+  for (i = 0; i < idh.word_dict_size; ++i) {
+    // read the next word and associated information
+    wordEl.Read (dictFile, idh.num_levels);
+
+    // push string onto pool data
+    register unsigned long l;
+    l = wordEl.el.size() + 1;
+    if (pool_left < l) {
+      pool = (u_char *) Xmalloc (POOL_SIZE);
+      pool_left = POOL_SIZE;
+    }
+    starts[i] = pool;
+    
+    *pool++ = wordEl.el.size();
+    memcpy ((char *) pool, &(wordEl.el[0]), wordEl.el.size());
+    //cerr << pool<<"   " <<starts[i]<<endl;
+    pool += wordEl.el.size();
+    pool_left -= l;
+    
+  }
+  fclose (dictFile);
+  //cerr << pool<<"   " <<starts[i-1]<<endl;
+  //cerr<<"starts  "<<starts[113529]<<endl;
+  //cerr << starts[17][1] << " "<<starts[25][4]<<endl;
+  // create perfect hash file
+  hashFile = create_file (filename, INVF_DICT_HASH_SUFFIX, "wb",
+			  MAGIC_HASH, MG_ABORT);
+  if (!(phd = gen_hash_func (idh.word_dict_size, starts, r)))
+    FatalError (1, "Unable to generate hash function");
+  if (write_perf_hash_data (hashFile, phd) == -1)
+    FatalError (1, "Unable to write hash function");
+  fclose (hashFile);
+}
+
+
+
+int main (int argc, char **argv) {
+  int r = -1;
+  char *filename = "";
+  int ch;
+  msg_prefix = argv[0];
+  opterr = 0;
+
+  while ((ch = getopt (argc, argv, "f:d:r:h")) != -1) {
+    switch (ch) {
+    case 'f':		// input file
+      filename = optarg;
+      break;
+    case 'd':
+      set_basepath (optarg);
+      break;
+    case 'r':
+      r = atoi (optarg);
+      break;
+    case 'h':
+    case '?':
+      fprintf (stderr, "usage: %s [-f input_file]"
+	       "[-d data directory] [-r random seed] [-h]\n", argv[0]);
+      exit (1);
+    }
+  }
+
+  ProcessFiles (filename, r);
+  return 0;
+}
Index: /indexers/branches/3.03a/mgpp/text/mgpp_stem_idx.1
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_stem_idx.1	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_stem_idx.1	(revision 14757)
@@ -0,0 +1,95 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.\"------------------------------------------------------------
+.TH mgpp_stem_idx 1 \*(Dt CITRI
+.SH NAME
+mgpp_stem_idx \- builds a stem index file
+.SH SYNOPSIS
+.B mgpp_stem_idx
+[
+.B \-h
+]
+[
+.BI \-b " entries-per-block"
+]
+.if n .ti +12n
+[
+.BI \-a " stemmer"
+]
+[
+.BI \-d " directory"
+]
+.if n .ti +12n
+.B \-s 1|2|3
+.BI \-f " name"
+.SH DESCRIPTION
+.B mgpp_stem_idx
+generates a stem index file for a collection.
+This program should be called three times: once for each
+.B -s
+parameter.  It uses the stemmed dictionary to create the stem index which
+contains pointers into the stemmed dictionary.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIdirectoryyyyyyyy\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-b " entries-per-block"
+The dictionary is stored in blocks on disk; this option is used to set
+the number of entries per block. The default is 16.
+.TP
+.BI \-a " stemmer"
+The name of the stemmer to use, the default is the Lovin stemmer.
+.TP
+.B -s 1|2|3
+The stem method to apply for the stem index.
+.br
+1 = casefolded and non-stemmed
+.br
+2 = non-casefolded and stemmed
+.br
+3 = casefolded and stemmed
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection can be found.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the mgpp
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 22
+.B *.invf.dict
+Compressed stemmed dictionary.
+.TP
+.B *.invf.dict.blocked.1
+Stem index with stem index method 1.
+.TP
+.B *.invf.dict.blocked.2
+Stem index with stem index method 2.
+.TP
+.B *.invf.dict.blocked.3
+Stem index with stem index method 3.
+.SH "SEE ALSO"
+.na
+.BR mgpp_compression_dict (1),
+.BR mgpp_fast_comp_dict (1),
+.BR mgpp_invf_dict (1),
+.BR mgpp_passes (1),
+.BR mgpp_perf_hash_build (1),
+.BR mgpp_weights_build (1)
Index: /indexers/branches/3.03a/mgpp/text/mgpp_stem_idx.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_stem_idx.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_stem_idx.cpp	(revision 14757)
@@ -0,0 +1,244 @@
+/**************************************************************************
+ *
+ * mgpp_stem_idx.cpp -- stem index builder
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+/* getopt is in posix.2, so cygwin should have it in unistd, but doesn't */
+#if defined (__WIN32__) || defined (__CYGWIN__)
+# include "getopt_old.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "UCArray.h"
+#include "sysfuncs.h"
+#include "messages.h"
+#include "mg_files.h"
+#include "invf.h"
+#include "words.h"
+#include "stemmer.h"
+
+#if defined(GSDL_USE_OBJECTSPACE)
+#  include <ospace\std\map>
+#  include <ospace\std\vector>
+#elif defined(GSDL_USE_STL_H)
+#  include <map.h>
+#  include <vector.h>
+#else
+#  include <map>
+#  include <vector>
+#endif
+
+typedef vector<unsigned long> WordNumList;
+typedef map<UCArray, WordNumList, DictLTUCArray> StemMapDict;
+
+void CreateStemDict (char *filename,
+		     StemMapDict &stemDict,
+		     int stemMethod,
+		     int stemmerNum) {
+  stemDict.erase (stemDict.begin(), stemDict.end());
+
+  // open the dictionary
+  FILE *dictFile = open_file (filename, INVF_DICT_SUFFIX, "rb",
+			      MAGIC_STEM_BUILD, MG_ABORT);
+  invf_dict_header idh;
+  idh.Read (dictFile);
+
+  fseek (dictFile, idh.word_dict_start, SEEK_SET);
+
+  unsigned long wordNum;
+  u_char mgWord[MAXSTEMLEN + 1];
+  word_dict_el wordEl;
+  UCArray stemEl;
+  wordEl.SetNumLevels (idh.num_levels);
+  for (wordNum=0; wordNum<idh.word_dict_size; ++wordNum) {
+    // read in the next word
+    wordEl.Read (dictFile, idh.num_levels);
+
+    // convert the word to an "mg word"
+    mgWord[0] = wordEl.el.size();
+    memcpy((char *)&mgWord[1], &(wordEl.el[0]), wordEl.el.size());
+
+    // stem the word
+    mgpp_stemmer (stemMethod, stemmerNum, mgWord);
+
+    // convert the result back to a UCArray
+    stemEl.erase (stemEl.begin(), stemEl.end());
+    stemEl.insert (stemEl.end(), &mgWord[1], &mgWord[1] + mgWord[0]);
+
+//      cout << "\"" << stemEl << "\" -> \"" << wordEl.el << "\"\n";
+    
+    // add this word number to the list of word numbers for this word
+    stemDict[stemEl].push_back (wordNum);
+  }
+
+  fclose (dictFile);
+}
+
+
+void WriteStemDict (char *filename,
+		    StemMapDict &stemDict,
+		    int stemMethod,
+		    int stemmerNum,
+		    unsigned long entriesPerBlock) {
+  
+  /* [JFG - Mar 06: Accent folding patch] */
+  // Create appropriate stem index file
+  FILE *stemDictFile = NULL;
+  if (stemMethod >= STEM_MIN && stemMethod <= STEM_MAX) {
+  	char *suffix = make_suffix (INVF_DICT_BLOCKED_SUFFIX_PAT, stemMethod, NULL);
+    stemDictFile = create_file (filename, suffix,
+				"wb", MAGIC_STEM_GEN(stemMethod + '0'), MG_ABORT);  
+  }
+  else {
+    FatalError (1, "Unknown stem method %d", stemMethod);
+  }
+
+  stem_idx_header sih;
+  sih.lookback = 0;
+  sih.dict_size = stemDict.size();
+  sih.entries_per_block = entriesPerBlock;
+  sih.max_block_size = 0;
+  
+  sih.stemmer_num = stemmerNum;
+  sih.stem_method = stemMethod;
+
+  // write out a place-holder version of the header
+  sih.Write (stemDictFile);
+
+  sih.blocks_start = ftell (stemDictFile);
+
+  block_idx stemIdx;
+  unsigned long stemNum = 0;
+  stem_block_dict_el stemEl;
+  UCArray lastEl;
+
+  StemMapDict::const_iterator here = stemDict.begin();
+  StemMapDict::const_iterator end = stemDict.end();
+  while (here != end) {
+    // remember this stem (and position) if this is the start
+    // of a new block
+    if (stemNum % entriesPerBlock == 0) {
+      block_idx_info elIdx;
+      elIdx.el = (*here).first;
+      elIdx.block_ptr = ftell (stemDictFile);
+
+      // see if this block is the longest so far
+      if (stemIdx.size() > 0) {
+	unsigned long blockLen = elIdx.block_ptr -
+	  (*(stemIdx.end()-1)).block_ptr;
+	if (blockLen > sih.max_block_size) sih.max_block_size = blockLen;
+      }
+      
+      stemIdx.push_back (elIdx);
+      lastEl.erase (lastEl.begin(), lastEl.end()); // output full word
+    }
+
+    // copy the information for this stem
+    stemEl.el = (*here).first;
+    stemEl.equivWords = (*here).second;
+
+    // write out the stem
+    stemEl.Write (stemDictFile, &lastEl);
+    
+    ++here; ++stemNum;
+  }
+
+
+  // write out the element indexes
+  sih.num_blocks = stemIdx.size();
+  sih.block_idx_start = ftell (stemDictFile);
+  WriteBlockIdx (stemDictFile, stemIdx);
+  
+  // write out the stem dictionary header
+  fseek (stemDictFile, sizeof(unsigned long), SEEK_SET);
+  sih.Write (stemDictFile);
+
+
+  // close open files
+  fclose (stemDictFile);
+  
+  // print out information
+#ifndef SILENT
+  Message ("Num word stems = %d\n", sih.dict_size);
+  Message ("Max stem block size = %d\n", sih.max_block_size);
+  Message ("Number of stem blocks written = %d\n", sih.num_blocks);
+#endif
+}
+
+
+int main (int argc, char **argv) {
+  unsigned long entriesPerBlock = 16;
+  char *filename = "";
+  int ch;
+  int stemMethod = 0; // illegal value (no translation)
+  int stemmerNum = 0; // English stemmer
+  msg_prefix = argv[0];
+  opterr = 0;
+
+  while ((ch = getopt (argc, argv, "f:d:b:s:h")) != -1) {
+    switch (ch) {
+    case 'f':		// input file
+      filename = optarg;
+      break;
+    case 'd':
+      set_basepath (optarg);
+      break;
+    case 'b':
+      entriesPerBlock = atoi (optarg);
+      break;
+    case 's':
+      stemMethod = atoi (optarg);
+      break;
+    case 'a':
+      stemmerNum = mgpp_stemmernumber ((unsigned char *) optarg);
+      break;
+    case 'h':
+    case '?':
+      fprintf (stderr, "usage: %s [-d directory] "
+	       "[-b entries-per-block] [-h] -s 1|2|3", argv[0]);
+#ifdef ENABLE_ACCENTFOLD
+      fprintf (stderr, "|4|5|6|7");
+#endif
+      fprintf (stderr, " [-a stemmer-method] -f name\n");
+      exit (1);
+    }
+  }
+  
+  /* [JFG - Mar 06: Accent folding patch] */
+  if (stemMethod < STEM_MIN || stemMethod > STEM_MAX) 
+    FatalError (1, "Stem method must be between %d and %d", STEM_MIN, STEM_MAX);
+#ifndef ENABLE_ACCENTFOLD
+  if (stemMethod & STEM_AccentFolding) {
+    // accent folding not enabled
+    return 2;
+  }
+#endif
+  // read in the dictionary and create the in memory dictionary
+  StemMapDict stemDict;
+  CreateStemDict (filename, stemDict, stemMethod, stemmerNum);
+  
+  // write out the dictionary as a blocked file
+  WriteStemDict (filename, stemDict, stemMethod, stemmerNum, entriesPerBlock);
+  
+  return 0;
+}
Index: /indexers/branches/3.03a/mgpp/text/mgpp_weights_build.1
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_weights_build.1	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_weights_build.1	(revision 14757)
@@ -0,0 +1,79 @@
+.\"------------------------------------------------------------
+.\" Id - set Rv,revision, and Dt, Date using rcs-Id tag.
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.\"------------------------------------------------------------
+.TH mgpp_weights_build 1 \*(Dt CITRI
+.SH NAME
+mgpp_weights_build \- builds the approximate weights file
+.SH SYNOPSIS
+.B mgpp_weights_build
+[
+.B \-h
+]
+[
+.BI \-b " num-bits"
+]
+.if n .ti +17n
+[
+.BI \-d " directory"
+]
+.BI \-f " name"
+.SH DESCRIPTION
+.B mgpp_weights_build
+is the program that generates the exact and approximate weights 
+files.  To do this, it uses the inverted file
+and dictionary.
+.SH OPTIONS
+Options may appear in any order.
+.TP "\w'\fB\-d\fP \fIirectory\fP'u+2n"
+.B \-h
+This displays a usage line on
+.IR stderr .
+.TP
+.BI \-b " num-bits"
+This specifies the number of bits of precision that should be used for
+the approximate weights.  If not specified, it defaults to 8.
+.TP
+.BI \-d " directory"
+This specifies the directory where the document collection is.
+.TP
+.BI \-f " name"
+This specifies the base name of the document collection.
+.SH ENVIRONMENT
+.TP "\w'\fBMGDATA\fP'u+2n"
+.SB MGDATA
+If this environment variable exists, then its value is used as the
+default directory where the mgpp
+collection files are.  If this variable does not exist, then the
+directory \*(lq\fB.\fP\*(rq is used by default.  The command line
+option
+.BI \-d " directory"
+overrides the directory in
+.BR MGDATA .
+.SH FILES
+.TP 20
+.B *.invf
+Inverted file.
+.TP
+.B *.invf.dict
+Compressed stemmed dictionary.
+.TP
+.B *.text.idx
+Index into the compressed documents.
+.TP
+.B *.weight
+The exact weights file.
+.TP
+.B *.weight.approx
+Approximate document weights.
+.SH "SEE ALSO"
+.na
+.BR mgpp_compression_dict (1),
+.BR mgpp_fast_comp_dict (1),
+.BR mgpp_invf_dict (1),
+.BR mgpp_passes (1),
+.BR mgpp_perf_hash_build (1),
+.BR mgpp_stem_idx (1)
Index: /indexers/branches/3.03a/mgpp/text/mgpp_weights_build.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/mgpp_weights_build.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/mgpp_weights_build.cpp	(revision 14757)
@@ -0,0 +1,399 @@
+/**************************************************************************
+ *
+ * mgpp_weights_build.cpp -- Program to build the document weights file
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+/* getopt is in posix.2, so cygwin should have it in unistd, but doesn't */
+#if defined (__WIN32__) || defined (__CYGWIN__)
+# include "getopt_old.h"
+#else
+# include <unistd.h>
+#endif
+
+#include "UCArray.h"
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "messages.h"
+#include "local_strings.h"
+#include "bitio_gen.h"
+#include "bitio_m_stdio.h"
+#include "mg_files.h"
+#include "locallib.h"
+#include "invf.h"
+#include "FIvfLevelInfo.h"
+#include "FragLevelConvert.h"
+
+#if defined(GSDL_USE_OBJECTSPACE)
+#  include <ospace\std\map>
+#elif defined(GSDL_USE_STL_H)
+#  include <map.h>
+#else
+#  include <map>
+#endif
+
+#define MAXBITS (sizeof(unsigned long) * 8)
+
+struct WBTagPtr {
+  unsigned long tagNum;
+  unsigned long tagPtr;
+  unsigned long fragOccur;
+  
+  WBTagPtr () {
+    tagNum = 0;
+    tagPtr = 0;
+    fragOccur = 0;
+  }
+};
+
+// maps tags to tag information
+typedef map<UCArray, WBTagPtr, DictLTUCArray> WBTagDict;
+
+typedef vector<float> Weights;
+
+
+static void ReadTagDict (const invf_dict_header &idh,
+			 FILE *dictFile,
+			 FILE *invfIdxFile,
+			 WBTagDict &tagDict) {
+  tagDict.erase (tagDict.begin(), tagDict.end());
+
+  // seek to the start of the tag information
+  fseek (dictFile, idh.tag_dict_start, SEEK_SET);
+  fseek (invfIdxFile, sizeof(unsigned long) +
+	 idh.word_dict_size*sizeof(unsigned long), SEEK_SET);
+  
+  unsigned long tagNum;
+  unsigned long tagPtr;
+  dict_el thisEl;
+  for (tagNum = 0; tagNum < idh.tag_dict_size; ++tagNum) {
+    thisEl.Read (dictFile);
+    ReadUL (invfIdxFile, tagPtr);
+    tagDict[thisEl.el].tagNum = tagNum;
+    tagDict[thisEl.el].tagPtr = tagPtr;
+    tagDict[thisEl.el].fragOccur = thisEl.frag_occur;
+  }
+}
+
+static void AddWeight (Weights &w,
+		       unsigned long levelDocNum,
+		       unsigned long termFreq,
+		       float idf) {
+  double weight = termFreq * idf;
+  w[levelDocNum-1] += weight * weight;
+}
+
+static void GenerateLevelWeights (const invf_dict_header &idh,
+				  const invf_file_header &ifh,
+				  unsigned long numLevelDocs,
+				  unsigned long levelNum,
+				  FILE *dictFile,
+				  FILE *invfFile,
+				  FILE *invfIdxFile,
+				  const FragLevelConvert &fragLevelConvert,
+				  Weights &w) {
+  // pre-allocate the right number of weights
+  w.erase (w.begin(), w.end());
+  w.insert (w.end(), (Weights::size_type)numLevelDocs, (float)0.0);
+
+  double logN = log ((double) numLevelDocs);
+
+  // reset the files
+  fseek (dictFile, idh.word_dict_start, SEEK_SET);
+  fseek (invfIdxFile, sizeof (unsigned long), SEEK_SET);
+  
+  // process each word adding its contributions to the document weights
+  unsigned long wordNum;
+  unsigned long wordStart;
+  word_dict_el wordEl;
+  wordEl.SetNumLevels (idh.num_levels);
+  for (wordNum=0; wordNum<idh.word_dict_size; ++wordNum) {
+#ifndef SILENT
+    // give a little feedback every 4096 words
+    if ((wordNum & 0xfff) == 0) fprintf (stderr, ".");
+#endif
+    
+    wordEl.Read (dictFile, idh.num_levels);
+    ReadUL (invfIdxFile, wordStart);
+
+    float idf = logN - log ((double) wordEl.levelFreqs[levelNum]);
+
+    // seek to the appropriate place in the inverted file
+    fseek (invfFile, wordStart, SEEK_SET);
+    stdio_bitio_buffer buffer (invfFile);
+    
+    unsigned long B = BIO_Bblock_Init (idh.num_frags, wordEl.frag_occur);
+    unsigned long fragNum = 0;
+    unsigned long levelDocNum = 0;
+    unsigned long lastLevelDocNum = 0;
+    unsigned long termFreq = 0;
+    unsigned long checkLevelFreq = 0;
+    
+    unsigned long count, i;
+    for (i=0; i<wordEl.frag_occur; ++i) {
+      fragNum += buffer.bblock_decode (B, NULL);
+      if (!ifh.word_level_index) count = buffer.gamma_decode (NULL);
+      else count = 1;
+
+      if (fragNum > idh.num_frags)
+	FatalError (1, "fragNum = %d, "
+		    "number of fragments = %d\n"
+		    "wordNum = %d\n"
+		    "i = %d, frag_occur = %d\n",
+		    fragNum, idh.num_frags, wordNum, i, wordEl.frag_occur);
+
+      if (!fragLevelConvert.FragToLevel (fragNum, levelDocNum))
+	FatalError (1, "could not convert fragment number %d in level %d", fragNum, levelNum);
+
+      if (levelDocNum == 0 || levelDocNum > numLevelDocs)
+	FatalError (1, "bad level document number %d in level %d", levelDocNum, levelNum);
+      
+      if (levelDocNum != lastLevelDocNum) {
+	// new level document
+	if (lastLevelDocNum > 0) {
+	  AddWeight (w, lastLevelDocNum, termFreq, idf);
+	  ++checkLevelFreq;
+	}
+	lastLevelDocNum = levelDocNum;
+	termFreq = 0;
+      }
+      termFreq += count;
+    }
+
+    if (lastLevelDocNum > 0) {
+      AddWeight (w, lastLevelDocNum, termFreq, idf);
+      ++checkLevelFreq;
+    }
+
+    if (checkLevelFreq != wordEl.levelFreqs[levelNum]) {
+      cerr << "bad level freq at level " <<levelNum<<" "<< checkLevelFreq << " != "
+	   << wordEl.levelFreqs[levelNum] << ", word \""
+	   << wordEl.el << "\" (" << wordNum << ")\n";
+      exit (1);
+    }
+    
+    buffer.done();
+  }
+
+  if (w.size() != numLevelDocs) 
+    FatalError (1, "wrong number of weights created %d != %d",
+		w.size(), numLevelDocs);
+}
+
+static void WriteExactWeights (FILE *weightsFile,
+			       unsigned long &diskPtr,
+			       const Weights &w) {
+  diskPtr = ftell(weightsFile);
+
+  Weights::const_iterator here = w.begin();
+  Weights::const_iterator end = w.end();
+  while (here != end) {
+//      cout << *here << "\n";
+    WriteF (weightsFile, sqrt (*here));
+    ++here;
+  }
+}
+
+static void WriteApproxWeights (FILE *approxWeightsFile,
+				unsigned long &diskPtr,
+				const Weights &w,
+				unsigned char bits) {
+  diskPtr = ftell(approxWeightsFile);
+
+  // calculate L, U and B
+  double L = 1e300;
+  double U = 0;
+  float wgt;
+  Weights::const_iterator here = w.begin();
+  Weights::const_iterator end = w.end();
+  while (here != end) {
+    wgt = sqrt (*here);
+    if (wgt > U) U = wgt;
+    if (wgt > 0 && wgt < L) L = wgt;
+    ++here;
+  }
+
+  double B = pow (U / L, pow (2.0, -(double) bits));
+
+#ifndef SILENT
+  fprintf (stderr, "L = %f\n", L);
+  fprintf (stderr, "U = %f\n", U);
+  fprintf (stderr, "B = %f\n", B);
+#endif
+  
+  WriteUC (approxWeightsFile, bits);
+  WriteD (approxWeightsFile, L);
+  WriteD (approxWeightsFile, B);
+  
+
+  unsigned long max = (bits == 32) ? 0xffffffff : (1 << bits) - 1;;
+  unsigned long i=0, buf=0, pos=0;
+  here = w.begin();
+  end = w.end();
+  while (here != end) {
+    unsigned long fx;
+    wgt = sqrt (*here);
+    if (wgt == 0) {
+      wgt = L;
+#ifndef SILENT
+      Message ("Warning: Document %d had a weight of 0.", i);
+#endif
+    }
+    fx = (unsigned long) floor (log (wgt / L) / log (B));
+
+    if (fx > max) fx = max;
+
+    buf |= (fx << pos);
+    pos += bits;
+
+    if (pos >= MAXBITS) {
+      WriteUL (approxWeightsFile, buf);
+      buf = fx >> (bits - (pos - MAXBITS));
+      pos = pos - MAXBITS;
+    }
+
+    ++here; ++i;
+  }
+
+  // write out the last bits
+  if (pos > 0) WriteUL (approxWeightsFile, buf);
+}
+
+int main (int argc, char **argv) {
+  unsigned char bits = 8;
+  char *filename = "";
+  int ch;
+  opterr = 0;
+  msg_prefix = argv[0];
+
+  while ((ch = getopt (argc, argv, "f:d:b:h")) != -1) {
+    switch (ch) {
+    case 'f':		// input file
+      filename = optarg;
+      break;
+    case 'd':
+      set_basepath (optarg);
+      break;
+    case 'b':
+      bits = atoi (optarg);
+      if (bits > 32) {
+	fprintf (stderr, "b may only take values 0-32\n");
+	exit (1);
+      }
+      break;
+    case 'h':
+    case '?':
+      fprintf (stderr, "usage: %s [-f input_file]"
+	       "[-d data directory] [-b bits] [-h]\n", argv[0]);
+      exit (1);
+    }
+  }
+
+  
+  // open the dictionary
+  FILE *dictFile = open_file (filename, INVF_DICT_SUFFIX, "rb",
+			      MAGIC_STEM_BUILD, MG_ABORT);
+  invf_dict_header idh;
+  idh.Read (dictFile);
+
+  // open the inverted file
+  FILE *invfFile = open_file (filename, INVF_SUFFIX, "rb",
+			MAGIC_INVF, MG_ABORT);
+  invf_file_header ifh;
+  ifh.Read (invfFile);
+  if (ifh.skip_mode != SKIP_MODE_NO_SKIPS)
+    FatalError (1, "The invf file contains skips. Unable to create weights.");
+
+  // open the inverted index file
+  FILE *invfIdxFile = open_file (filename, INVF_IDX_SUFFIX, "rb",
+				 MAGIC_INVI, MG_ABORT);
+  
+  // read the level information
+  FILE *levelFile = open_file (filename, INVF_LEVEL_SUFFIX, "rb",
+			       MAGIC_INVF_LEVELS, MG_ABORT);
+  FIvfLevel ivfLevel;
+  ivfLevel.Read (levelFile);
+  fclose (levelFile);
+
+  // read in the tag dictionary and inverted file pointers
+  WBTagDict tagDict;
+  ReadTagDict (idh, dictFile, invfIdxFile, tagDict);
+
+  
+  // create the weights file
+  FILE *weightsFile = create_file (filename, WEIGHTS_SUFFIX, "wb",
+				   MAGIC_WGHT, MG_ABORT);
+
+  // create the approx weights file
+  FILE *approxWeightsFile = create_file (filename, APPROX_WEIGHTS_SUFFIX, "wb",
+					 MAGIC_WGHT_APPROX, MG_ABORT);
+
+  
+  // create weights for each document level
+  FragLevelConvert fragLevelConvert;
+  Weights w;
+  IvfLevelInfoMap::iterator levelHere = ivfLevel.levelInfo.begin();
+  IvfLevelInfoMap::iterator levelEnd = ivfLevel.levelInfo.end();
+  unsigned long levelNum = 0;
+  while (levelHere != levelEnd) {
+    const UCArray &levelName = (*levelHere).first;
+    
+    // read the tag information about this level
+    fragLevelConvert.Read(invfFile, tagDict[levelName].tagPtr,
+			  idh.num_frags, tagDict[levelName].fragOccur);
+    
+    // create the weights for this level
+    GenerateLevelWeights (idh, ifh, tagDict[levelName].fragOccur,
+			  levelNum, dictFile, invfFile, invfIdxFile,
+			  fragLevelConvert, w);
+
+    // write out the exact weights
+    WriteExactWeights (weightsFile,
+		       (*levelHere).second.exactWeightsDiskPtr,
+		       w);
+    
+    // write out the approximate weights
+    WriteApproxWeights (approxWeightsFile,
+			(*levelHere).second.approxWeightsDiskPtr,
+			w, bits);
+    
+    ++levelHere; ++levelNum;
+  }
+  
+
+  // close input files
+  fclose (dictFile);
+  fclose (invfFile);
+  fclose (invfIdxFile);
+
+  // update the level information
+  levelFile = create_file (filename, INVF_LEVEL_SUFFIX, "wb",
+			   MAGIC_INVF_LEVELS, MG_ABORT);
+  ivfLevel.Write (levelFile);
+  fclose (levelFile);
+
+  // close output files
+  fclose (weightsFile);
+  fclose (approxWeightsFile);
+
+
+  return 0;
+}
Index: /indexers/branches/3.03a/mgpp/text/stemmer.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/stemmer.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/stemmer.cpp	(revision 14757)
@@ -0,0 +1,141 @@
+/**************************************************************************
+ *
+ * stemmer.cpp -- The stemmer/case folder
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#include "sysfuncs.h"
+#include "stemmer.h"
+#include "lovinstem.h"
+#include "simplefrenchstem.h"
+#include "unitool.h"
+
+#ifdef ENABLE_ACCENTFOLD
+/* [JFG - Mar 06: Accent folding patch] */
+#include "unac.h"
+#endif
+
+#define LOVINSTEMMER        0
+#define SIMPLEFRENCHSTEMMER 1
+
+
+/* decode the utf-8 encoded unicode, casefold and then recode 
+ * making sure the final length doesn't exceed the original
+ * length */
+static void mgpp_unicode_casefold (u_char *word) {
+  unsigned short out[256]; /* temp space */
+  int i;
+  int len;
+
+  /* decode */
+  utf8_word_to_unicode (word, out, 255);
+  len = out[0];
+
+  /* casefold and simplify-fold */
+  for (i=0; i<len; ++i) {
+    out[i+1] = unicode_tosimplified(unicode_tolower(out[i+1]));
+  }
+
+  /* re-code */
+  unicode_to_utf8_word (out, word, word[0]+1);
+}
+
+#ifdef ENABLE_ACCENTFOLD
+/* [JFG - Mar 06: Accent folding patch] */
+/* =========================================================================
+ * Function: unicode_accentfold
+ 
+ * Description: remove accents from characters
+ * Input: a word string with the length in the first byte
+ * Output: the unaccented word
+ * ========================================================================= */
+void mgpp_unicode_accentfold (unsigned char *word) {      
+  size_t unac_size = 0;
+  char *unac = NULL;
+
+
+  unac_string("utf-8", (char*)word+1, word[0], &unac, &unac_size);
+  strncpy((char*)word+1, unac, word[0]+1);
+  word[0] = unac_size;
+  
+  free(unac);
+  return;
+}
+#endif
+      
+int mgpp_stemmernumber (u_char *stemmerdescription) {
+  u_char descript[MAX_STEM_DESCRIPTION_LEN];
+  int i;
+
+  /* copy and case-fold the description */
+  for (i=0; (stemmerdescription[i] != '\0') && 
+	 (i < MAX_STEM_DESCRIPTION_LEN-1); ++i)
+    descript[i] = tolower (stemmerdescription[i]);
+  descript[i] = '\0';
+
+  /* map the description to its number */
+
+  if ((strcmp ((char *) descript,  "0") == 0) ||
+      (strcmp ((char *) descript, "english") == 0) ||
+      (strcmp ((char *) descript, "lovin") == 0))
+    return LOVINSTEMMER;
+
+  if ((strcmp ((char *) descript, "1") == 1) ||
+      (strcmp ((char *) descript, "french") == 0) ||
+      (strcmp ((char *) descript, "simplefrench") == 0))
+    return SIMPLEFRENCHSTEMMER;
+
+  return -1;
+}
+
+
+
+/*
+ * Method 0 - Do not stem or case fold.
+ * Method 1 - Case fold.
+ * Method 2 - Stem.
+ * Method 3 - Case fold and stem.
+ * Method 4 - Accent fold
+ * Method 5 - Accent fold and case fold
+ * Method 6 - Accent fold and stem
+ * Method 7 - Accent fold, stem and case fold
+
+ * The stemmer number should be obtained using
+ * the stemmernumber function above.
+ */
+void 
+mgpp_stemmer (int method, int stemmer, u_char *word) {
+  if (method & STEM_CaseFolding) {
+    mgpp_unicode_casefold (word);
+  }
+
+#ifdef ENABLE_ACCENTFOLD
+  if (method & STEM_AccentFolding) {
+    mgpp_unicode_accentfold (word);
+  }
+#endif
+
+  if (method & STEM_Stemming) {
+    switch (stemmer) {
+    case LOVINSTEMMER: lovinstem (word);
+      break;
+    case SIMPLEFRENCHSTEMMER: simplefrenchstem (word);
+      break;
+    }
+  }
+}
Index: /indexers/branches/3.03a/mgpp/text/stemmer.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/stemmer.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/stemmer.h	(revision 14757)
@@ -0,0 +1,90 @@
+/**************************************************************************
+ *
+ * stemmer.h -- The stemmer/case folder
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef STEMMER_H
+#define STEMMER_H
+
+/* [RPAP - Jan 97: Stem Index Change] */
+/* [JFG - Mar 06: Accent folding patch] */
+enum stemMethods {
+	STEM_None		=	0,
+	STEM_CaseFolding	=	0x1,
+	STEM_Stemming      	=	0x2,
+	STEM_AccentFolding 	=	0x4,
+};
+
+/* This is for the QueryParser */
+#define CHAR_FLAG_STEM_CaseFold    'i'	// ignore case
+#define CHAR_FLAG_STEM_NoCaseFold  'c'	// case sensitive
+#define CHAR_FLAG_STEM_Stemming    's'	// stem words
+#define CHAR_FLAG_STEM_NoStemming  'u'	// do not stem words
+#define CHAR_FLAG_STEM_AccentFold  'f'	// accent fold
+#define CHAR_FLAG_STEM_NoAccentFold  'a'	// do no accent folding
+#define CHAR_FLAG_STEM_Validator  "icsufa"	// all of the above
+
+
+#define STEM_MIN 1
+#define STEM_MAX (STEM_CaseFolding | STEM_Stemming | STEM_AccentFolding)
+#define STEM_PARTIAL_MATCH  (STEM_MAX+1)
+#define STEM_INVALID        (STEM_MAX+2)
+
+#define STEMMER_MASK 3
+#define MAX_STEM_DESCRIPTION_LEN 16
+
+/* stemmernumber will return the stemmer for
+ * a description of the stemmer. Stemmer descriptions
+ * are not case sensitive. Valid descriptions are:
+ *
+ *   'English'
+ *   'Lovin'
+ *   'French'
+ *   'SimpleFrench'
+ *
+ * More than one description might result in the same
+ * stemmer number (for example, for stemming 'English'
+ * we currently use the 'Lovin' stemmer).
+ *
+ * stemmerdescription is a normal C, null-terminated,
+ * string.
+ *
+ * stemmernumber will return -1 if it doesn't know the
+ * stemmer description.
+ */
+int mgpp_stemmernumber (unsigned char *stemmerdescription);
+
+/*
+ * Method 0 - Do not stem or case fold.
+ * Method 1 - Case fold.
+ * Method 2 - Stem.
+ * Method 3 - Case fold and stem.
+ * Method 4 - Accent fold
+ * Method 5 - Case fold and accent fold
+ * Method 6 - Stem and accent fold
+ * Method 7 - Case fold, stem and accent fold
+ * The stemmer number should be obtained using function
+ * stemmernumber above.
+ */
+#ifdef __cplusplus
+extern "C" 
+#endif
+void mgpp_stemmer (int method, int stemmer, unsigned char * word);
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/text.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/text.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/text.cpp	(revision 14757)
@@ -0,0 +1,146 @@
+/**************************************************************************
+ *
+ * text.h -- Header file for compression related stuff
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+// UCArray currently contains all the basic reading and writing functions
+#include "UCArray.h"
+#include "text.h"
+
+compressed_text_header::compressed_text_header () {
+  Clear();
+}
+
+void compressed_text_header::Clear () {
+  num_of_docs = 0;
+  num_of_words = 0;
+  num_of_bytes = 0.0;
+}
+
+
+bool compressed_text_header::Read (FILE *f) {
+  return (ReadUL (f, num_of_docs) &&
+	  ReadUL (f, num_of_words) &&
+	  ReadD (f, num_of_bytes));
+}
+
+bool compressed_text_header::Write (FILE *f) const {
+  return (WriteUL (f, num_of_docs) &&
+	  WriteUL (f, num_of_words) &&
+	  WriteD (f, num_of_bytes));
+}
+
+
+auxiliary_dict::auxiliary_dict () {
+  word_data[0] = NULL;
+  word_data[1] = NULL;
+  words[0] = NULL;
+  words[1] = NULL;
+}
+
+auxiliary_dict::~auxiliary_dict () {
+  Clear ();
+}
+
+void auxiliary_dict::Clear () {
+  if (word_data[0] != NULL) {
+    delete []word_data[0];
+    word_data[0] = NULL;
+  }
+  if (word_data[1] != NULL) {
+    delete []word_data[1];
+    word_data[1] = NULL;
+  }
+  if (words[0] != NULL) {
+    delete []words[0];
+    words[0] = NULL;
+  }
+  if (words[1] != NULL) {
+    delete []words[1];
+    words[1] = NULL;
+  }
+}
+
+
+compression_dict::compression_dict () {
+  int which;
+  for (which = 0; which < 2; ++which) {
+    cfh[which] = NULL;
+    values[which] = NULL;
+    escape[which] = NULL;
+    chars_huff[which] = NULL;
+    chars_vals[which] = NULL;
+    lens_huff[which] = NULL;
+    lens_vals[which] = NULL;
+  }
+
+  MemForCompDict = 0;
+  ad = NULL;
+  fast_loaded = 0;
+}
+
+compression_dict::~compression_dict () {
+  Clear ();
+}
+
+void compression_dict::Clear () {
+  int which;
+  for (which = 0; which < 2; ++which) {
+    if (cfh[which] != NULL) {
+      delete cfh[which];
+      cfh[which] = NULL;
+    }
+    if (values[which] != NULL) {
+      delete []values[which][0][0];
+      delete []values[which][0];
+      delete []values[which];
+      values[which] = NULL;
+    }
+    if (escape[which] != NULL) { // don't know if needed
+      //delete escape[which]; // this was causing a seg fault
+      escape[which] = NULL;
+    }
+    if (chars_huff[which] != NULL) {
+      delete chars_huff[which];
+      chars_huff[which] = NULL;
+    }
+    if (chars_vals[which] != NULL) {
+      delete []chars_vals[which][0];
+      delete []chars_vals[which];
+      chars_vals[which] = NULL;
+    }
+    if (lens_huff[which] != NULL) {
+      delete lens_huff[which];
+      lens_huff[which] = NULL;
+    }
+    if (lens_vals[which] != NULL) {
+      delete []lens_vals[which][0];
+      delete []lens_vals[which];
+      lens_vals[which] = NULL;
+    }
+  }
+
+  if (ad != NULL) {
+    delete ad;
+    ad = NULL;
+  }
+
+  MemForCompDict = 0;
+  fast_loaded = 0;
+}
Index: /indexers/branches/3.03a/mgpp/text/text.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/text.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/text.h	(revision 14757)
@@ -0,0 +1,199 @@
+/**************************************************************************
+ *
+ * text.h -- Header file for compression related stuff
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#ifndef H_TEXT
+#define H_TEXT
+
+// some elderly windows compilers need to include <vector> (or something
+// similar) here so that they know what a "bool" is
+#if defined(GSDL_USE_OBJECTSPACE)
+#  include <ospace\std\vector>
+#elif defined(GSDL_USE_STL_H)
+#  include <vector.h>
+#else
+#  include <vector>
+#endif
+
+
+#include "huffman.h"
+#include <stdio.h>
+
+/*****************************************************************************
+ *
+ * There are several different methods of compressing the text of the
+ * database. The following defines list the different methods of text
+ * compression
+ *
+ */
+
+
+/* The dictionary contains all the fragments that occur in the collection
+   i.e. escapes are not possible */
+#define MG_COMPLETE_DICTIONARY 0
+
+
+/* Certain words have been deleted from the dictionary. The words deleted
+   have been used to create the frequency huffman codes of the characters. 
+   This dictionary has an escape code and may be used to compress novel
+   words. This dictionary may fail if there is a novel character. */
+#define MG_PARTIAL_DICTIONARY 1
+
+
+/* This dictionary has an escape so that novel words and non-words can be 
+   coded. The method for coding the novel words and non-words is determined
+   by a dictionary parameter. */
+#define MG_SEED_DICTIONARY 2
+
+
+
+
+
+
+
+
+
+/*****************************************************************************
+ *
+ * With a seed dictionary there are several methods for coding the novel
+ * words and non-words the following defined values specify the different
+ * methods of coding.
+ *
+ */
+
+
+/* Code novel words and non-words character by character using huffman codes.
+   The huffman codes for the word and non-word lengths and characters are 
+   generated from the distribution of lengths and characters in the
+   dictionary. */
+#define MG_NOVEL_HUFFMAN_CHARS 0
+
+
+/* This method codes novel words using delta codes. The novel words are stored
+   in a auxillary dictionary which is built by pass two. */
+#define MG_NOVEL_DELTA 2
+
+
+/* This method codes novel words using hybrid version of delta. The novel
+   words are stored in a auxillary dictionary which is built by pass two. */
+#define MG_NOVEL_HYBRID 3
+
+
+
+
+
+
+/* This specified an amount of extra space allocated in the
+   compression_dict_header for adding new parameters. As new
+   parameters are added this should be decreased. */
+#define TEXT_PARAMS 15
+
+
+
+struct compression_dict_header {
+  u_long dict_type;
+  u_long novel_method;
+  u_long params[TEXT_PARAMS];
+  u_long num_words[2];
+  u_long num_word_chars[2];
+  u_long lookback;
+};
+
+
+struct comp_frags_header {
+  huff_data hd;
+  u_long uncompressed_size;
+  u_long huff_words_size[MAX_HUFFCODE_LEN + 1];
+};
+
+// BOGUSTEXTLEN is used to replace the ratio
+// in the compressed_text_header while preparing
+// for UCArray
+#define BOGUSTEXTLEN 1000000
+
+struct compressed_text_header {
+  u_long num_of_docs;
+  u_long num_of_words; // number of words in collection
+  double num_of_bytes;
+
+  compressed_text_header ();
+  void Clear ();
+
+  // you must seek to the appropriate place before calling
+  // Read or Write
+  bool Read (FILE *f);
+  bool Write (FILE *f) const;
+};
+
+
+struct compression_stats_header {
+  u_long num_docs;
+  u_long dummy;     // alignment
+  double num_bytes; 
+};
+
+
+struct frags_stats_header {
+  u_long num_frags;
+  u_long mem_for_frags;
+};
+
+
+struct aux_frags_header {
+  u_long num_frags;
+  u_long mem_for_frags;
+};
+
+
+struct auxiliary_dict {
+  aux_frags_header afh[2];
+  u_char *word_data[2];
+  u_char **words[2];
+  int blk_start[2][33], blk_end[2][33];	/* blk_start and blk_end are required
+					   for the hybrid methods */
+
+  auxiliary_dict ();
+  ~auxiliary_dict ();
+
+  void Clear ();
+};
+
+
+struct compression_dict {
+  compression_dict_header cdh;
+  comp_frags_header *cfh[2];
+  unsigned long MemForCompDict;
+  u_char ***values[2];
+  u_char *escape[2];
+  huff_data *chars_huff[2];
+  u_long **chars_vals[2];
+  huff_data *lens_huff[2];
+  u_long **lens_vals[2];
+  auxiliary_dict *ad;
+  int fast_loaded;
+
+  compression_dict ();
+  ~compression_dict ();
+
+  void Clear ();
+};
+
+
+#endif
Index: /indexers/branches/3.03a/mgpp/text/text.pass1.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/text.pass1.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/text.pass1.cpp	(revision 14757)
@@ -0,0 +1,388 @@
+/**************************************************************************
+ *
+ * text.pass1.cpp -- Text compression (Pass 1)
+ * Copyright (C) 1994  Neil Sharman, Gary Eddy and Alistair Moffat
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "messages.h"
+#include "huffman.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+#include "mg_files.h"
+#include "mg.h"
+#include "build.h"
+#include "locallib.h"
+#include "words.h"
+#include "text.h"
+#include "hash.h"
+#include "local_strings.h"
+#include "TextEl.h"
+
+/* for more meaningful messages - jrm21 (gsdl) */
+#ifdef HAVE_STRERROR
+#include <string.h>
+#include <errno.h>
+#endif
+
+
+#define POOL_SIZE 1024*1024
+#define INITIAL_HASH_SIZE 7927
+
+
+typedef struct hash_rec
+  {
+    unsigned long wcnt;		/* word frequency */
+    unsigned long occurance_num;
+    u_char *word;
+  }
+hash_rec;
+
+typedef struct dict_data
+  {
+    hash_rec *HashTable;
+    unsigned long HashSize;
+    unsigned long HashUsed;
+    unsigned long wordnum;
+    unsigned long words_read;
+    unsigned long bytes_diff;
+    huff_data hd;
+  }
+dict_data;
+
+
+
+static unsigned long longestDoc = 0;
+static unsigned long occurance_num = 0;
+static dict_data DictData[2];
+
+static u_char *Pool;
+static int PoolLeft;
+static double inputbytes = 0; /* [RJM 07/97: 4G limit] */
+static unsigned long MaxMemInUse = 0;
+static unsigned long MemInUse = 0;
+static compression_stats_header csh = {0, 0, 0.0}; /* [RJM 07/97: 4G limit] */
+
+
+static void ChangeMem (int Change) {
+  MemInUse += Change;
+  if (MemInUse > MaxMemInUse) MaxMemInUse = MemInUse;
+}
+
+
+int init_text_1 (const TagInfo &/*tagInfo*/, char * /*FileName*/) {
+  int which;
+  
+  if (!(Pool = (u_char *) Xmalloc (POOL_SIZE))) {
+    Message ("Unable to allocate memory for pool");
+    return (COMPERROR);
+  }
+  PoolLeft = POOL_SIZE;
+  ChangeMem (POOL_SIZE);
+  
+  for (which = 1; which >= 0; --which) {
+    u_char *word;
+    hash_rec *ent;
+    dict_data *dd = &DictData[which];
+    
+    dd->wordnum = 0;
+    dd->words_read = 0;
+    dd->bytes_diff = 0;
+    dd->HashSize = INITIAL_HASH_SIZE;
+    dd->HashUsed = 0;
+    
+    if (!(dd->HashTable = (hash_rec *) Xmalloc (sizeof (hash_rec) * dd->HashSize))) {
+      Message ("Unable to allocate memory for table");
+      return (COMPERROR);
+    }
+    ChangeMem (sizeof (hash_rec) * dd->HashSize);
+    memset (dd->HashTable,'\0' , sizeof (hash_rec) * dd->HashSize);
+
+    word = Pool;
+    *Pool++ = '\0';
+    --PoolLeft;
+    {
+      register u_char *wptr;
+      register int hsize = dd->HashSize;
+      register unsigned long hashval, step;
+      
+      HASH (hashval, step, word, hsize);
+      wptr = (dd->HashTable + hashval)->word;
+      while (wptr) {
+	hashval += step;
+	if (hashval >= (unsigned long)hsize)
+	  hashval -= hsize;
+	wptr = (dd->HashTable + hashval)->word;
+      }
+      ent = dd->HashTable + hashval;
+    }
+    ent->wcnt = 1;
+    ent->word = word;
+    dd->HashUsed = 1;
+  }
+  return (COMPALLOK);
+}
+
+
+static int process_text_element (const u_char *s_in, int l_in) {
+  const u_char *end = s_in + l_in - 1;
+  
+   /*
+   ** Alternately parse off words and non-words from the input
+   ** stream beginning with a non-word. Each token is then
+   ** inserted into the set if it does not exist or has it's
+   ** frequency count incremented if it does.
+   */
+  
+  bool which = false; // non-word
+  for (; s_in <= end; which = !which) {
+    u_char Word[MAXWORDLEN + 1];
+    dict_data *dd = &DictData[which];
+    
+    /* First parse a word or non-word out of the string */
+    if (which) PARSE_WORD (Word, s_in, end);
+    else PARSE_NON_WORD (Word, s_in, end);
+    
+    ++dd->wordnum;
+    inputbytes += *Word;
+    ++dd->words_read;
+    
+    /* Search the hash table for Word */
+    {
+      register unsigned long hashval, step;
+      register int hsize = dd->HashSize;
+      HASH (hashval, step, Word, hsize);
+      for (;;) {
+	register u_char *s1;
+	register u_char *s2;
+	register int len;
+	register hash_rec *ent;
+	ent = dd->HashTable + hashval;
+	if (!ent->word) {
+	  int len = *Word + 1;
+	  if (len > PoolLeft) {
+	    if (!(Pool = (u_char *) Xmalloc (POOL_SIZE))) {
+	      Message ("Unable to allocate memory for pool");
+	      return (COMPERROR);
+	    }
+	    PoolLeft = POOL_SIZE;
+	    ChangeMem (POOL_SIZE);
+	  }
+	  ent->occurance_num = occurance_num++;
+	  ent->wcnt = 1;
+	  ent->word = Pool;
+	  memcpy (Pool, Word, len);
+	  Pool += len;
+	  PoolLeft -= len;
+	  ++dd->HashUsed;
+	  dd->bytes_diff += Word[0];
+	  break;
+	}
+	
+	/* Compare the words */
+	s1 = Word;
+	s2 = ent->word;
+	len = *s1 + 1;
+	for (; len; --len)
+	  if (*s1++ != *s2++) break;
+	
+	if (len) {
+	  hashval = (hashval + step);
+	  if (hashval >= (unsigned long)hsize) hashval -= hsize;
+	} else {
+	  ++ent->wcnt;
+	  break;
+	}
+      }
+    }
+
+    
+    if (dd->HashUsed >= dd->HashSize >> 1) {
+      hash_rec *ht;
+      unsigned long size;
+      unsigned long i;
+      size = prime (dd->HashSize * 2);
+      if (!(ht = (hash_rec *) Xmalloc (sizeof (hash_rec) * size))) {
+	Message ("Unable to allocate memory for table");
+	return (COMPERROR);
+      }
+      ChangeMem (sizeof (hash_rec) * size);
+      memset (ht, '\0', sizeof (hash_rec) * size);
+
+      for (i = 0; i < dd->HashSize; ++i)
+	if (dd->HashTable[i].word) {
+	  register u_char *wptr;
+	  register unsigned long hashval, step;
+	  
+	  wptr = dd->HashTable[i].word;
+	  HASH (hashval, step, wptr, size);
+	  wptr = (ht + hashval)->word;
+	  while (wptr) {
+	    hashval += step;
+	    if (hashval >= size) hashval -= size;
+	    wptr = (ht + hashval)->word;
+	  }
+	  ht[hashval] = dd->HashTable[i];
+	}
+      Xfree (dd->HashTable);
+      ChangeMem (-sizeof (hash_rec) * dd->HashSize);
+      dd->HashTable = ht;
+      dd->HashSize = size;
+    }
+  }
+
+  return COMPALLOK;
+}
+
+
+int process_text_1 (const TagInfo &/*tagInfo*/, const TextElArray &doc) {
+  unsigned long textLen = 0;
+  unsigned long docLen = 0;
+  int retValue;
+
+  // process each text element in this document
+  TextElArray::const_iterator here = doc.begin();
+  TextElArray::const_iterator end = doc.end();
+  while (here != end) {
+    textLen = (*here).text.size();
+    docLen += textLen;
+
+    retValue = process_text_element (&(here->text[0]), textLen);
+    if (retValue != COMPALLOK) return retValue;
+    
+    ++here;
+  }
+
+  // get max document length
+  if (docLen > longestDoc) longestDoc = docLen;
+
+  // update header information
+  ++csh.num_docs;
+  csh.num_bytes += docLen;
+  
+  return COMPALLOK;
+}
+
+
+static int PackHashTable (dict_data * dd) {
+  int s, d;
+  for (s = d = 0; (unsigned int)s < dd->HashSize; ++s)
+    if (dd->HashTable[s].word)
+      dd->HashTable[d++] = dd->HashTable[s];
+  
+  ChangeMem (-sizeof (hash_rec) * dd->HashSize);
+  ChangeMem (sizeof (hash_rec) * dd->HashUsed);
+  
+  if (!(dd->HashTable = (hash_rec *) Xrealloc (dd->HashTable,
+			   sizeof (hash_rec) * dd->HashUsed))) {
+    Message ("Out of memory");
+    return COMPERROR;
+  }
+  dd->HashSize = dd->HashUsed;
+  return COMPALLOK;
+}
+
+
+static int ent_comp (const void *s1, const void *s2) {
+  return casecompare (((hash_rec *) s1)->word, ((hash_rec *) s2)->word);
+}
+
+
+static void WriteHashTable (FILE * fp, dict_data * dd) {
+  frags_stats_header fsh;
+  u_long j = 0;
+  u_char *curr;
+
+  if (PackHashTable (dd) == COMPERROR) return;
+  
+  qsort (dd->HashTable, dd->HashUsed, sizeof (hash_rec), ent_comp);
+  
+  fsh.num_frags = dd->HashSize;
+  fsh.mem_for_frags = dd->HashSize;
+  for (j = 0; j < dd->HashSize; ++j)
+    fsh.mem_for_frags += dd->HashTable[j].word[0];
+  
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(fsh.num_frags);
+  HTONUL(fsh.mem_for_frags);
+  
+  fwrite (&fsh, sizeof (fsh), 1, fp);
+  
+  for (j = 0; j < dd->HashSize; ++j) {
+    curr = dd->HashTable[j].word;
+    
+    /* [RPAP - Jan 97: Endian Ordering] */
+    HTONUL(dd->HashTable[j].wcnt);
+    HTONUL(dd->HashTable[j].occurance_num);
+    
+    fwrite (&dd->HashTable[j].wcnt, sizeof (dd->HashTable[j].wcnt), 1, fp);
+    fwrite (&dd->HashTable[j].occurance_num,
+	    sizeof (dd->HashTable[j].occurance_num), 1, fp);
+    
+    /* [RPAP - Jan 97: Endian Ordering] */
+    NTOHUL(dd->HashTable[j].wcnt);
+    NTOHUL(dd->HashTable[j].occurance_num);
+    
+    fwrite (curr, sizeof (u_char), curr[0] + 1, fp);
+  }
+}
+
+
+int done_text_1 (const TagInfo &/*tagInfo*/, char *file_name) {
+  char *temp_str;
+  FILE *fp;
+  
+  if (!(fp = create_file (file_name, TEXT_STATS_DICT_SUFFIX, "wb",
+			  MAGIC_STATS_DICT, MG_MESSAGE)))  /* [RPAP - Feb 97: WIN32 Port] */
+    {
+      fprintf(stderr,"Couldn't create file %s%s:%s\n",
+              file_name, TEXT_STATS_DICT_SUFFIX,
+#if defined(HAVE_STRERROR) || defined(__WIN32__)
+              strerror(errno)
+#else
+	      " "
+#endif
+              );
+      return COMPERROR;
+    }
+
+  temp_str = msg_prefix;
+  msg_prefix = "text.pass1";
+  
+  /* [RPAP - Jan 97: Endian Ordering] */
+  HTONUL(csh.num_docs);
+  HTOND(csh.num_bytes); /* [RJM 07/97: 4G limit] */
+
+  fwrite (&csh, sizeof (csh), 1, fp);
+
+  /* [RPAP - Jan 97: Endian Ordering] */
+  NTOHUL(csh.num_docs);
+  NTOHD(csh.num_bytes); /* [RJM 07/97: 4G limit] */
+
+  WriteHashTable (fp, &DictData[0]);
+  WriteHashTable (fp, &DictData[1]);
+  msg_prefix = temp_str;
+  fclose(fp);
+  return COMPALLOK;
+}
Index: /indexers/branches/3.03a/mgpp/text/text.pass2.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/text.pass2.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/text.pass2.cpp	(revision 14757)
@@ -0,0 +1,585 @@
+/**************************************************************************
+ *
+ * text.pass2.cpp -- Text compression (Pass 2)
+ * Copyright (C) 1994  Neil Sharman, Gary Eddy and Alistair Moffat
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
+#pragma warning(disable:4786)
+#endif
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+#if defined (__WIN32__)
+# include <stdio.h>
+# define unlink _unlink
+#endif
+
+#include "sysfuncs.h"
+#include "memlib.h"
+#include "messages.h"
+#include "local_strings.h"
+#include "bitio_m_stdio.h"
+#include "huffman.h"
+#include "netorder.h"  /* [RPAP - Jan 97: Endian Ordering] */
+#include "mg.h"
+#include "mg_files.h"
+#include "build.h"
+#include "words.h"
+#include "text.h"
+#include "hash.h"
+#include "locallib.h"
+#include "comp_dict.h"
+#include "FText.h"
+
+#define POOL_SIZE 1024*256
+
+
+struct char_pool {
+  struct char_pool *next;
+  u_long left;
+  u_char *ptr;
+  u_char pool[POOL_SIZE];
+};
+
+struct novel_hash_rec {
+  u_long ordinal_num;
+  u_char *word;
+};
+
+
+#define INITIAL_HASH_SIZE 7927
+
+struct novel_hash_table {
+  novel_hash_rec *HashTable;
+  u_long HashSize, HashUsed;
+  char_pool *first_pool;
+  char_pool *pool;
+  u_long next_num, binary_start;
+  novel_hash_rec **code_to_nhr;
+};
+
+
+static FILE *text;
+static stdio_bitio_buffer textOutBuf;
+static u_long headLen;
+
+static novel_hash_table nht[2];
+
+int blk_start[2][33], blk_end[2][33];
+
+// 0 = non-word, 1 = word
+unsigned char whichWordType = 0;
+
+CompressTextInfoMap textInfoMap;
+
+
+static char_pool *new_pool (char_pool * pool) {
+  char_pool *p = (char_pool *) Xmalloc (sizeof (char_pool));
+  if (!p) FatalError (1, "Unable to allocate memory for pool");
+  
+  if (pool) pool->next = p;
+  p->next = NULL;
+  p->left = POOL_SIZE;
+  p->ptr = p->pool;
+  return p;
+}
+
+
+int init_text_2 (const TagInfo &/*tagInfo*/, char *fileName) {
+  char path[512];
+
+  // load the compression dictionary
+  if (LoadCompressionDictionary (make_name (fileName, TEXT_DICT_SUFFIX,
+					    path)) == COMPERROR)
+    return COMPERROR;
+
+  // create the compressed text file and attach it to the text buffer
+  if (!(text = create_file (fileName, TEXT_SUFFIX, "w+b",
+			    MAGIC_TEXT, MG_MESSAGE)))
+    return COMPERROR;
+  textOutBuf.attachFile (text);
+  textOutBuf.encodeStart ();
+  
+  // write out the compressed text header
+  memset (&cth, '\0', sizeof (cth));
+  if (fwrite (&cth, sizeof (cth), 1, text) != 1)
+    return COMPERROR;
+
+  // the length of the compressed header is the size of the
+  // magic number plus the size of the compressed text header
+  headLen = sizeof (u_long) + sizeof (cth);
+
+  // start off with non-word
+  whichWordType = 0;
+
+  // clear the text pointers
+  textInfoMap.erase (textInfoMap.begin(), textInfoMap.end());
+  
+  // set up the hash table of novel words
+  int i;
+  if (cdh.novel_method != MG_NOVEL_HUFFMAN_CHARS)
+    for (i = 0; i <= 1; ++i)
+      {
+	nht[i].HashSize = INITIAL_HASH_SIZE;
+	nht[i].HashTable = (novel_hash_rec *) Xmalloc (sizeof (novel_hash_rec) * nht[i].HashSize);
+	memset (nht[i].HashTable, '\0',
+	       sizeof (novel_hash_rec) * nht[i].HashSize);
+	nht[i].HashUsed = 0;
+	nht[i].HashSize = INITIAL_HASH_SIZE;
+	nht[i].pool = nht[i].first_pool = new_pool (NULL);
+	nht[i].next_num = 1;
+	nht[i].binary_start = 1;
+	nht[i].code_to_nhr = NULL;
+	if (cdh.novel_method == MG_NOVEL_HYBRID)
+	  {
+	    int num;
+	    num = 1;
+	    blk_start[i][0] = 0;
+	    blk_end[i][0] = cdh.num_words[i] - 1;
+	    while (num < 33)
+	      {
+		blk_start[i][num] = blk_end[i][num - 1] + 1;
+		blk_end[i][num] = blk_start[i][num] +
+		  (blk_end[i][num - 1] - blk_start[i][num - 1]) * 2;
+		++num;
+	      }
+	  }
+      }
+
+  return (COMPALLOK);
+}
+
+
+static int compress_text (bitio_buffer &buffer, const u_char *s_in,
+			  int l_in, unsigned char &which,
+			  unsigned long &numWords) {
+  const u_char *end = s_in + l_in - 1;
+
+  for (; s_in <= end; which = !which) {
+    u_char Word[MAXWORDLEN + 1];
+    int res;
+    
+    if (which) ++numWords;
+
+    /* First parse a word or non-word out of the string */
+    if (which) PARSE_WORD (Word, s_in, end);
+    else PARSE_NON_WORD (Word, s_in, end);
+
+    /* Search the hash table for Word */
+    if (ht[which]) {
+      register unsigned long hashval, step;
+      register int tsize = ht[which]->size;
+      register u_char **wptr;
+      HASH (hashval, step, Word, tsize);
+      for (;;) {
+	register u_char *s1;
+	register u_char *s2;
+	register int len;
+	wptr = ht[which]->table[hashval];
+	if (wptr == NULL) {
+	  res = COMPERROR;
+	  break;
+	}
+
+	/* Compare the words */
+	s1 = Word;
+	s2 = *wptr;
+	len = *s1 + 1;
+	for (; len; --len)
+	  if (*s1++ != *s2++) break;
+	
+	if (len) {
+	  hashval += step;
+	  if (hashval >= (unsigned long)tsize) hashval -= tsize;
+	  
+	} else {
+	  res = ht[which]->table[hashval] - ht[which]->words;
+	  break;
+	}
+      }
+    }
+    else
+      res = COMPERROR;
+    /* Check that the word was found in the dictionary */
+    if (res == COMPERROR)
+      {
+	if (cdh.dict_type == MG_COMPLETE_DICTIONARY)
+	  {
+	    Message ("Unknown word \"%.*s\"\n", *Word, Word + 1);
+	    return (COMPERROR);
+	  }
+	if (cdh.dict_type == MG_PARTIAL_DICTIONARY)
+	  {
+	    u_long i;
+	    if (ht[which])
+	      {
+		res = ht[which]->hd->num_codes - 1;
+		buffer.huff_encode (res, ht[which]->codes, ht[which]->hd->clens, NULL);
+	      }
+	    buffer.huff_encode (Word[0], lens_codes[which], lens_huff[which].clens, NULL);
+	    for (i = 0; i < Word[0]; ++i)
+	      buffer.huff_encode (Word[i + 1], char_codes[which],
+				  char_huff[which].clens, NULL);
+	  }
+	if (cdh.dict_type == MG_SEED_DICTIONARY)
+	  {
+	    if (ht[which])
+	      {
+		res = ht[which]->hd->num_codes - 1;
+		buffer.huff_encode (res, ht[which]->codes, ht[which]->hd->clens, NULL);
+	      }
+	    switch (cdh.novel_method)
+	      {
+	      case MG_NOVEL_HUFFMAN_CHARS:
+		{
+		  u_long i;
+		  buffer.huff_encode (Word[0], lens_codes[which],
+				      lens_huff[which].clens, NULL);
+		  for (i = 0; i < Word[0]; ++i)
+		    buffer.huff_encode (Word[i + 1], char_codes[which],
+					char_huff[which].clens, NULL);
+		}
+		break;
+	      case MG_NOVEL_DELTA:
+	      case MG_NOVEL_HYBRID:
+		{
+		  register unsigned long hashval, step;
+		  register novel_hash_table *h = &nht[which];
+		  register int hsize = h->HashSize;
+		  register novel_hash_rec *ent;
+		  HASH (hashval, step, Word, hsize);
+		  for (;;)
+		    {
+		      register u_char *s1, *s2;
+		      register int len;
+		      ent = h->HashTable + hashval;
+		      if (!ent->word)
+			{
+			  int len = *Word + 1;
+			  if ((unsigned)len > h->pool->left)
+			    h->pool = new_pool (h->pool);
+			  ent->word = h->pool->ptr;
+			  ent->ordinal_num = h->next_num++;
+			  memcpy (h->pool->ptr, Word, len);
+			  h->pool->ptr += len;
+			  h->pool->left -= len;
+			  ++h->HashUsed;
+			  break;
+			}
+		      /* Compare the words */
+		      s1 = Word;
+		      s2 = ent->word;
+		      len = *s1 + 1;
+		      for (; len; --len)
+			if (*s1++ != *s2++)
+			  break;
+		      
+		      if (!len)
+			break;
+		      
+		      hashval = (hashval + step);
+		      if (hashval >= (unsigned)hsize) hashval -= hsize;
+		    }
+		  
+		  switch (cdh.novel_method) {
+		  case MG_NOVEL_DELTA:
+		    buffer.delta_encode (ent->ordinal_num, NULL);
+		    break;
+		  case MG_NOVEL_HYBRID:
+		    int k = 0;
+		    int j = ent->ordinal_num - 1;
+		    while (j > blk_end[which][k])
+		      ++k;
+		    assert (j - blk_start[which][k] + 1 >= 1 &&
+			    j - blk_start[which][k] + 1 <=
+			    blk_end[which][k] - blk_start[which][k] + 1);
+		    
+		    buffer.gamma_encode (k + 1, NULL);
+		    buffer.binary_encode (j - blk_start[which][k] + 1,
+					  blk_end[which][k] - blk_start[which][k] + 1,
+					  NULL);
+		    break;
+		  }
+		  
+		  if (h->HashUsed >= h->HashSize >> 1)
+		    {
+		      novel_hash_rec *ht;
+		      unsigned long size;
+		      unsigned long i;
+		      size = prime (h->HashSize * 2);
+		      if (!(ht = (novel_hash_rec *) Xmalloc (sizeof (novel_hash_rec) * size)))
+			{
+			  Message ("Unable to allocate memory for table");
+			  return (COMPERROR);
+			}
+		      memset (ht, '\0', sizeof (novel_hash_rec) * size);
+		      
+		      for (i = 0; i < h->HashSize; ++i)
+			if (h->HashTable[i].word)
+			  {
+			    register u_char *wptr;
+			    register unsigned long hashval, step;
+			    
+			    wptr = h->HashTable[i].word;
+			    HASH (hashval, step, wptr, size);
+			    wptr = (ht + hashval)->word;
+			    while (wptr)
+			      {
+				hashval += step;
+				if (hashval >= size)
+				  hashval -= size;
+				wptr = (ht + hashval)->word;
+			      }
+			    ht[hashval] = h->HashTable[i];
+			  }
+		      Xfree (h->HashTable);
+		      h->HashTable = ht;
+		      h->HashSize = size;
+		    }
+		}
+		break;
+	      }
+	  }
+      }
+    else
+      {
+	buffer.huff_encode (res, ht[which]->codes, ht[which]->hd->clens, NULL);
+      }
+  }
+  
+  return COMPALLOK;
+}
+
+
+int process_text_2 (const TagInfo &tagInfo, const TextElArray &doc) {
+  // we need to remember where the last text element ends
+  unsigned char endBit = textOutBuf.GetBtg (); // 8=high bit, 1=low bit
+  unsigned long endPos = textOutBuf.GetBytesWritten () + headLen;
+
+  // process each text element
+  TextElArray::const_iterator here = doc.begin();
+  TextElArray::const_iterator end = doc.end();
+  while (here != end) {
+    // remember current place in compressed text
+    unsigned char startWhich = whichWordType;
+    unsigned char startBit = textOutBuf.GetBtg (); // 8=high bit, 1=low bit
+    unsigned long startPos = textOutBuf.GetBytesWritten () + headLen;
+
+    // compress the text
+    if (compress_text (textOutBuf,
+		       &(here->text[0]),
+		       (*here).text.size(),
+		       whichWordType,
+		       cth.num_of_words) != COMPALLOK)
+      return COMPERROR;
+
+    endBit = textOutBuf.GetBtg (); // 8=high bit, 1=low bit
+    endPos = textOutBuf.GetBytesWritten () + headLen;
+    
+    // update the pointers if this is a level tag
+    if (tagInfo.levelTags.find ((*here).tagName) != tagInfo.levelTags.end()) {
+      if ((*here).elType == OpenTagE) {
+	// set the start of the document
+	textInfoMap[(*here).tagName].SetStart (startPos, startBit, startWhich);
+	
+      } else if ((*here).elType == CloseTagE) {
+	// set the end of the document
+	textInfoMap[(*here).tagName].SetEnd (endPos, endBit);
+	
+      } else {
+	// TextE, nothing needs to be done
+      }
+    }
+    
+    cth.num_of_bytes += (*here).text.size();
+    ++here;
+  }
+
+  // close off any unclosed tags
+  CompressTextInfoMap::iterator tiHere = textInfoMap.begin ();
+  CompressTextInfoMap::iterator tiEnd = textInfoMap.end ();
+  while (tiHere != tiEnd) {
+    if ((*tiHere).second.inDoc) (*tiHere).second.SetEnd (endPos, endBit);
+    ++tiHere;
+  }
+  
+  // we've processed one more document
+  ++cth.num_of_docs;
+
+  return COMPALLOK;
+}
+
+
+static int write_aux_dict (char *fileName) {
+  int i;
+  FILE *aux;
+  if (!(aux = create_file (fileName, TEXT_DICT_AUX_SUFFIX, "wb",
+			   MAGIC_AUX_DICT, MG_MESSAGE)))
+    return COMPERROR;
+  
+  for (i = 0; i <= 1; ++i)
+    {
+      aux_frags_header afh;
+      char_pool *cp;
+      
+      afh.num_frags = nht[i].HashUsed;
+      afh.mem_for_frags = 0;
+      for (cp = nht[i].first_pool; cp; cp = cp->next)
+	afh.mem_for_frags += POOL_SIZE - cp->left;
+      
+      /* [RPAP - Jan 97: Endian Ordering] */
+      HTONUL(afh.num_frags);
+      HTONUL(afh.mem_for_frags);
+      
+      fwrite (&afh, sizeof (afh), 1, aux);
+      
+      for (cp = nht[i].first_pool; cp; cp = cp->next)
+	fwrite (cp->pool, POOL_SIZE - cp->left, sizeof (u_char), aux);
+    }
+  fclose (aux);
+  return COMPALLOK;
+}
+
+
+static void estimate_compressed_aux_dict (void) {
+  int i;
+  u_long aux_compressed = 0, total_uncomp = 0;
+  for (i = 0; i <= 1; ++i)
+    {
+      int j;
+      long chars[256], fchars[256];
+      long lens[16], flens[16];
+      char_pool *cp;
+      memset (chars, '\0', sizeof (chars));
+      memset (lens, '\0', sizeof (lens));
+      for (cp = nht[i].first_pool; cp; cp = cp->next)
+	{
+	  u_char *buf = cp->pool;
+	  while (buf != cp->ptr)
+	    {
+	      int len = *buf++;
+	      ++lens[len];
+	      total_uncomp += len + 4;
+	      for (; len; --len)
+		++chars[*buf++];
+	    }
+	}
+      for (j = 0; j < 256; ++j)
+	if (!chars[j] && PESINAWORD (j) == i)
+	  fchars[j] = 1;
+	else
+	  fchars[j] = chars[j];
+      for (j = 0; j < 16; ++j)
+	if (!lens[j])
+	  flens[j] = 1;
+	else
+	  flens[j] = lens[j];
+      
+      aux_compressed += (long unsigned int) ((Calculate_Huffman_Size (16, flens, lens) +
+					      Calculate_Huffman_Size (256, fchars, chars)) / 8);
+      
+    }
+}
+
+
+
+static bool WriteTextIdx (char *fileName, FTextLevel &textLevels) {
+  // create the text index
+  FILE *textIdxFile;
+  if (!(textIdxFile = create_file (fileName, TEXT_IDX_SUFFIX, "w+b",
+				MAGIC_TEXI, MG_MESSAGE)))
+    return false;
+
+  // output each level
+  CompressTextInfoMap::iterator tiHere = textInfoMap.begin ();
+  CompressTextInfoMap::iterator tiEnd = textInfoMap.end ();
+  while (tiHere != tiEnd) {
+    // remember the level information
+    TextLevelInfo levelInfo;
+    levelInfo.levelTag = (*tiHere).first;
+    levelInfo.textIdxPtr = ftell (textIdxFile);
+    levelInfo.numEntries = (*tiHere).second.docPtrs.size();
+    textLevels.levelInfo[levelInfo.levelTag] = levelInfo;
+
+    // write out the index array for this level
+    if (!WriteTextIdxArray (textIdxFile, (*tiHere).second.docPtrs))
+      return false;
+    
+    ++tiHere;
+  }
+
+  // close the file
+  fclose (textIdxFile);
+
+  return true;
+}
+
+
+bool WriteTextLevels (char *fileName, const FTextLevel &textLevels) {
+  //  cout << textLevels;
+  
+  // create the text index
+  FILE *textLevelFile;
+  if (!(textLevelFile = create_file (fileName, TEXT_LEVEL_SUFFIX, "w+b",
+				     MAGIC_TEXT_LEVELS, MG_MESSAGE)))
+    return false;
+
+  // output each level
+  if (!textLevels.Write (textLevelFile)) return false;
+  
+  // close the file
+  fclose (textLevelFile);
+
+  return true;
+}
+
+
+int done_text_2 (const TagInfo &/*tagInfo*/, char *fileName) {
+  // write out any remaining bits
+  textOutBuf.encodeDone();
+
+  // write out the compressed text header (with updated statistics)
+  if (fseek (text, sizeof (u_long), SEEK_SET) == -1 || !cth.Write (text))
+    return COMPERROR;
+  fclose (text);
+
+  // write out the text index file and get the level information
+  FTextLevel textLevels;
+  if (!WriteTextIdx (fileName, textLevels)) return COMPERROR;
+  
+  // write out the text level information
+  if (!WriteTextLevels (fileName, textLevels)) return COMPERROR;
+
+  // write out the auxiliary dictionary
+  if (cdh.dict_type != MG_COMPLETE_DICTIONARY &&
+      (cdh.novel_method == MG_NOVEL_DELTA ||
+       cdh.novel_method == MG_NOVEL_HYBRID)) {
+    if (write_aux_dict (fileName) == COMPERROR) return COMPERROR;
+    estimate_compressed_aux_dict ();
+    
+  } else {
+    unlink (make_name (fileName, TEXT_DICT_AUX_SUFFIX, NULL));
+  }
+
+  return (COMPALLOK);
+}
Index: /indexers/branches/3.03a/mgpp/text/words.cpp
===================================================================
--- /indexers/branches/3.03a/mgpp/text/words.cpp	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/words.cpp	(revision 14757)
@@ -0,0 +1,123 @@
+/**************************************************************************
+ *
+ * words.cpp -- Functions for parsing out words from the source text
+ * Copyright (C) 1999  Rodger McNab
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+
+// need this to avoid bizarre compiler problems under VC++ 6.0
+#if defined (__WIN32__) && !defined (GSDL_USE_IOS_H)
+# include <iostream>
+#endif
+
+#include "words.h"
+
+int MAXNUMERIC = 4;
+
+/* Takes the place of the old INAWORD macro. It determines
+   whether a given place in a UTF-8 encoded Unicode string
+   is part of a word. */
+int inaword_mgpp (const u_char *here, const u_char *end) {
+  unsigned short c;
+  if (parse_utf8_char(here, end, &c) > 0) return is_unicode_letdig (c);
+  return 0;
+}
+
+/* It determines whether a given place in a UTF-8 encoded Unicode string is a unicode space. */
+int isaspace_mgpp (const u_char *here, const u_char *end)
+{
+  unsigned short c;
+  if (parse_utf8_char(here, end, &c) > 0) return is_unicode_space(c);
+  return 0;
+}
+
+/* Return a the UTF-8 encoded Unicode string with begining
+   unicode spaces skippend. */
+u_char *skipspace_mgpp(u_char *here, u_char *end)
+{
+  unsigned short c;	
+  int length;
+  while(here != end) {
+    length = parse_utf8_char(here, end, &c);
+    if (length == 0 || !is_unicode_space(c)) break;
+    here += length;
+  }
+  return here;
+}
+ 
+const unsigned char *ParseIndexWord (const unsigned char *textHere,
+				     const unsigned char *textEnd,
+				     UCArray &word) {
+  word.erase (word.begin(), word.end());
+
+  register int charlength = 0;
+  register int length = 0;
+  register int numeric = 0;
+  unsigned short c;
+  
+  charlength = parse_utf8_char (textHere, textEnd, &c);
+  
+  while (length+charlength <= MAXSTEMLEN && charlength > 0 &&
+	 (is_unicode_letter(c) || (is_unicode_digit(c) &&
+				   ++numeric <= MAXNUMERIC))) {
+    while (charlength-- > 0) {
+      word.push_back (*textHere++); ++length;
+    }
+    charlength = parse_utf8_char (textHere, textEnd, &c);
+  }
+  
+  return textHere;
+}
+
+const unsigned char *ParseIndexMGWord (const unsigned char *textHere,
+				       const unsigned char *textEnd,
+				       unsigned char *mgWord) {
+  register int charlength = 0;
+  register int length = 0;
+  register int numeric = 0;
+  unsigned short c;
+  
+  charlength = parse_utf8_char (textHere, textEnd, &c);
+  
+  while (length+charlength <= MAXSTEMLEN && charlength > 0 &&
+	 (is_unicode_letter(c) || (is_unicode_digit(c) &&
+				   ++numeric <= MAXNUMERIC))) {
+    while (charlength-- > 0) {
+      mgWord[++length] = *textHere++;
+    }
+    charlength = parse_utf8_char (textHere, textEnd, &c);
+  }
+
+  mgWord[0] = length;
+  
+  return textHere;
+}
+
+const unsigned char *ParseNonindexWord (const unsigned char *textHere,
+					const unsigned char *textEnd) {
+  register int charlength = 0;
+  unsigned short c;
+  
+  charlength = parse_utf8_char(textHere, textEnd, &c);
+  
+  while (charlength > 0 && !is_unicode_letdig(c)) {
+    textHere += charlength;
+    charlength = parse_utf8_char (textHere, textEnd, &c);
+  }
+  
+  return textHere;
+}
Index: /indexers/branches/3.03a/mgpp/text/words.h
===================================================================
--- /indexers/branches/3.03a/mgpp/text/words.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/text/words.h	(revision 14757)
@@ -0,0 +1,171 @@
+/**************************************************************************
+ *
+ * words.h -- Macros for parsing out words from the source text
+ * Copyright (C) 1994  Neil Sharman
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************/
+#ifndef H_WORDS
+#define H_WORDS
+
+
+#include "sysfuncs.h"
+
+#include "unitool.h"
+#include "UCArray.h"
+
+
+/*
+ * This has been cleaned up by Tim Shimmin. 
+ */
+
+/*
+ * ---NOTE---
+ *
+ * "WORD" refers to a word in the compressed text.
+ * "STEM" or "STEM_WORD" refers to a word for indexing on
+ *
+ */
+
+#define MAXWORDLEN	15
+	/* Maximum length in bytes of any word or non-word. Note that
+	   variations to MAXWORDLEN may have dramatic effects on the rest
+	   of the program, as the length and the prefix match are packed
+	   together into a four bit nibble, and there is not check that
+	   this is possible, i.e., leave MAXWORDLEN alone... */
+
+#define MAXSTEMLEN	255
+	/* Maximum length in bytes of any stem. Note that
+	   variations to MAXSTEMLEN may have dramatic effects on the rest
+	   of the program, , i.e., leave MAXSTEMLEN alone... */
+
+//#define MAXNUMERIC	4
+	/* Maximum number of numeric characters permitted in a word.
+	   This avoids long sequences of numbers creating just one
+	   word occurrence for each number. At most 10,000 all numeric
+	   words will be permitted. */
+
+extern  int MAXNUMERIC;
+
+/* [RPAP - Jan 97: Stem Index Change] */
+#define MAXPARAMLEN     20
+        /* Maximum number of bytes to read for a parameter value for a
+	   term in a query. */
+#define WEIGHTPARAM     '/'
+#define STEMPARAM       '#'
+
+/* [RJM 07/97: Ranked Required Terms] */
+#define MUSTMATCHPARAM     '+'
+
+
+#define PESINAWORD(c)      (isalnum(c) || ((c) >= 0x80 && (c) <= 0xff))
+        /* The definition of what characters are permitted in a word.
+	   This macro is pessimistic, you cannot tell from a particular
+	   byte above 0x80 whether it is a character or not. This function
+	   is needed by various functions relating to huffman coding
+	   where frequency counts need to be primed, it should not be
+	   used in parsing the UTF-8 encoded input. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int inaword_mgpp (const u_char *here, const u_char *end);
+        /* Takes the place of the old INAWORD macro. It determines
+	   whether a given place in a UTF-8 encoded Unicode string
+	   is part of a word. */
+
+int isaspace_mgpp (const u_char *here, const u_char *end);
+        /* It determines whether a given place in a UTF-8 encoded Unicode string  is a unicode space. */
+
+u_char *skipspace_mgpp(u_char *here, u_char *end);
+        /* Return a the UTF-8 encoded Unicode string with begining unicode spaces skippend. */
+
+#ifdef __cplusplus
+}
+#endif
+
+const unsigned char *ParseIndexWord (const unsigned char *textHere,
+				     const unsigned char *textEnd,
+				     UCArray &word);
+const unsigned char *ParseIndexMGWord (const unsigned char *textHere,
+				       const unsigned char *textEnd,
+				       unsigned char *mgWord);
+const unsigned char *ParseNonindexWord (const unsigned char *textHere,
+					const unsigned char *textEnd);
+
+
+
+/* =========================================================================
+ * Macro: PARSE_WORD
+ * Description: 
+ *      Extract a word out for compressing text
+ * Input: 
+ *      s_in = string start in buffer
+ *      end = string end in buffer
+ * Output: 
+ *      Word = extracted word with length in 1st byte
+ *      s_in = ptr to next character in buffer yet to be processed
+ * ========================================================================= */
+#define PARSE_WORD(Word, s_in, end)                                \
+  do {                                                             \
+    register int charlength = 0;                                   \
+    register u_char *wptr = (Word)+1;                              \
+    register int length = 0;                                       \
+    register int numeric = 0;                                      \
+    unsigned short c;                                              \
+                                                                   \
+    charlength = parse_utf8_char((s_in),(end),&c);                 \
+                                                                   \
+    while (length+charlength <= MAXWORDLEN && charlength > 0 &&    \
+	   (is_unicode_letter(c) || (is_unicode_digit(c) &&        \
+				     ++numeric <= MAXNUMERIC))) {  \
+      while (charlength-- > 0) {                                   \
+        *wptr++ = *(s_in)++; ++length;                             \
+      }                                                            \
+      charlength = parse_utf8_char((s_in),(end),&c);               \
+    }                                                              \
+    *(Word) = length;                                              \
+  }while(0)
+
+
+
+/* =========================================================================
+ * Macro: PARSE_NON_WORD
+ * Description: 
+ *      Extract a non-word out for storing compressed text
+ * Input: as above
+ * Output: as above
+ * ========================================================================= */
+#define PARSE_NON_WORD(Word, s_in, end)                            \
+  do {                                                             \
+    register int charlength = 0;                                   \
+    register u_char *wptr = (Word)+1;                              \
+    register int length = 0;                                       \
+    unsigned short c;                                              \
+                                                                   \
+    charlength = parse_utf8_char((s_in),(end),&c);                 \
+                                                                   \
+    while (length+charlength <= MAXWORDLEN && charlength > 0 &&    \
+	   !is_unicode_letdig(c)) {                                \
+      while (charlength-- > 0) {                                   \
+        *wptr++ = *(s_in)++; ++length;                             \
+      }                                                            \
+      charlength = parse_utf8_char((s_in),(end),&c);               \
+    }                                                              \
+    *(Word) = length;                                              \
+  }while(0)
+
+#endif
Index: /indexers/branches/3.03a/mgpp/win32cfg.h
===================================================================
--- /indexers/branches/3.03a/mgpp/win32cfg.h	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/win32cfg.h	(revision 14757)
@@ -0,0 +1,163 @@
+/* config.h.  Generated automatically by configure.  */
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
+#endif
+
+/* Define if using alloca.c.  */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work.  */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro.  */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+/* #define HAVE_ALLOCA_H 1 */
+
+/* Define if you don't have vprintf but do have _doprnt.  */
+/* #undef HAVE_DOPRNT */
+
+/* Define if you have the vprintf function.  */
+#define HAVE_VPRINTF 1
+
+/* Define if on MINIX.  */
+/* #undef _MINIX */
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+/* #undef off_t */
+
+/* Define if the system does not provide POSIX.1 features except
+   with this defined.  */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define if you need to in order for stat and other things to work.  */
+/* #undef _POSIX_SOURCE */
+
+/* Define as the return type of signal handlers (int or void).  */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files.  */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+/* #define TIME_WITH_SYS_TIME 1 */
+
+/* Define if your <sys/time.h> declares struct tm.  */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define to the name of the distribution.  */
+#define PACKAGE "mg"
+
+/* Define to the version of the distribution.  */
+#define VERSION "1.2"
+
+/* Define to 1 if you have the valloc function.  */
+/* #define HAVE_VALLOC 1 */
+
+/* Define to 1 if ANSI function prototypes are usable.  */
+#define PROTOTYPES 1
+
+ 
+/* Define to 1 for better use of the debugging malloc library.  See
+   site ftp.antaire.com in antaire/src, file dmalloc/dmalloc.tar.gz.  */
+/* #undef WITH_DMALLOC */
+
+ 
+/* Define to 1 if GNU regex should be used instead of GNU rx.  */
+/* #undef WITH_REGEX */
+
+/* Some braindead header files do not have the requ'd function declarations */
+#define HAVE_FGETC_DECL 1
+#define HAVE_FREAD_DECL 1
+
+/* See if have this field in the prstatus_t structure */
+/* It stores the size of the process heap */
+/* #define HAVE_PR_BRKSIZE 1 */
+
+/* Define if you have the ftime function.  */
+/* #undef HAVE_FTIME */
+
+/* Define if you have the getpagesize function.  */
+/* #undef HAVE_GETPAGESIZE */
+
+/* Define if you have the getrusage function.  */
+/* #undef HAVE_GETRUSAGE */
+
+/* Define if you have the mallinfo function.  */
+/* #undef HAVE_MALLINFO */
+
+/* Define if you have the select function.  */
+#define HAVE_SELECT 1
+
+/* Define if you have the setbuffer function.  */
+/* #undef HAVE_SETBUFFER */
+
+/* Define if you have the strftime function.  */
+#define HAVE_STRFTIME 1
+
+/* Define if you have the strtol function.  */
+#define HAVE_STRTOL 1
+
+/* Define if you have the times function.  */
+/* #define HAVE_TIMES 1 */
+
+/* Define if you have the valloc function.  */
+/* #define HAVE_VALLOC 1 */
+
+/* Define if you have the <dirent.h> header file.  */
+/* #define HAVE_DIRENT_H 1 */
+
+/* Define if you have the <fcntl.h> header file.  */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file.  */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <memory.h> header file.  */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <ndir.h> header file.  */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <string.h> header file.  */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/dir.h> header file.  */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/ndir.h> header file.  */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/procfs.h> header file.  */
+/* #define HAVE_SYS_PROCFS_H 1 */
+
+/* Define if you have the <sys/time.h> header file.  */
+/* #define HAVE_SYS_TIME_H 1 */
+
+/* Define if you have the <unistd.h> header file.  */
+/* #define HAVE_UNISTD_H 1 */
+
+/* Define if you have the m library (-lm).  */
+#define HAVE_LIBM 1
Index: /indexers/branches/3.03a/mgpp/winMake.bat
===================================================================
--- /indexers/branches/3.03a/mgpp/winMake.bat	(revision 14757)
+++ /indexers/branches/3.03a/mgpp/winMake.bat	(revision 14757)
@@ -0,0 +1,54 @@
+@echo off
+
+set MAKE=nmake
+set MAKE_OPTIONS=/f
+
+if ""%1"" == """" goto all
+if ""%1"" == ""all"" goto go
+if ""%1"" == ""install"" goto go
+if ""%1"" == ""clean"" goto go
+
+:unknown
+	echo Error: Unrecognized argument %1.
+	goto done
+
+:go
+	if ""%2"" == ""javaonly"" goto java
+	if ""%2"" == ""nojava"" goto nojava
+
+:all
+	cd lib
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..
+
+	cd text
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..
+
+	cd java\org\greenstone\mgpp
+	call winMake.bat %1
+	cd ..\..\..\..
+
+	cd jni
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..
+	goto done
+
+:java
+	cd java\org\greenstone\mgpp
+	call winMake.bat %1
+	cd ..\..\..\..
+	goto done
+
+:nojava
+	cd lib
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..
+
+	cd text
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..
+	goto done
+	
+:done
+
Index: /indexers/branches/3.03a/packages/unac/.version
===================================================================
--- /indexers/branches/3.03a/packages/unac/.version	(revision 14757)
+++ /indexers/branches/3.03a/packages/unac/.version	(revision 14757)
@@ -0,0 +1,1 @@
+1.7.0
Index: /indexers/branches/3.03a/packages/unac/Makefile.in
===================================================================
--- /indexers/branches/3.03a/packages/unac/Makefile.in	(revision 14757)
+++ /indexers/branches/3.03a/packages/unac/Makefile.in	(revision 14757)
@@ -0,0 +1,67 @@
+#
+# Copyright (C) 2000, 2001, 2002 Loic Dachary <loic@senga.org>
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+# This Makefile produced by Katherine Don for the Greenstone Digial Library
+# software
+
+VERSION = @VERSION@
+
+CC = @CC@
+AR = ar
+RANLIB = @RANLIB@
+
+LIBICONV = @LIBICONV@
+LTLIBICONV = @LTLIBICONV@
+
+
+DEFS = @DEFS@ -DUNAC_VERSION=\"$(VERSION)\"
+INCLUDES = 
+CFLAGS = @CFLAGS@
+
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES)  $(CFLAGS)
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+	$(COMPILE) $<
+
+HEADERS = unac.h
+
+SOURCES = unac.c 
+
+OBJECTS = unac.o 
+
+
+all : libunac.a
+
+
+libunac.a: $(OBJECTS)
+	rm -f libunac.a
+	$(AR) cru libunac.a $(OBJECTS)
+	$(RANLIB) libunac.a
+
+
+install:
+
+clean:
+	rm -f *.o libunac.a
+
+distclean: clean
+	rm -f Makefile config.h config.log config.status
+
+
Index: /indexers/branches/3.03a/packages/unac/aclocal.m4
===================================================================
--- /indexers/branches/3.03a/packages/unac/aclocal.m4	(revision 14757)
+++ /indexers/branches/3.03a/packages/unac/aclocal.m4	(revision 14757)
@@ -0,0 +1,5249 @@
+# aclocal.m4 generated automatically by aclocal 1.5
+
+# Copyright 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+dnl Copyright (C) 2000, 2001, 2002 Loic Dachary <loic@senga.org>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+dnl
+dnl Local autoconf definitions. Try to follow the guidelines of the autoconf
+dnl macro repository so that integration in the repository is easy.
+dnl To submit a macro to the repository send the macro (one macro per mail)
+dnl to Peter Simons <simons@cryp.to>.
+dnl The repository itself is at httphttp://savannah.gnu.org/projects/ac-archive/
+dnl
+
+dnl @synopsis AC_MANDATORY_HEADER(HEADER-FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl
+dnl Same semantic as AC_CHECK_HEADER except that it aborts the configuration
+dnl script if the header file is not found.
+dnl
+dnl @author Loic Dachary <loic@senga.org>
+dnl
+AC_DEFUN([AC_MANDATORY_HEADER],
+[dnl Do the transliteration at runtime so arg 1 can be a shell variable.
+ac_safe=`echo "$1" | sed 'y%./+-%__p_%'`
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(ac_cv_header_$ac_safe,
+[AC_TRY_CPP([#include <$1>], eval "ac_cv_header_$ac_safe=yes",
+  eval "ac_cv_header_$ac_safe=no")])dnl
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  AC_MSG_RESULT(yes)
+  ifelse([$2], , :, [$2])
+else
+  AC_MSG_ERROR(header not found check config.log)
+ifelse([$3], , , [$3
+])dnl
+fi
+])
+
+dnl @synopsis AC_MANDATORY_HEADERS(HEADER-FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl
+dnl Same semantic as AC_CHECK_HEADERS except that it aborts the configuration
+dnl script if one of the headers file is not found.
+dnl
+dnl @author Loic Dachary <loic@senga.org>
+dnl 
+AC_DEFUN([AC_MANDATORY_HEADERS],
+[for ac_hdr in $1
+do
+AC_MANDATORY_HEADER($ac_hdr,
+[changequote(, )dnl
+  ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+changequote([, ])dnl
+  AC_DEFINE_UNQUOTED($ac_tr_hdr) $2], $3)dnl
+done
+])
+
+dnl @synopsis AC_MANDATORY_LIB(LIBRARY, FUNCTION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]])
+dnl
+dnl Same semantic as AC_CHECK_LIB except that it aborts the configuration
+dnl script if the library is not found or compilation fails.
+dnl
+dnl @author Loic Dachary <loic@senga.org>
+dnl
+AC_DEFUN([AC_MANDATORY_LIB],
+[AC_MSG_CHECKING([for $2 in -l$1])
+dnl Use a cache variable name containing both the library and function name,
+dnl because the test really is for library $1 defining function $2, not
+dnl just for library $1.  Separate tests with the same $1 and different $2s
+dnl may have different results.
+ac_lib_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
+AC_CACHE_VAL(ac_cv_lib_$ac_lib_var,
+[ac_save_LIBS="$LIBS"
+LIBS="-l$1 $5 $LIBS"
+AC_TRY_LINK(dnl
+ifelse(AC_LANG, [FORTRAN77], ,
+ifelse([$2], [main], , dnl Avoid conflicting decl of main.
+[/* Override any gcc2 internal prototype to avoid an error.  */
+]ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus
+extern "C"
+#endif
+])dnl
+[/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $2();
+])),
+	    [$2()],
+	    eval "ac_cv_lib_$ac_lib_var=yes",
+	    eval "ac_cv_lib_$ac_lib_var=no")
+LIBS="$ac_save_LIBS"
+])dnl
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  AC_MSG_RESULT(yes)
+  ifelse([$3], ,
+[changequote(, )dnl
+  ac_tr_lib=HAVE_LIB`echo $1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+changequote([, ])dnl
+  AC_DEFINE_UNQUOTED($ac_tr_lib)
+  LIBS="-l$1 $LIBS"
+], [$3])
+else
+  AC_MSG_ERROR(library not found check config.log)
+ifelse([$4], , , [$4
+])dnl
+fi
+])
+
+dnl @synopsis AC_COMPILE_WARNINGS
+dnl
+dnl Set the maximum warning verbosity according to compiler used.
+dnl Currently supports g++ and gcc.
+dnl This macro must be put after AC_PROG_CC and AC_PROG_CXX in
+dnl configure.in
+dnl
+dnl @author Loic Dachary <loic@senga.org>
+dnl
+
+AC_DEFUN(AC_COMPILE_WARNINGS,
+[AC_MSG_CHECKING(maximum warning verbosity option)
+if test -n "$CXX"
+then
+  if test "$GXX" = "yes"
+  then
+    ac_compile_warnings_opt='-Wall -Woverloaded-virtual'
+  fi
+  CXXFLAGS="$CXXFLAGS $ac_compile_warnings_opt"
+  ac_compile_warnings_msg="$ac_compile_warnings_opt for C++"
+fi
+
+if test -n "$CC"
+then
+  if test "$GCC" = "yes"
+  then
+    ac_compile_warnings_opt='-Wall -Wmissing-declarations -Wmissing-prototypes'
+  fi
+  CFLAGS="$CFLAGS $ac_compile_warnings_opt"
+  ac_compile_warnings_msg="$ac_compile_warnings_msg $ac_compile_warnings_opt for C"
+fi
+AC_MSG_RESULT($ac_compile_warnings_msg)
+unset ac_compile_warnings_msg
+unset ac_compile_warnings_opt
+])
+
+
+# Do all the work for Automake.  This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 5
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# We require 2.13 because we rely on SHELL being computed by configure.
+AC_PREREQ([2.13])
+
+# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
+# -----------------------------------------------------------
+# If MACRO-NAME is provided do IF-PROVIDED, else IF-NOT-PROVIDED.
+# The purpose of this macro is to provide the user with a means to
+# check macros which are provided without letting her know how the
+# information is coded.
+# If this macro is not defined by Autoconf, define it here.
+ifdef([AC_PROVIDE_IFELSE],
+      [],
+      [define([AC_PROVIDE_IFELSE],
+              [ifdef([AC_PROVIDE_$1],
+                     [$2], [$3])])])
+
+
+# AM_INIT_AUTOMAKE(PACKAGE,VERSION, [NO-DEFINE])
+# ----------------------------------------------
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_REQUIRE([AC_PROG_INSTALL])dnl
+# test to see if srcdir already configured
+if test "`CDPATH=:; cd $srcdir && pwd`" != "`pwd`" &&
+   test -f $srcdir/config.status; then
+  AC_MSG_ERROR([source directory already configured; run \"make distclean\" there first])
+fi
+
+# Define the identity of the package.
+PACKAGE=$1
+AC_SUBST(PACKAGE)dnl
+VERSION=$2
+AC_SUBST(VERSION)dnl
+ifelse([$3],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])
+
+# Autoconf 2.50 wants to disallow AM_ names.  We explicitly allow
+# the ones we care about.
+ifdef([m4_pattern_allow],
+      [m4_pattern_allow([^AM_[A-Z]+FLAGS])])dnl
+
+# Autoconf 2.50 always computes EXEEXT.  However we need to be
+# compatible with 2.13, for now.  So we always define EXEEXT, but we
+# don't compute it.
+AC_SUBST(EXEEXT)
+# Similar for OBJEXT -- only we only use OBJEXT if the user actually
+# requests that it be used.  This is a bit dumb.
+: ${OBJEXT=o}
+AC_SUBST(OBJEXT)
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal)
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake)
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_MISSING_PROG(AMTAR, tar)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_PROVIDE_IFELSE([AC_PROG_][CC],
+                  [_AM_DEPENDENCIES(CC)],
+                  [define([AC_PROG_][CC],
+                          defn([AC_PROG_][CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_][CXX],
+                  [_AM_DEPENDENCIES(CXX)],
+                  [define([AC_PROG_][CXX],
+                          defn([AC_PROG_][CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+# serial 3
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+
+# serial 2
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  am_backtick='`'
+  AC_MSG_WARN([${am_backtick}missing' script is too old or missing])
+fi
+])
+
+# AM_AUX_DIR_EXPAND
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND], [
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`CDPATH=:; cd $ac_aux_dir && pwd`
+])
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# serial 4						-*- Autoconf -*-
+
+
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+
+# _AM_DEPENDENCIES(NAME)
+# ---------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX" or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC,   [depcc="$CC"   am_compiler_list=],
+       [$1], CXX,  [depcc="$CXX"  am_compiler_list=],
+       [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc']
+       [$1], GCJ,  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                   [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    echo '#include "conftest.h"' > conftest.c
+    echo 'int i;' > conftest.h
+    echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=conftest.c object=conftest.o \
+       depfile=conftest.Po tmpdepfile=conftest.TPo \
+       $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 &&
+       grep conftest.h conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      am_cv_$1_dependencies_compiler_type=$depmode
+      break
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+$1DEPMODE="depmode=$am_cv_$1_dependencies_compiler_type"
+AC_SUBST([$1DEPMODE])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[rm -f .deps 2>/dev/null
+mkdir .deps 2>/dev/null
+if test -d .deps; then
+  DEPDIR=.deps
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  DEPDIR=_deps
+fi
+rmdir .deps 2>/dev/null
+AC_SUBST(DEPDIR)
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[  --disable-dependency-tracking Speeds up one-time builds
+  --enable-dependency-tracking  Do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+pushdef([subst], defn([AC_SUBST]))
+subst(AMDEPBACKSLASH)
+popdef([subst])
+])
+
+# Generate code to set up dependency tracking.
+# This macro should only be invoked once -- use via AC_REQUIRE.
+# Usage:
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],[
+AC_OUTPUT_COMMANDS([
+test x"$AMDEP_TRUE" != x"" ||
+for mf in $CONFIG_FILES; do
+  case "$mf" in
+  Makefile) dirpart=.;;
+  */Makefile) dirpart=`echo "$mf" | sed -e 's|/[^/]*$||'`;;
+  *) continue;;
+  esac
+  grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue
+  # Extract the definition of DEP_FILES from the Makefile without
+  # running `make'.
+  DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n -e '/^U = / s///p' < "$mf"`
+  test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR"
+  # We invoke sed twice because it is the simplest approach to
+  # changing $(DEPDIR) to its actual value in the expansion.
+  for file in `sed -n -e '
+    /^DEP_FILES = .*\\\\$/ {
+      s/^DEP_FILES = //
+      :loop
+	s/\\\\$//
+	p
+	n
+	/\\\\$/ b loop
+      p
+    }
+    /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`echo "$file" | sed -e 's|/[^/]*$||'`
+    $ac_aux_dir/mkinstalldirs "$dirpart/$fdir" > /dev/null 2>&1
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+], [AMDEP_TRUE="$AMDEP_TRUE"
+ac_aux_dir="$ac_aux_dir"])])
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+doit:
+	@echo done
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include='#'
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote='"'
+      _am_result=BSD
+   fi
+fi
+AC_SUBST(am__include)
+AC_SUBST(am__quote)
+AC_MSG_RESULT($_am_result)
+rm -f confinc confmf
+])
+
+# serial 3
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+#
+# FIXME: Once using 2.50, use this:
+# m4_match([$1], [^TRUE\|FALSE$], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_DEFUN([AM_CONDITIONAL],
+[ifelse([$1], [TRUE],
+        [errprint(__file__:__line__: [$0: invalid condition: $1
+])dnl
+m4exit(1)])dnl
+ifelse([$1], [FALSE],
+       [errprint(__file__:__line__: [$0: invalid condition: $1
+])dnl
+m4exit(1)])dnl
+AC_SUBST([$1_TRUE])
+AC_SUBST([$1_FALSE])
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi])
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+# serial 3
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  We must strip everything past the first ":",
+# and everything past the last "/".
+
+AC_PREREQ([2.12])
+
+AC_DEFUN([AM_CONFIG_HEADER],
+[ifdef([AC_FOREACH],dnl
+	 [dnl init our file count if it isn't already
+	 m4_ifndef([_AM_Config_Header_Index], m4_define([_AM_Config_Header_Index], [0]))
+	 dnl prepare to store our destination file list for use in config.status
+	 AC_FOREACH([_AM_File], [$1],
+		    [m4_pushdef([_AM_Dest], m4_patsubst(_AM_File, [:.*]))
+		    m4_define([_AM_Config_Header_Index], m4_incr(_AM_Config_Header_Index))
+		    dnl and add it to the list of files AC keeps track of, along
+		    dnl with our hook
+		    AC_CONFIG_HEADERS(_AM_File,
+dnl COMMANDS, [, INIT-CMDS]
+[# update the timestamp
+echo timestamp >"AS_ESCAPE(_AM_DIRNAME(]_AM_Dest[))/stamp-h]_AM_Config_Header_Index["
+][$2]m4_ifval([$3], [, [$3]]))dnl AC_CONFIG_HEADERS
+		    m4_popdef([_AM_Dest])])],dnl
+[AC_CONFIG_HEADER([$1])
+  AC_OUTPUT_COMMANDS(
+   ifelse(patsubst([$1], [[^ ]], []),
+	  [],
+	  [test -z "$CONFIG_HEADERS" || echo timestamp >dnl
+	   patsubst([$1], [^\([^:]*/\)?.*], [\1])stamp-h]),dnl
+[am_indx=1
+for am_file in $1; do
+  case " \$CONFIG_HEADERS " in
+  *" \$am_file "*)
+    am_dir=\`echo \$am_file |sed 's%:.*%%;s%[^/]*\$%%'\`
+    if test -n "\$am_dir"; then
+      am_tmpdir=\`echo \$am_dir |sed 's%^\(/*\).*\$%\1%'\`
+      for am_subdir in \`echo \$am_dir |sed 's%/% %'\`; do
+        am_tmpdir=\$am_tmpdir\$am_subdir/
+        if test ! -d \$am_tmpdir; then
+          mkdir \$am_tmpdir
+        fi
+      done
+    fi
+    echo timestamp > "\$am_dir"stamp-h\$am_indx
+    ;;
+  esac
+  am_indx=\`expr \$am_indx + 1\`
+done])
+])]) # AM_CONFIG_HEADER
+
+# _AM_DIRNAME(PATH)
+# -----------------
+# Like AS_DIRNAME, only do it during macro expansion
+AC_DEFUN([_AM_DIRNAME],
+       [m4_if(m4_regexp([$1], [^.*[^/]//*[^/][^/]*/*$]), -1,
+	      m4_if(m4_regexp([$1], [^//\([^/]\|$\)]), -1,
+		    m4_if(m4_regexp([$1], [^/.*]), -1,
+			  [.],
+			  m4_patsubst([$1], [^\(/\).*], [\1])),
+		    m4_patsubst([$1], [^\(//\)\([^/].*\|$\)], [\1])),
+	      m4_patsubst([$1], [^\(.*[^/]\)//*[^/][^/]*/*$], [\1]))[]dnl
+]) # _AM_DIRNAME
+
+# libtool.m4 - Configure libtool for the host system. -*-Shell-script-*-
+
+# serial 46 AC_PROG_LIBTOOL
+
+AC_DEFUN([AC_PROG_LIBTOOL],
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Prevent multiple expansion
+define([AC_PROG_LIBTOOL], [])
+])
+
+AC_DEFUN([AC_LIBTOOL_SETUP],
+[AC_PREREQ(2.13)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+AC_REQUIRE([LT_AC_PROG_SED])dnl
+
+AC_REQUIRE([AC_PROG_LN_S])dnl
+AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+AC_REQUIRE([AC_OBJEXT])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+dnl
+
+_LT_AC_PROG_ECHO_BACKSLASH
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    AC_PATH_MAGIC
+  fi
+  ;;
+esac
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(STRIP, strip, :)
+
+ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+enable_win32_dll=yes, enable_win32_dll=no)
+
+AC_ARG_ENABLE(libtool-lock,
+  [  --disable-libtool-lock  avoid locking (might break parallel builds)])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_SAVE
+     AC_LANG_C
+     AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_RESTORE])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+
+  # recent cygwin and mingw systems supply a stub DllMain which the user
+  # can override, but on older systems we have to supply one
+  AC_CACHE_CHECK([if libtool should supply DllMain function], lt_cv_need_dllmain,
+    [AC_TRY_LINK([],
+      [extern int __attribute__((__stdcall__)) DllMain(void*, int, void*);
+      DllMain (0, 0, 0);],
+      [lt_cv_need_dllmain=no],[lt_cv_need_dllmain=yes])])
+
+  case $host/$CC in
+  *-*-cygwin*/gcc*-mno-cygwin*|*-*-mingw*)
+    # old mingw systems require "-dll" to link a DLL, while more recent ones
+    # require "-mdll"
+    SAVE_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS -mdll"
+    AC_CACHE_CHECK([how to link DLLs], lt_cv_cc_dll_switch,
+      [AC_TRY_LINK([], [], [lt_cv_cc_dll_switch=-mdll],[lt_cv_cc_dll_switch=-dll])])
+    CFLAGS="$SAVE_CFLAGS" ;;
+  *-*-cygwin* | *-*-pw32*)
+    # cygwin systems need to pass --dll to the linker, and not link
+    # crt.o which will require a WinMain@16 definition.
+    lt_cv_cc_dll_switch="-Wl,--dll -nostartfiles" ;;
+  esac
+  ;;
+  ])
+esac
+
+_LT_AC_LTCONFIG_HACK
+
+])
+
+# AC_LIBTOOL_HEADER_ASSERT
+# ------------------------
+AC_DEFUN([AC_LIBTOOL_HEADER_ASSERT],
+[AC_CACHE_CHECK([whether $CC supports assert without backlinking],
+    [lt_cv_func_assert_works],
+    [case $host in
+    *-*-solaris*)
+      if test "$GCC" = yes && test "$with_gnu_ld" != yes; then
+        case `$CC --version 2>/dev/null` in
+        [[12]].*) lt_cv_func_assert_works=no ;;
+        *)        lt_cv_func_assert_works=yes ;;
+        esac
+      fi
+      ;;
+    esac])
+
+if test "x$lt_cv_func_assert_works" = xyes; then
+  AC_CHECK_HEADERS(assert.h)
+fi
+])# AC_LIBTOOL_HEADER_ASSERT
+
+# _LT_AC_CHECK_DLFCN
+# --------------------
+AC_DEFUN([_LT_AC_CHECK_DLFCN],
+[AC_CHECK_HEADERS(dlfcn.h)
+])# _LT_AC_CHECK_DLFCN
+
+# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+# ---------------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_NM])
+AC_REQUIRE([AC_OBJEXT])
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [dnl
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*) # Its linker distinguishes data from code symbols
+  lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+  lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+solaris* | sysv5*)
+  symcode='[[BDT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $host_os in
+mingw*)
+  opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+  symcode='[[ABCDGISTW]]'
+fi
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Write the raw and C identifiers.
+lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ 	]]\($symcode$symcode*\)[[ 	]][[ 	]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+  rm -f conftest*
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+	if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext'
+
+	  cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr address;
+}
+lt_preloaded_symbols[[]] =
+{
+EOF
+	  sed "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext
+	  cat <<\EOF >> conftest.$ac_ext
+  {0, (lt_ptr) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  save_LIBS="$LIBS"
+	  save_CFLAGS="$CFLAGS"
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$no_builtin_flag"
+	  if AC_TRY_EVAL(ac_link) && test -s conftest; then
+	    pipe_works=yes
+	  fi
+	  LIBS="$save_LIBS"
+	  CFLAGS="$save_CFLAGS"
+	else
+	  echo "cannot find nm_test_func in $nlist" >&AC_FD_CC
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&AC_FD_CC
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC
+    fi
+  else
+    echo "$progname: failed program was:" >&AC_FD_CC
+    cat conftest.$ac_ext >&5
+  fi
+  rm -f conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+global_symbol_pipe="$lt_cv_sys_global_symbol_pipe"
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  global_symbol_to_cdecl=
+  global_symbol_to_c_name_address=
+else
+  global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl"
+  global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address"
+fi
+if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address";
+then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+
+# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+# ---------------------------------
+AC_DEFUN([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR],
+[# Find the correct PATH separator.  Usually this is `:', but
+# DJGPP uses `;' like DOS.
+if test "X${PATH_SEPARATOR+set}" != Xset; then
+  UNAME=${UNAME-`uname 2>/dev/null`}
+  case X$UNAME in
+    *-DOS) lt_cv_sys_path_separator=';' ;;
+    *)     lt_cv_sys_path_separator=':' ;;
+  esac
+  PATH_SEPARATOR=$lt_cv_sys_path_separator
+fi
+])# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+
+# _LT_AC_PROG_ECHO_BACKSLASH
+# --------------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+[ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+			      [AC_DIVERT_PUSH(NOTICE)])
+_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+  ;;
+esac
+
+echo=${ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X[$]1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+  for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+       echo_test_string="`eval $cmd`" &&
+       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+    then
+      break
+    fi
+  done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+   test "X$echo_testing_string" = "X$echo_test_string"; then
+  :
+else
+  # The Solaris, AIX, and Digital Unix default echo programs unquote
+  # backslashes.  This makes it impossible to quote backslashes using
+  #   echo "$something" | sed 's/\\/\\\\/g'
+  #
+  # So, first we look for a working echo in the user's PATH.
+
+  IFS="${IFS= 	}"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for dir in $PATH /usr/ucb; do
+    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      echo="$dir/echo"
+      break
+    fi
+  done
+  IFS="$save_ifs"
+
+  if test "X$echo" = Xecho; then
+    # We didn't find a better echo, so look for alternatives.
+    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      # This shell has a builtin print -r that does the trick.
+      echo='print -r'
+    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+	 test "X$CONFIG_SHELL" != X/bin/ksh; then
+      # If we have ksh, try running configure again with it.
+      ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+      export ORIGINAL_CONFIG_SHELL
+      CONFIG_SHELL=/bin/ksh
+      export CONFIG_SHELL
+      exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+    else
+      # Try using printf.
+      echo='printf %s\n'
+      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+	 echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+	 test "X$echo_testing_string" = "X$echo_test_string"; then
+	# Cool, printf works
+	:
+      elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+	   test "X$echo_testing_string" = 'X\t' &&
+	   echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	   test "X$echo_testing_string" = "X$echo_test_string"; then
+	CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+	export CONFIG_SHELL
+	SHELL="$CONFIG_SHELL"
+	export SHELL
+	echo="$CONFIG_SHELL [$]0 --fallback-echo"
+      elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+	   test "X$echo_testing_string" = 'X\t' &&
+	   echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	   test "X$echo_testing_string" = "X$echo_test_string"; then
+	echo="$CONFIG_SHELL [$]0 --fallback-echo"
+      else
+	# maybe with a smaller string...
+	prev=:
+
+	for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+	  if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+	  then
+	    break
+	  fi
+	  prev="$cmd"
+	done
+
+	if test "$prev" != 'sed 50q "[$]0"'; then
+	  echo_test_string=`eval $prev`
+	  export echo_test_string
+	  exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+	else
+	  # Oops.  We lost completely, so just stick with echo.
+	  echo=echo
+	fi
+      fi
+    fi
+  fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+   ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(ECHO)
+AC_DIVERT_POP
+])# _LT_AC_PROG_ECHO_BACKSLASH
+
+# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                           ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ------------------------------------------------------------------
+AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+[if test "$cross_compiling" = yes; then :
+  [$4]
+else
+  AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+
+    exit (status);
+}]
+EOF
+  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_unknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_AC_TRY_DLOPEN_SELF
+
+# AC_LIBTOOL_DLOPEN_SELF
+# -------------------
+AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+[if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+   ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+          [lt_cv_dlopen="shl_load"],
+      [AC_CHECK_LIB([dld], [shl_load],
+            [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
+	[AC_CHECK_FUNC([dlopen],
+	      [lt_cv_dlopen="dlopen"],
+	  [AC_CHECK_LIB([dl], [dlopen],
+	        [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+	    [AC_CHECK_LIB([svld], [dlopen],
+	          [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+	      [AC_CHECK_LIB([dld], [dld_link],
+	            [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
+	      ])
+	    ])
+	  ])
+	])
+      ])
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+	  lt_cv_dlopen_self, [dnl
+	  _LT_AC_TRY_DLOPEN_SELF(
+	    lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+	    lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      LDFLAGS="$LDFLAGS $link_static_flag"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+    	  lt_cv_dlopen_self_static, [dnl
+	  _LT_AC_TRY_DLOPEN_SELF(
+	    lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+	    lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+])# AC_LIBTOOL_DLOPEN_SELF
+
+AC_DEFUN([_LT_AC_LTCONFIG_HACK],
+[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])dnl
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+sed_quote_subst='s/\([[\\"\\`$\\\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([[\\"\\`\\\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+need_locks="$enable_libtool_lock"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+if test x"$host" != x"$build"; then
+  ac_tool_prefix=${host_alias}-
+else
+  ac_tool_prefix=
+fi
+
+# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+case $host_os in
+linux-gnu*) ;;
+linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+esac
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
+    ;;
+  *)
+    old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+# Allow CC to be a program name with arguments.
+set dummy $CC
+compiler="[$]2"
+
+AC_MSG_CHECKING([for objdir])
+rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+AC_MSG_RESULT($objdir)
+
+
+AC_ARG_WITH(pic,
+[  --with-pic              try to use only PIC/non-PIC objects [default=use both]],
+pic_mode="$withval", pic_mode=default)
+test -z "$pic_mode" && pic_mode=default
+
+# We assume here that the value for lt_cv_prog_cc_pic will not be cached
+# in isolation, and that seeing it set (from the cache) indicates that
+# the associated values are set (in the cache) correctly too.
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+AC_CACHE_VAL(lt_cv_prog_cc_pic,
+[ lt_cv_prog_cc_pic=
+  lt_cv_prog_cc_shlib=
+  lt_cv_prog_cc_wl=
+  lt_cv_prog_cc_static=
+  lt_cv_prog_cc_no_builtin=
+  lt_cv_prog_cc_can_build_shared=$can_build_shared
+
+  if test "$GCC" = yes; then
+    lt_cv_prog_cc_wl='-Wl,'
+    lt_cv_prog_cc_static='-static'
+
+    case $host_os in
+    aix*)
+      # Below there is a dirty hack to force normal static linking with -ldl
+      # The problem is because libdl dynamically linked with both libc and
+      # libC (AIX C++ library), which obviously doesn't included in libraries
+      # list by gcc. This cause undefined symbols with -static flags.
+      # This hack allows C programs to be linked with "-static -ldl", but
+      # not sure about C++ programs.
+      lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC"
+      ;;
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4'
+      ;;
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_cv_prog_cc_pic='-fno-common'
+      ;;
+    cygwin* | mingw* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_cv_prog_cc_pic='-DDLL_EXPORT'
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	 lt_cv_prog_cc_pic=-Kconform_pic
+      fi
+      ;;
+    *)
+      lt_cv_prog_cc_pic='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for PIC flags for the system compiler.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      lt_cv_prog_cc_wl='-Wl,'
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_cv_prog_cc_static='-Bstatic'
+      else
+	lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      # Is there a better lt_cv_prog_cc_static that works with the bundled CC?
+      lt_cv_prog_cc_wl='-Wl,'
+      lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive"
+      lt_cv_prog_cc_pic='+Z'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_cv_prog_cc_wl='-Wl,'
+      lt_cv_prog_cc_static='-non_shared'
+      # PIC (with -KPIC) is the default.
+      ;;
+
+    cygwin* | mingw* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_cv_prog_cc_pic='-DDLL_EXPORT'
+      ;;
+
+    newsos6)
+      lt_cv_prog_cc_pic='-KPIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      # All OSF/1 code is PIC.
+      lt_cv_prog_cc_wl='-Wl,'
+      lt_cv_prog_cc_static='-non_shared'
+      ;;
+
+    sco3.2v5*)
+      lt_cv_prog_cc_pic='-Kpic'
+      lt_cv_prog_cc_static='-dn'
+      lt_cv_prog_cc_shlib='-belf'
+      ;;
+
+    solaris*)
+      lt_cv_prog_cc_pic='-KPIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      lt_cv_prog_cc_wl='-Wl,'
+      ;;
+
+    sunos4*)
+      lt_cv_prog_cc_pic='-PIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      lt_cv_prog_cc_wl='-Qoption ld '
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+      lt_cv_prog_cc_pic='-KPIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      lt_cv_prog_cc_wl='-Wl,'
+      ;;
+
+    uts4*)
+      lt_cv_prog_cc_pic='-pic'
+      lt_cv_prog_cc_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	lt_cv_prog_cc_pic='-Kconform_pic'
+	lt_cv_prog_cc_static='-Bstatic'
+      fi
+      ;;
+
+    *)
+      lt_cv_prog_cc_can_build_shared=no
+      ;;
+    esac
+  fi
+])
+if test -z "$lt_cv_prog_cc_pic"; then
+  AC_MSG_RESULT([none])
+else
+  AC_MSG_RESULT([$lt_cv_prog_cc_pic])
+
+  # Check to make sure the pic_flag actually works.
+  AC_MSG_CHECKING([if $compiler PIC flag $lt_cv_prog_cc_pic works])
+  AC_CACHE_VAL(lt_cv_prog_cc_pic_works, [dnl
+    save_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC"
+    AC_TRY_COMPILE([], [], [dnl
+      case $host_os in
+      hpux9* | hpux10* | hpux11*)
+	# On HP-UX, both CC and GCC only warn that PIC is supported... then
+	# they create non-PIC objects.  So, if there were any warnings, we
+	# assume that PIC is not supported.
+	if test -s conftest.err; then
+	  lt_cv_prog_cc_pic_works=no
+	else
+	  lt_cv_prog_cc_pic_works=yes
+	fi
+	;;
+      *)
+	lt_cv_prog_cc_pic_works=yes
+	;;
+      esac
+    ], [dnl
+      lt_cv_prog_cc_pic_works=no
+    ])
+    CFLAGS="$save_CFLAGS"
+  ])
+
+  if test "X$lt_cv_prog_cc_pic_works" = Xno; then
+    lt_cv_prog_cc_pic=
+    lt_cv_prog_cc_can_build_shared=no
+  else
+    lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic"
+  fi
+
+  AC_MSG_RESULT([$lt_cv_prog_cc_pic_works])
+fi
+
+# Check for any special shared library compilation flags.
+if test -n "$lt_cv_prog_cc_shlib"; then
+  AC_MSG_WARN([\`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries])
+  if echo "$old_CC $old_CFLAGS " | egrep -e "[[ 	]]$lt_cv_prog_cc_shlib[[ 	]]" >/dev/null; then :
+  else
+   AC_MSG_WARN([add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure])
+    lt_cv_prog_cc_can_build_shared=no
+  fi
+fi
+
+AC_MSG_CHECKING([if $compiler static flag $lt_cv_prog_cc_static works])
+AC_CACHE_VAL([lt_cv_prog_cc_static_works], [dnl
+  lt_cv_prog_cc_static_works=no
+  save_LDFLAGS="$LDFLAGS"
+  LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static"
+  AC_TRY_LINK([], [], [lt_cv_prog_cc_static_works=yes])
+  LDFLAGS="$save_LDFLAGS"
+])
+
+# Belt *and* braces to stop my trousers falling down:
+test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static=
+AC_MSG_RESULT([$lt_cv_prog_cc_static_works])
+
+pic_flag="$lt_cv_prog_cc_pic"
+special_shlib_compile_flags="$lt_cv_prog_cc_shlib"
+wl="$lt_cv_prog_cc_wl"
+link_static_flag="$lt_cv_prog_cc_static"
+no_builtin_flag="$lt_cv_prog_cc_no_builtin"
+can_build_shared="$lt_cv_prog_cc_can_build_shared"
+
+
+# Check to see if options -o and -c are simultaneously supported by compiler
+AC_MSG_CHECKING([if $compiler supports -c -o file.$ac_objext])
+AC_CACHE_VAL([lt_cv_compiler_c_o], [
+$rm -r conftest 2>/dev/null
+mkdir conftest
+cd conftest
+echo "int some_variable = 0;" > conftest.$ac_ext
+mkdir out
+# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
+# that will create temporary files in the current directory regardless of
+# the output directory.  Thus, making CWD read-only will cause this test
+# to fail, enabling locking or at least warning the user not to do parallel
+# builds.
+chmod -w .
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+compiler_c_o=no
+if { (eval echo configure:__oline__: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+  # The compiler can only warn and ignore the option if not recognized
+  # So say no if there are warnings
+  if test -s out/conftest.err; then
+    lt_cv_compiler_c_o=no
+  else
+    lt_cv_compiler_c_o=yes
+  fi
+else
+  # Append any errors to the config.log.
+  cat out/conftest.err 1>&AC_FD_CC
+  lt_cv_compiler_c_o=no
+fi
+CFLAGS="$save_CFLAGS"
+chmod u+w .
+$rm conftest* out/*
+rmdir out
+cd ..
+rmdir conftest
+$rm -r conftest 2>/dev/null
+])
+compiler_c_o=$lt_cv_compiler_c_o
+AC_MSG_RESULT([$compiler_c_o])
+
+if test x"$compiler_c_o" = x"yes"; then
+  # Check to see if we can write to a .lo
+  AC_MSG_CHECKING([if $compiler supports -c -o file.lo])
+  AC_CACHE_VAL([lt_cv_compiler_o_lo], [
+  lt_cv_compiler_o_lo=no
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -c -o conftest.lo"
+  save_objext="$ac_objext"
+  ac_objext=lo
+  AC_TRY_COMPILE([], [int some_variable = 0;], [dnl
+    # The compiler can only warn and ignore the option if not recognized
+    # So say no if there are warnings
+    if test -s conftest.err; then
+      lt_cv_compiler_o_lo=no
+    else
+      lt_cv_compiler_o_lo=yes
+    fi
+  ])
+  ac_objext="$save_objext"
+  CFLAGS="$save_CFLAGS"
+  ])
+  compiler_o_lo=$lt_cv_compiler_o_lo
+  AC_MSG_RESULT([$compiler_o_lo])
+else
+  compiler_o_lo=no
+fi
+
+# Check to see if we can do hard links to lock some files if needed
+hard_links="nottested"
+if test "$compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test "$hard_links" = no; then
+    AC_MSG_WARN([\`$CC' does not support \`-c -o', so \`make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+if test "$GCC" = yes; then
+  # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+  AC_MSG_CHECKING([if $compiler supports -fno-rtti -fno-exceptions])
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext"
+  compiler_rtti_exceptions=no
+  AC_TRY_COMPILE([], [int some_variable = 0;], [dnl
+    # The compiler can only warn and ignore the option if not recognized
+    # So say no if there are warnings
+    if test -s conftest.err; then
+      compiler_rtti_exceptions=no
+    else
+      compiler_rtti_exceptions=yes
+    fi
+  ])
+  CFLAGS="$save_CFLAGS"
+  AC_MSG_RESULT([$compiler_rtti_exceptions])
+
+  if test "$compiler_rtti_exceptions" = "yes"; then
+    no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
+  else
+    no_builtin_flag=' -fno-builtin'
+  fi
+fi
+
+# See if the linker supports building shared libraries.
+AC_MSG_CHECKING([whether the linker ($LD) supports shared libraries])
+
+allow_undefined_flag=
+no_undefined_flag=
+need_lib_prefix=unknown
+need_version=unknown
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+archive_cmds=
+archive_expsym_cmds=
+old_archive_from_new_cmds=
+old_archive_from_expsyms_cmds=
+export_dynamic_flag_spec=
+whole_archive_flag_spec=
+thread_safe_flag_spec=
+hardcode_into_libs=no
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+hardcode_shlibpath_var=unsupported
+runpath_var=
+link_all_deplibs=unknown
+always_export_symbols=no
+export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
+# include_expsyms should be a list of space-separated symbols to be *always*
+# included in the symbol list
+include_expsyms=
+# exclude_expsyms can be an egrep regular expression of symbols to exclude
+# it will be wrapped by ` (' and `)$', so one must not match beginning or
+# end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+# as well as any symbol that contains `d'.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+# platforms (ab)use it in PIC code, but their linkers get confused if
+# the symbol is explicitly referenced.  Since portable code cannot
+# rely on this symbol name, it's probably fine to never include it in
+# preloaded symbol tables.
+extract_expsyms_cmds=
+
+case $host_os in
+cygwin* | mingw* | pw32*)
+  # FIXME: the MSVC++ port hasn't been tested in a loooong time
+  # When not using gcc, we currently assume that we are using
+  # Microsoft Visual C++.
+  if test "$GCC" != yes; then
+    with_gnu_ld=no
+  fi
+  ;;
+openbsd*)
+  with_gnu_ld=no
+  ;;
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+  # If archive_cmds runs LD, not CC, wlarc should be empty
+  wlarc='${wl}'
+
+  # See if GNU ld supports shared libraries.
+  case $host_os in
+  aix3* | aix4* | aix5*)
+    # On AIX, the GNU linker is very broken
+    # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available.
+    ld_shlibs=no
+    cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+    ;;
+
+  amigaos*)
+    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+
+    # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+    # that the semantics of dynamic libraries on AmigaOS, at least up
+    # to version 4, is to share data among multiple programs linked
+    # with the same dynamic library.  Since this doesn't match the
+    # behavior of shared libraries on other platforms, we can use
+    # them.
+    ld_shlibs=no
+    ;;
+
+  beos*)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      allow_undefined_flag=unsupported
+      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+      # support --undefined.  This deserves some investigation.  FIXME
+      archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # hardcode_libdir_flag_spec is actually meaningless, as there is
+    # no search path for DLLs.
+    hardcode_libdir_flag_spec='-L$libdir'
+    allow_undefined_flag=unsupported
+    always_export_symbols=yes
+
+    extract_expsyms_cmds='test -f $output_objdir/impgen.c || \
+      sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~
+      test -f $output_objdir/impgen.exe || (cd $output_objdir && \
+      if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \
+      else $CC -o impgen impgen.c ; fi)~
+      $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def'
+
+    old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib'
+
+    # cygwin and mingw dlls have different entry points and sets of symbols
+    # to exclude.
+    # FIXME: what about values for MSVC?
+    dll_entry=__cygwin_dll_entry@12
+    dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~
+    case $host_os in
+    mingw*)
+      # mingw values
+      dll_entry=_DllMainCRTStartup@12
+      dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~
+      ;;
+    esac
+
+    # mingw and cygwin differ, and it's simplest to just exclude the union
+    # of the two symbol sets.
+    dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12
+
+    # recent cygwin and mingw systems supply a stub DllMain which the user
+    # can override, but on older systems we have to supply one (in ltdll.c)
+    if test "x$lt_cv_need_dllmain" = "xyes"; then
+      ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext "
+      ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~
+	test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~'
+    else
+      ltdll_obj=
+      ltdll_cmds=
+    fi
+
+    # Extract the symbol export list from an `--export-all' def file,
+    # then regenerate the def file from the symbol export list, so that
+    # the compiled dll only exports the symbol export list.
+    # Be careful not to strip the DATA tag left be newer dlltools.
+    export_symbols_cmds="$ltdll_cmds"'
+      $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~
+      sed -e "1,/EXPORTS/d" -e "s/ @ [[0-9]]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols'
+
+    # If the export-symbols file already is a .def file (1st line
+    # is EXPORTS), use it as is.
+    # If DATA tags from a recent dlltool are present, honour them!
+    archive_expsym_cmds='if test "x`sed 1q $export_symbols`" = xEXPORTS; then
+	cp $export_symbols $output_objdir/$soname-def;
+      else
+	echo EXPORTS > $output_objdir/$soname-def;
+	_lt_hint=1;
+	cat $export_symbols | while read symbol; do
+	 set dummy \$symbol;
+	 case \[$]# in
+	   2) echo "   \[$]2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;;
+	   4) echo "   \[$]2 \[$]3 \[$]4 ; " >> $output_objdir/$soname-def; _lt_hint=`expr \$_lt_hint - 1`;;
+	   *) echo "     \[$]2 @ \$_lt_hint \[$]3 ; " >> $output_objdir/$soname-def;;
+	 esac;
+	 _lt_hint=`expr 1 + \$_lt_hint`;
+	done;
+      fi~
+      '"$ltdll_cmds"'
+      $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~
+      $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~
+      $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags'
+    ;;
+
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+      wlarc=
+    else
+      archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    fi
+    ;;
+
+  solaris* | sysv5*)
+    if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
+      ld_shlibs=no
+      cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+    elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+
+  sunos4*)
+    archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+    wlarc=
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  *)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+  esac
+
+  if test "$ld_shlibs" = yes; then
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    case $host_os in
+    cygwin* | mingw* | pw32*)
+      # dlltool doesn't understand --whole-archive et. al.
+      whole_archive_flag_spec=
+      ;;
+    *)
+      # ancient GNU ld didn't support --whole-archive et. al.
+      if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
+	whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+	whole_archive_flag_spec=
+      fi
+      ;;
+    esac
+  fi
+else
+  # PORTME fill in a description of your system's linker (not GNU ld)
+  case $host_os in
+  aix3*)
+    allow_undefined_flag=unsupported
+    always_export_symbols=yes
+    archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+    # Note: this linker hardcodes the directories in LIBPATH if there
+    # are no directories specified by -L.
+    hardcode_minus_L=yes
+    if test "$GCC" = yes && test -z "$link_static_flag"; then
+      # Neither direct hardcoding nor static linking is supported with a
+      # broken collect2.
+      hardcode_direct=unsupported
+    fi
+    ;;
+
+  aix4* | aix5*)
+    if test "$host_cpu" = ia64; then
+      # On IA64, the linker does run time linking by default, so we don't
+      # have to do anything special.
+      aix_use_runtimelinking=no
+      exp_sym_flag='-Bexport'
+      no_entry_flag=""
+    else
+      aix_use_runtimelinking=no
+
+      # Test if we are trying to use run time linking or normal
+      # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+      # need to do runtime linking.
+      case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+	for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	done
+      esac
+
+      exp_sym_flag='-bexport'
+      no_entry_flag='-bnoentry'
+    fi
+
+    # When large executables or shared objects are built, AIX ld can
+    # have problems creating the table of contents.  If linking a library
+    # or program results in "error TOC overflow" add -mminimal-toc to
+    # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+    # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+    hardcode_direct=yes
+    archive_cmds=''
+    hardcode_libdir_separator=':'
+    if test "$GCC" = yes; then
+      case $host_os in aix4.[[012]]|aix4.[[012]].*)
+	collect2name=`${CC} -print-prog-name=collect2`
+	if test -f "$collect2name" && \
+	  strings "$collect2name" | grep resolve_lib_name >/dev/null
+	then
+	  # We have reworked collect2
+	  hardcode_direct=yes
+	else
+	  # We have old collect2
+	  hardcode_direct=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  hardcode_minus_L=yes
+	  hardcode_libdir_flag_spec='-L$libdir'
+	  hardcode_libdir_separator=
+	fi
+      esac
+
+      shared_flag='-shared'
+    else
+      # not using gcc
+      if test "$host_cpu" = ia64; then
+	shared_flag='${wl}-G'
+      else
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag='${wl}-G'
+	else
+	  shared_flag='${wl}-bM:SRE'
+	fi
+      fi
+    fi
+
+    # It seems that -bexpall can do strange things, so it is better to
+    # generate a list of symbols to export.
+    always_export_symbols=yes
+    if test "$aix_use_runtimelinking" = yes; then
+      # Warning - without using the other runtime loading flags (-brtl),
+      # -berok will link without error, but may produce a broken library.
+      allow_undefined_flag='-berok'
+      hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib'
+      archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+    else
+      if test "$host_cpu" = ia64; then
+	hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+	allow_undefined_flag="-z nodefs"
+	archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+      else
+	hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib'
+	# Warning - without using the other run time loading flags,
+	# -berok will link without error, but may produce a broken library.
+	allow_undefined_flag='${wl}-berok'
+	# This is a bit strange, but is similar to how AIX traditionally builds
+	# it's shared libraries.
+	archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname'
+      fi
+    fi
+    ;;
+
+  amigaos*)
+    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+    # see comment about different semantics on the GNU ld section
+    ld_shlibs=no
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    # hardcode_libdir_flag_spec is actually meaningless, as there is
+    # no search path for DLLs.
+    hardcode_libdir_flag_spec=' '
+    allow_undefined_flag=unsupported
+    # Tell ltmain to make .lib files, not .a files.
+    libext=lib
+    # FIXME: Setting linknames here is a bad hack.
+    archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+    # The linker will automatically build a .lib file if we build a DLL.
+    old_archive_from_new_cmds='true'
+    # FIXME: Should let the user specify the lib program.
+    old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
+    fix_srcfile_path='`cygpath -w "$srcfile"`'
+    ;;
+
+  darwin* | rhapsody*)
+    case "$host_os" in
+    rhapsody* | darwin1.[[012]])
+      allow_undefined_flag='-undefined suppress'
+      ;;
+    *) # Darwin 1.3 on
+      allow_undefined_flag='-flat_namespace -undefined suppress'
+      ;;
+    esac
+    # FIXME: Relying on posixy $() will cause problems for
+    #        cross-compilation, but unfortunately the echo tests do not
+    #        yet detect zsh echo's removal of \ escapes.  Also zsh mangles
+    #	     `"' quotes if we put them in here... so don't!
+    archive_cmds='$nonopt $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs$linker_flags -install_name $rpath/$soname $verstring'
+    # We need to add '_' to the symbols in $export_symbols first
+    #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    whole_archive_flag_spec='-all_load $convenience'
+    ;;
+
+  freebsd1*)
+    ld_shlibs=no
+    ;;
+
+  # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+  # support.  Future versions do this automatically, but an explicit c++rt0.o
+  # does not break anything, and helps significantly (at the cost of a little
+  # extra space).
+  freebsd2.2*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+  freebsd2*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_direct=yes
+    hardcode_minus_L=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+  freebsd*)
+    archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  hpux9* | hpux10* | hpux11*)
+    case $host_os in
+    hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;;
+    *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;;
+    esac
+    hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+    hardcode_libdir_separator=:
+    hardcode_direct=yes
+    hardcode_minus_L=yes # Not in the search PATH, but as the default
+			 # location of the library.
+    export_dynamic_flag_spec='${wl}-E'
+    ;;
+
+  irix5* | irix6* | nonstopux*)
+    if test "$GCC" = yes; then
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+    else
+      archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    link_all_deplibs=yes
+    ;;
+
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+    else
+      archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+    fi
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  newsos6)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_direct=yes
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    hardcode_shlibpath_var=no
+    ;;
+
+  openbsd*)
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+    else
+      case "$host_os" in
+      openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	hardcode_libdir_flag_spec='-R$libdir'
+        ;;
+      *)
+        archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags'
+        hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+        ;;
+      esac
+    fi
+    ;;
+
+  os2*)
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+    allow_undefined_flag=unsupported
+    archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+    old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+    ;;
+
+  osf3*)
+    if test "$GCC" = yes; then
+      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+    else
+      allow_undefined_flag=' -expect_unresolved \*'
+      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    ;;
+
+  osf4* | osf5*)	# as osf3* with the addition of -msym flag
+    if test "$GCC" = yes; then
+      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    else
+      allow_undefined_flag=' -expect_unresolved \*'
+      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+      $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+
+      #Both c and cxx compiler support -rpath directly
+      hardcode_libdir_flag_spec='-rpath $libdir'
+    fi
+    hardcode_libdir_separator=:
+    ;;
+
+  sco3.2v5*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_shlibpath_var=no
+    runpath_var=LD_RUN_PATH
+    hardcode_runpath_var=yes
+    export_dynamic_flag_spec='${wl}-Bexport'
+    ;;
+
+  solaris*)
+    # gcc --version < 3.0 without binutils cannot create self contained
+    # shared libraries reliably, requiring libgcc.a to resolve some of
+    # the object symbols generated in some cases.  Libraries that use
+    # assert need libgcc.a to resolve __eprintf, for example.  Linking
+    # a copy of libgcc.a into every shared library to guarantee resolving
+    # such symbols causes other problems:  According to Tim Van Holder
+    # <tim.van.holder@pandora.be>, C++ libraries end up with a separate
+    # (to the application) exception stack for one thing.
+    no_undefined_flag=' -z defs'
+    if test "$GCC" = yes; then
+      case `$CC --version 2>/dev/null` in
+      [[12]].*)
+	cat <<EOF 1>&2
+
+*** Warning: Releases of GCC earlier than version 3.0 cannot reliably
+*** create self contained shared libraries on Solaris systems, without
+*** introducing a dependency on libgcc.a.  Therefore, libtool is disabling
+*** -no-undefined support, which will at least allow you to build shared
+*** libraries.  However, you may find that when you link such libraries
+*** into an application without using GCC, you have to manually add
+*** \`gcc --print-libgcc-file-name\` to the link command.  We urge you to
+*** upgrade to a newer version of GCC.  Another option is to rebuild your
+*** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer.
+
+EOF
+        no_undefined_flag=
+	;;
+      esac
+    fi
+    # $CC -shared without GNU ld will not create a library from C++
+    # object files and a static libstdc++, better avoid it by now
+    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+		$LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_shlibpath_var=no
+    case $host_os in
+    solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+    *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+      whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+    esac
+    link_all_deplibs=yes
+    ;;
+
+  sunos4*)
+    if test "x$host_vendor" = xsequent; then
+      # Use $CC to link under sequent, because it throws in some extra .o
+      # files that make .init and .fini sections work.
+      archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+    else
+      archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+    fi
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_direct=yes
+    hardcode_minus_L=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4)
+    case $host_vendor in
+      sni)
+        archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+        hardcode_direct=yes # is this really true???
+        ;;
+      siemens)
+        ## LD is ld it makes a PLAMLIB
+        ## CC just makes a GrossModule.
+        archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+        reload_cmds='$CC -r -o $output$reload_objs'
+        hardcode_direct=no
+        ;;
+      motorola)
+        archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+        hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+        ;;
+    esac
+    runpath_var='LD_RUN_PATH'
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4.3*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_shlibpath_var=no
+    export_dynamic_flag_spec='-Bexport'
+    ;;
+
+  sysv5*)
+    no_undefined_flag=' -z text'
+    # $CC -shared without GNU ld will not create a library from C++
+    # object files and a static libstdc++, better avoid it by now
+    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+		$LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+    hardcode_libdir_flag_spec=
+    hardcode_shlibpath_var=no
+    runpath_var='LD_RUN_PATH'
+    ;;
+
+  uts4*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_shlibpath_var=no
+    ;;
+
+  dgux*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4*MP*)
+    if test -d /usr/nec; then
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      runpath_var=LD_RUN_PATH
+      hardcode_runpath_var=yes
+      ld_shlibs=yes
+    fi
+    ;;
+
+  sysv4.2uw2*)
+    archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_direct=yes
+    hardcode_minus_L=no
+    hardcode_shlibpath_var=no
+    hardcode_runpath_var=yes
+    runpath_var=LD_RUN_PATH
+    ;;
+
+  sysv5uw7* | unixware7*)
+    no_undefined_flag='${wl}-z ${wl}text'
+    if test "$GCC" = yes; then
+      archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+    else
+      archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+    fi
+    runpath_var='LD_RUN_PATH'
+    hardcode_shlibpath_var=no
+    ;;
+
+  *)
+    ld_shlibs=no
+    ;;
+  esac
+fi
+AC_MSG_RESULT([$ld_shlibs])
+test "$ld_shlibs" = no && can_build_shared=no
+
+# Check hardcoding attributes.
+AC_MSG_CHECKING([how to hardcode library paths into programs])
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+   test -n "$runpath_var"; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$hardcode_shlibpath_var" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+AC_MSG_RESULT([$hardcode_action])
+
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+  AC_MSG_RESULT([no])
+fi
+
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+# PORTME Fill in your ld.so characteristics
+AC_MSG_CHECKING([dynamic linker characteristics])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}.so$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+	if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	     echo ' yes '
+	     echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+	  :
+	else
+	  can_build_shared=no
+	fi
+	;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can
+    # not hardcode correct soname into executable. Probably we can
+    # add versioning support to collect2, so additional links can
+    # be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}.so$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}.so'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi4*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  export_dynamic_flag_spec=-rdynamic
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  need_version=no
+  need_lib_prefix=no
+  case $GCC,$host_os in
+  yes,cygwin*)
+    library_names_spec='$libname.dll.a'
+    soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll'
+    postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog .libs/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    ;;
+  yes,mingw*)
+    library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll'
+    sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g" -e "s,=/,/,g"`
+    ;;
+  yes,pw32*)
+    library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll'
+    ;;
+  *)
+    library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  # FIXME: Relying on posixy $() will cause problems for
+  #        cross-compilation, but unfortunately the echo tests do not
+  #        yet detect zsh echo's removal of \ escapes.
+  library_names_spec='${libname}${release}${versuffix}.$(test .$module = .yes && echo so || echo dylib) ${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib) ${libname}.$(test .$module = .yes && echo so || echo dylib)'
+  soname_spec='${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib)'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd*)
+  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  *)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  dynamic_linker="$host_os dld.sl"
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  shlibpath_var=SHLIB_PATH
+  shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+  library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
+  soname_spec='${libname}${release}.sl$major'
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)          version_type=irix ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}.so$major'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
+    soname_spec='${libname}${release}.so$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case "$host_os" in
+    openbsd2.[[89]] | openbsd2.[[89]].*)
+      shlibpath_overrides_runpath=no
+      ;;
+    *)
+      shlibpath_overrides_runpath=yes
+      ;;
+    esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+os2*)
+  libname_spec='$name'
+  need_lib_prefix=no
+  library_names_spec='$libname.dll $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_version=no
+  soname_spec='${libname}${release}.so'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+sco3.2v5*)
+  version_type=osf
+  soname_spec='${libname}${release}.so$major'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+    soname_spec='$libname.so.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+# Report the final consequences.
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+
+aix4*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+  ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+if test "$hardcode_action" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+AC_LIBTOOL_DLOPEN_SELF
+
+if test "$enable_shared" = yes && test "$GCC" = yes; then
+  case $archive_cmds in
+  *'~'*)
+    # FIXME: we may have to deal with multi-command sequences.
+    ;;
+  '$CC '*)
+    # Test whether the compiler implicitly links with -lc since on some
+    # systems, -lgcc has to come before -lc. If gcc already passes -lc
+    # to ld, don't add -lc before -lgcc.
+    AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+    AC_CACHE_VAL([lt_cv_archive_cmds_need_lc],
+    [$rm conftest*
+    echo 'static int dummy;' > conftest.$ac_ext
+
+    if AC_TRY_EVAL(ac_compile); then
+      soname=conftest
+      lib=conftest
+      libobjs=conftest.$ac_objext
+      deplibs=
+      wl=$lt_cv_prog_cc_wl
+      compiler_flags=-v
+      linker_flags=-v
+      verstring=
+      output_objdir=.
+      libname=conftest
+      save_allow_undefined_flag=$allow_undefined_flag
+      allow_undefined_flag=
+      if AC_TRY_EVAL(archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+      then
+	lt_cv_archive_cmds_need_lc=no
+      else
+	lt_cv_archive_cmds_need_lc=yes
+      fi
+      allow_undefined_flag=$save_allow_undefined_flag
+    else
+      cat conftest.err 1>&5
+    fi])
+    AC_MSG_RESULT([$lt_cv_archive_cmds_need_lc])
+    ;;
+  esac
+fi
+need_lc=${lt_cv_archive_cmds_need_lc-yes}
+
+# The second clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  :
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  test -f Makefile && make "$ltmain"
+fi
+
+if test -f "$ltmain"; then
+  trap "$rm \"${ofile}T\"; exit 1" 1 2 15
+  $rm -f "${ofile}T"
+
+  echo creating $ofile
+
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS SED \
+    AR AR_FLAGS CC LD LN_S NM SHELL \
+    reload_flag reload_cmds wl \
+    pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+    thread_safe_flag_spec whole_archive_flag_spec libname_spec \
+    library_names_spec soname_spec \
+    RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+    old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \
+    postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \
+    old_striplib striplib file_magic_cmd export_symbols_cmds \
+    deplibs_check_method allow_undefined_flag no_undefined_flag \
+    finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
+    global_symbol_to_c_name_address \
+    hardcode_libdir_flag_spec hardcode_libdir_separator  \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+
+    case $var in
+    reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
+    extract_expsyms_cmds | old_archive_from_expsyms_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  cat <<__EOF__ > "${ofile}T"
+#! $SHELL
+
+# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996-2000 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="${SED} -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$need_lc
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# The default C compiler.
+CC=$lt_CC
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_wl
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_pic_flag
+pic_mode=$pic_mode
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_compiler_c_o
+
+# Can we write directly to a .lo ?
+compiler_o_lo=$lt_compiler_o_lo
+
+# Must we lock files when doing compilation ?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_link_static_flag
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# ### END LIBTOOL CONFIG
+
+__EOF__
+
+  case $host_os in
+  aix3*)
+    cat <<\EOF >> "${ofile}T"
+
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+EOF
+    ;;
+  esac
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | os2*)
+    cat <<'EOF' >> "${ofile}T"
+      # This is a source program that is used to create dlls on Windows
+      # Don't remove nor modify the starting and closing comments
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# #  ifdef __CYGWIN32__
+# #    define __CYGWIN__ __CYGWIN32__
+# #  endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+#   __hDllInstance_base = hInst;
+#   return TRUE;
+# }
+# /* ltdll.c ends here */
+	# This is a source program that is used to create import libraries
+	# on Windows for dlls which lack them. Don't remove nor modify the
+	# starting and closing comments
+# /* impgen.c starts here */
+# /*   Copyright (C) 1999-2000 Free Software Foundation, Inc.
+#
+#  This file is part of GNU libtool.
+#
+#  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 of the License, 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 program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#  */
+#
+# #include <stdio.h>		/* for printf() */
+# #include <unistd.h>		/* for open(), lseek(), read() */
+# #include <fcntl.h>		/* for O_RDONLY, O_BINARY */
+# #include <string.h>		/* for strdup() */
+#
+# /* O_BINARY isn't required (or even defined sometimes) under Unix */
+# #ifndef O_BINARY
+# #define O_BINARY 0
+# #endif
+#
+# static unsigned int
+# pe_get16 (fd, offset)
+#      int fd;
+#      int offset;
+# {
+#   unsigned char b[2];
+#   lseek (fd, offset, SEEK_SET);
+#   read (fd, b, 2);
+#   return b[0] + (b[1]<<8);
+# }
+#
+# static unsigned int
+# pe_get32 (fd, offset)
+#     int fd;
+#     int offset;
+# {
+#   unsigned char b[4];
+#   lseek (fd, offset, SEEK_SET);
+#   read (fd, b, 4);
+#   return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# static unsigned int
+# pe_as32 (ptr)
+#      void *ptr;
+# {
+#   unsigned char *b = ptr;
+#   return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# int
+# main (argc, argv)
+#     int argc;
+#     char *argv[];
+# {
+#     int dll;
+#     unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+#     unsigned long export_rva, export_size, nsections, secptr, expptr;
+#     unsigned long name_rvas, nexp;
+#     unsigned char *expdata, *erva;
+#     char *filename, *dll_name;
+#
+#     filename = argv[1];
+#
+#     dll = open(filename, O_RDONLY|O_BINARY);
+#     if (dll < 1)
+# 	return 1;
+#
+#     dll_name = filename;
+#
+#     for (i=0; filename[i]; i++)
+# 	if (filename[i] == '/' || filename[i] == '\\'  || filename[i] == ':')
+# 	    dll_name = filename + i +1;
+#
+#     pe_header_offset = pe_get32 (dll, 0x3c);
+#     opthdr_ofs = pe_header_offset + 4 + 20;
+#     num_entries = pe_get32 (dll, opthdr_ofs + 92);
+#
+#     if (num_entries < 1) /* no exports */
+# 	return 1;
+#
+#     export_rva = pe_get32 (dll, opthdr_ofs + 96);
+#     export_size = pe_get32 (dll, opthdr_ofs + 100);
+#     nsections = pe_get16 (dll, pe_header_offset + 4 +2);
+#     secptr = (pe_header_offset + 4 + 20 +
+# 	      pe_get16 (dll, pe_header_offset + 4 + 16));
+#
+#     expptr = 0;
+#     for (i = 0; i < nsections; i++)
+#     {
+# 	char sname[8];
+# 	unsigned long secptr1 = secptr + 40 * i;
+# 	unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+# 	unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+# 	unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+# 	lseek(dll, secptr1, SEEK_SET);
+# 	read(dll, sname, 8);
+# 	if (vaddr <= export_rva && vaddr+vsize > export_rva)
+# 	{
+# 	    expptr = fptr + (export_rva - vaddr);
+# 	    if (export_rva + export_size > vaddr + vsize)
+# 		export_size = vsize - (export_rva - vaddr);
+# 	    break;
+# 	}
+#     }
+#
+#     expdata = (unsigned char*)malloc(export_size);
+#     lseek (dll, expptr, SEEK_SET);
+#     read (dll, expdata, export_size);
+#     erva = expdata - export_rva;
+#
+#     nexp = pe_as32 (expdata+24);
+#     name_rvas = pe_as32 (expdata+32);
+#
+#     printf ("EXPORTS\n");
+#     for (i = 0; i<nexp; i++)
+#     {
+# 	unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
+# 	printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
+#     }
+#
+#     return 0;
+# }
+# /* impgen.c ends here */
+
+EOF
+    ;;
+  esac
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "${ofile}T" || (rm -f "${ofile}T"; exit 1)
+
+  mv -f "${ofile}T" "$ofile" || \
+    (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T")
+  chmod +x "$ofile"
+fi
+
+])# _LT_AC_LTCONFIG_HACK
+
+# AC_LIBTOOL_DLOPEN - enable checks for dlopen support
+AC_DEFUN([AC_LIBTOOL_DLOPEN], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])])
+
+# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's
+AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])])
+
+# AC_ENABLE_SHARED - implement the --enable-shared flag
+# Usage: AC_ENABLE_SHARED[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN([AC_ENABLE_SHARED],
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(shared,
+changequote(<<, >>)dnl
+<<  --enable-shared[=PKGS]  build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case $enableval in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
+])
+
+# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
+AC_DEFUN([AC_DISABLE_SHARED],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)])
+
+# AC_ENABLE_STATIC - implement the --enable-static flag
+# Usage: AC_ENABLE_STATIC[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN([AC_ENABLE_STATIC],
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(static,
+changequote(<<, >>)dnl
+<<  --enable-static[=PKGS]  build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case $enableval in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
+])
+
+# AC_DISABLE_STATIC - set the default static flag to --disable-static
+AC_DEFUN([AC_DISABLE_STATIC],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)])
+
+
+# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
+# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(fast-install,
+changequote(<<, >>)dnl
+<<  --enable-fast-install[=PKGS]  optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case $enableval in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
+])
+
+# AC_DISABLE_FAST_INSTALL - set the default to --disable-fast-install
+AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)])
+
+# AC_LIBTOOL_PICMODE - implement the --with-pic flag
+# Usage: AC_LIBTOOL_PICMODE[(MODE)]
+#   Where MODE is either `yes' or `no'.  If omitted, it defaults to
+#   `both'.
+AC_DEFUN([AC_LIBTOOL_PICMODE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+pic_mode=ifelse($#,1,$1,default)])
+
+
+# AC_PATH_TOOL_PREFIX - find a file program which can recognise shared library
+AC_DEFUN([AC_PATH_TOOL_PREFIX],
+[AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+  /*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+  ?:/*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
+  ;;
+  *)
+  ac_save_MAGIC_CMD="$MAGIC_CMD"
+  IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS=":"
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="ifelse([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$1; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    egrep "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  MAGIC_CMD="$ac_save_MAGIC_CMD"
+  ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+])
+
+
+# AC_PATH_MAGIC - find a file program which can recognise a shared library
+AC_DEFUN([AC_PATH_MAGIC],
+[AC_REQUIRE([AC_CHECK_TOOL_PREFIX])dnl
+AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin:$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    AC_PATH_TOOL_PREFIX(file, /usr/bin:$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])
+
+
+# AC_PROG_LD - find the path to the GNU or non-GNU linker
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH(gnu-ld,
+[  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by GCC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | [[A-Za-z]]:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+	test "$with_gnu_ld" != no && break
+      else
+	test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])
+
+# AC_PROG_LD_GNU -
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  lt_cv_prog_gnu_ld=yes
+else
+  lt_cv_prog_gnu_ld=no
+fi])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])
+
+# AC_PROG_LD_RELOAD_FLAG - find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+[AC_CACHE_CHECK([for $LD option to reload object files], lt_cv_ld_reload_flag,
+[lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+])
+
+# AC_DEPLIBS_CHECK_METHOD - how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+[AC_CACHE_CHECK([how to recognise dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given egrep regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi4*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin* | mingw* | pw32*)
+  lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  case "$host_os" in
+  rhapsody* | darwin1.[[012]])
+    lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1`
+    ;;
+  *) # Darwin 1.3 on
+    lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib'
+    ;;
+  esac
+  ;;
+
+freebsd*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20*|hpux11*)
+  lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libc.sl
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+  irix5* | nonstopux*)
+    # this will be overridden with pass_all, but let us keep it just in case
+    lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+    ;;
+  *)
+    case $LD in
+    *-32|*"-32 ") libmagic=32-bit;;
+    *-n32|*"-n32 ") libmagic=N32;;
+    *-64|*"-64 ") libmagic=64-bit;;
+    *) libmagic=never-match;;
+    esac
+    # this will be overridden with pass_all, but let us keep it just in case
+    lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1"
+    ;;
+  esac
+  lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+  case $host_cpu in
+  alpha* | hppa* | i*86 | mips | mipsel | powerpc* | sparc* | ia64*)
+    lt_cv_deplibs_check_method=pass_all ;;
+  *)
+    # glibc up to 2.1.1 does not perform some relocations on ARM
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;;
+  esac
+  lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so\.[[0-9]]+\.[[0-9]]+$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+openbsd*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object'
+  else
+    lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  # this will be overridden with pass_all, but let us keep it just in case
+  lt_cv_deplibs_check_method='file_magic COFF format alpha shared library'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sco3.2v5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  lt_cv_file_magic_test_file=/lib/libc.so
+  ;;
+
+sysv5uw[[78]]* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+])
+
+
+# AC_PROG_NM - find the path to a BSD-compatible name lister
+AC_DEFUN([AC_PROG_NM],
+[AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl
+AC_MSG_CHECKING([for BSD-compatible nm])
+AC_CACHE_VAL(lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    tmp_nm=$ac_dir/${ac_tool_prefix}nm
+    if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      # Tru64's nm complains that /dev/null is an invalid object file
+      if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then
+	lt_cv_path_NM="$tmp_nm -B"
+	break
+      elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+	lt_cv_path_NM="$tmp_nm -p"
+	break
+      else
+	lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi])
+NM="$lt_cv_path_NM"
+AC_MSG_RESULT([$NM])
+])
+
+# AC_CHECK_LIBM - check for math library
+AC_DEFUN([AC_CHECK_LIBM],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32*)
+  # These system don't have libm
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, main, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, main, LIBM="-lm")
+  ;;
+esac
+])
+
+# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl convenience library and LTDLINCL to the include flags for
+# the libltdl header and adds --enable-ltdl-convenience to the
+# configure arguments.  Note that LIBLTDL and LTDLINCL are not
+# AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  If DIR is not
+# provided, it is assumed to be `libltdl'.  LIBLTDL will be prefixed
+# with '${top_builddir}/' and LTDLINCL will be prefixed with
+# '${top_srcdir}/' (note the single quotes!).  If your package is not
+# flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  case $enable_ltdl_convenience in
+  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+  esac
+  LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+  LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  # For backwards non-gettext consistent compatibility...
+  INCLTDL="$LTDLINCL"
+])
+
+# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl installable library and LTDLINCL to the include flags for
+# the libltdl header and adds --enable-ltdl-install to the configure
+# arguments.  Note that LIBLTDL and LTDLINCL are not AC_SUBSTed, nor is
+# AC_CONFIG_SUBDIRS called.  If DIR is not provided and an installed
+# libltdl is not found, it is assumed to be `libltdl'.  LIBLTDL will
+# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed
+# with '${top_srcdir}/' (note the single quotes!).  If your package is
+# not flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  AC_CHECK_LIB(ltdl, main,
+  [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+  [if test x"$enable_ltdl_install" = xno; then
+     AC_MSG_WARN([libltdl not installed, but installation disabled])
+   else
+     enable_ltdl_install=yes
+   fi
+  ])
+  if test x"$enable_ltdl_install" = x"yes"; then
+    ac_configure_args="$ac_configure_args --enable-ltdl-install"
+    LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+    LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  else
+    ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+    LIBLTDL="-lltdl"
+    LTDLINCL=
+  fi
+  # For backwards non-gettext consistent compatibility...
+  INCLTDL="$LTDLINCL"
+])
+
+# old names
+AC_DEFUN([AM_PROG_LIBTOOL],   [AC_PROG_LIBTOOL])
+AC_DEFUN([AM_ENABLE_SHARED],  [AC_ENABLE_SHARED($@)])
+AC_DEFUN([AM_ENABLE_STATIC],  [AC_ENABLE_STATIC($@)])
+AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+AC_DEFUN([AM_PROG_LD],        [AC_PROG_LD])
+AC_DEFUN([AM_PROG_NM],        [AC_PROG_NM])
+
+# This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])
+
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+# LT_AC_PROG_SED
+# --------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+AC_DEFUN([LT_AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_executable_p="test -f"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+        _sed_list="$_sed_list $as_dir/$ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+
+  # Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+: ${TMPDIR=/tmp}
+{
+  tmp=`(umask 077 && mktemp -d -q "$TMPDIR/sedXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=$TMPDIR/sed$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in $TMPDIR" >&2
+   { (exit 1); exit 1; }
+}
+  _max=0
+  _count=0
+  # Add /usr/xpg4/bin/sed as it is typically found on Solaris
+  # along with /bin/sed that truncates output.
+  for _sed in $_sed_list /usr/xpg4/bin/sed; do
+    test ! -f ${_sed} && break
+    cat /dev/null > "$tmp/sed.in"
+    _count=0
+    echo ${ECHO_N-$ac_n} "0123456789${ECHO_C-$ac_c}" >"$tmp/sed.in"
+    # Check for GNU sed and select it if it is found.
+    if "${_sed}" --version 2>&1 < /dev/null | egrep '(GNU)' > /dev/null; then
+      lt_cv_path_SED=${_sed}
+      break;
+    fi
+    while true; do
+      cat "$tmp/sed.in" "$tmp/sed.in" >"$tmp/sed.tmp"
+      mv "$tmp/sed.tmp" "$tmp/sed.in"
+      cp "$tmp/sed.in" "$tmp/sed.nl"
+      echo >>"$tmp/sed.nl"
+      ${_sed} -e 's/a$//' < "$tmp/sed.nl" >"$tmp/sed.out" || break
+      cmp -s "$tmp/sed.out" "$tmp/sed.nl" || break
+      # 40000 chars as input seems more than enough
+      test $_count -gt 10 && break
+      _count=`expr $_count + 1`
+      if test $_count -gt $_max; then
+        _max=$_count
+        lt_cv_path_SED=$_sed
+      fi
+    done
+  done
+  rm -rf "$tmp"
+])
+if test "X$SED" != "X"; then
+  lt_cv_path_SED=$SED
+else
+  SED=$lt_cv_path_SED
+fi
+AC_MSG_RESULT([$SED])
+])
+
+# Add --enable-maintainer-mode option to configure.
+# From Jim Meyering
+
+# serial 1
+
+AC_DEFUN([AM_MAINTAINER_MODE],
+[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+  dnl maintainer-mode is disabled by default
+  AC_ARG_ENABLE(maintainer-mode,
+[  --enable-maintainer-mode enable make rules and dependencies not useful
+                          (and sometimes confusing) to the casual installer],
+      USE_MAINTAINER_MODE=$enableval,
+      USE_MAINTAINER_MODE=no)
+  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+  AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes])
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST(MAINT)dnl
+]
+)
+
+# iconv.m4 serial AM4 (gettext-0.11.3)
+dnl Copyright (C) 2000-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
+[
+  dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+
+  dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+  dnl accordingly.
+  AC_LIB_LINKFLAGS_BODY([iconv])
+])
+
+AC_DEFUN([AM_ICONV_LINK],
+[
+  dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
+  dnl those with the standalone portable GNU libiconv installed).
+
+  dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+  dnl accordingly.
+  AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
+
+  dnl Add $INCICONV to CPPFLAGS before performing the following checks,
+  dnl because if the user has installed libiconv and not disabled its use
+  dnl via --without-libiconv-prefix, he wants to use it. The first
+  dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed.
+  am_save_CPPFLAGS="$CPPFLAGS"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
+
+  AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [
+    am_cv_func_iconv="no, consider installing GNU libiconv"
+    am_cv_lib_iconv=no
+    AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+      [iconv_t cd = iconv_open("","");
+       iconv(cd,NULL,NULL,NULL,NULL);
+       iconv_close(cd);],
+      am_cv_func_iconv=yes)
+    if test "$am_cv_func_iconv" != yes; then
+      am_save_LIBS="$LIBS"
+      LIBS="$LIBS $LIBICONV"
+      AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+        [iconv_t cd = iconv_open("","");
+         iconv(cd,NULL,NULL,NULL,NULL);
+         iconv_close(cd);],
+        am_cv_lib_iconv=yes
+        am_cv_func_iconv=yes)
+      LIBS="$am_save_LIBS"
+    fi
+  ])
+  if test "$am_cv_func_iconv" = yes; then
+    AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
+  fi
+  if test "$am_cv_lib_iconv" = yes; then
+    AC_MSG_CHECKING([how to link with libiconv])
+    AC_MSG_RESULT([$LIBICONV])
+  else
+    dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
+    dnl either.
+    CPPFLAGS="$am_save_CPPFLAGS"
+    LIBICONV=
+    LTLIBICONV=
+  fi
+  AC_SUBST(LIBICONV)
+  AC_SUBST(LTLIBICONV)
+])
+
+AC_DEFUN([AM_ICONV],
+[
+  AM_ICONV_LINK
+  if test "$am_cv_func_iconv" = yes; then
+    AC_MSG_CHECKING([for iconv declaration])
+    AC_CACHE_VAL(am_cv_proto_iconv, [
+      AC_TRY_COMPILE([
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
+      am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
+    am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+    AC_MSG_RESULT([$]{ac_t:-
+         }[$]am_cv_proto_iconv)
+    AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
+      [Define as const if the declaration of iconv() needs const.])
+  fi
+])
+
+# lib-prefix.m4 serial 1 (gettext-0.11)
+dnl Copyright (C) 2001-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
+dnl to access previously installed libraries. The basic assumption is that
+dnl a user will want packages to use other packages he previously installed
+dnl with the same --prefix option.
+dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
+dnl libraries, but is otherwise very convenient.
+AC_DEFUN([AC_LIB_PREFIX],
+[
+  AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  dnl By default, look in $includedir and $libdir.
+  use_additional=yes
+  AC_LIB_WITH_FINAL_PREFIX([
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+  ])
+  AC_ARG_WITH([lib-prefix],
+[  --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
+  --without-lib-prefix    don't search for libraries in includedir and libdir],
+[
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+        AC_LIB_WITH_FINAL_PREFIX([
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+        ])
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/lib"
+      fi
+    fi
+])
+  if test $use_additional = yes; then
+    dnl Potentially add $additional_includedir to $CPPFLAGS.
+    dnl But don't add it
+    dnl   1. if it's the standard /usr/include,
+    dnl   2. if it's already present in $CPPFLAGS,
+    dnl   3. if it's /usr/local/include and we are using GCC on Linux,
+    dnl   4. if it doesn't exist as a directory.
+    if test "X$additional_includedir" != "X/usr/include"; then
+      haveit=
+      for x in $CPPFLAGS; do
+        AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+        if test "X$x" = "X-I$additional_includedir"; then
+          haveit=yes
+          break
+        fi
+      done
+      if test -z "$haveit"; then
+        if test "X$additional_includedir" = "X/usr/local/include"; then
+          if test -n "$GCC"; then
+            case $host_os in
+              linux*) haveit=yes;;
+            esac
+          fi
+        fi
+        if test -z "$haveit"; then
+          if test -d "$additional_includedir"; then
+            dnl Really add $additional_includedir to $CPPFLAGS.
+            CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
+          fi
+        fi
+      fi
+    fi
+    dnl Potentially add $additional_libdir to $LDFLAGS.
+    dnl But don't add it
+    dnl   1. if it's the standard /usr/lib,
+    dnl   2. if it's already present in $LDFLAGS,
+    dnl   3. if it's /usr/local/lib and we are using GCC on Linux,
+    dnl   4. if it doesn't exist as a directory.
+    if test "X$additional_libdir" != "X/usr/lib"; then
+      haveit=
+      for x in $LDFLAGS; do
+        AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+        if test "X$x" = "X-L$additional_libdir"; then
+          haveit=yes
+          break
+        fi
+      done
+      if test -z "$haveit"; then
+        if test "X$additional_libdir" = "X/usr/local/lib"; then
+          if test -n "$GCC"; then
+            case $host_os in
+              linux*) haveit=yes;;
+            esac
+          fi
+        fi
+        if test -z "$haveit"; then
+          if test -d "$additional_libdir"; then
+            dnl Really add $additional_libdir to $LDFLAGS.
+            LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
+          fi
+        fi
+      fi
+    fi
+  fi
+])
+
+dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
+dnl acl_final_exec_prefix, containing the values to which $prefix and
+dnl $exec_prefix will expand at the end of the configure script.
+AC_DEFUN([AC_LIB_PREPARE_PREFIX],
+[
+  dnl Unfortunately, prefix and exec_prefix get only finally determined
+  dnl at the end of configure.
+  if test "X$prefix" = "XNONE"; then
+    acl_final_prefix="$ac_default_prefix"
+  else
+    acl_final_prefix="$prefix"
+  fi
+  if test "X$exec_prefix" = "XNONE"; then
+    acl_final_exec_prefix='${prefix}'
+  else
+    acl_final_exec_prefix="$exec_prefix"
+  fi
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+  prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
+dnl variables prefix and exec_prefix bound to the values they will have
+dnl at the end of the configure script.
+AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
+[
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  $1
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+])
+
+# lib-link.m4 serial 3 (gettext-0.11.3)
+dnl Copyright (C) 2001-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
+dnl augments the CPPFLAGS variable.
+AC_DEFUN([AC_LIB_LINKFLAGS],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+  define([Name],[translit([$1],[./-], [___])])
+  define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+                               [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+  AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
+    AC_LIB_LINKFLAGS_BODY([$1], [$2])
+    ac_cv_lib[]Name[]_libs="$LIB[]NAME"
+    ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
+    ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
+  ])
+  LIB[]NAME="$ac_cv_lib[]Name[]_libs"
+  LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
+  INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+  AC_SUBST([LIB]NAME)
+  AC_SUBST([LTLIB]NAME)
+  dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
+  dnl results of this search when this library appears as a dependency.
+  HAVE_LIB[]NAME=yes
+  undefine([Name])
+  undefine([NAME])
+])
+
+dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode)
+dnl searches for libname and the libraries corresponding to explicit and
+dnl implicit dependencies, together with the specified include files and
+dnl the ability to compile and link the specified testcode. If found, it
+dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and
+dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and
+dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
+dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
+AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+  define([Name],[translit([$1],[./-], [___])])
+  define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+                               [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+
+  dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
+  dnl accordingly.
+  AC_LIB_LINKFLAGS_BODY([$1], [$2])
+
+  dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
+  dnl because if the user has installed lib[]Name and not disabled its use
+  dnl via --without-lib[]Name-prefix, he wants to use it.
+  ac_save_CPPFLAGS="$CPPFLAGS"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+
+  AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
+    ac_save_LIBS="$LIBS"
+    LIBS="$LIBS $LIB[]NAME"
+    AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no])
+    LIBS="$ac_save_LIBS"
+  ])
+  if test "$ac_cv_lib[]Name" = yes; then
+    HAVE_LIB[]NAME=yes
+    AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.])
+    AC_MSG_CHECKING([how to link with lib[]$1])
+    AC_MSG_RESULT([$LIB[]NAME])
+  else
+    HAVE_LIB[]NAME=no
+    dnl If $LIB[]NAME didn't lead to a usable library, we don't need
+    dnl $INC[]NAME either.
+    CPPFLAGS="$ac_save_CPPFLAGS"
+    LIB[]NAME=
+    LTLIB[]NAME=
+  fi
+  AC_SUBST([HAVE_LIB]NAME)
+  AC_SUBST([LIB]NAME)
+  AC_SUBST([LTLIB]NAME)
+  undefine([Name])
+  undefine([NAME])
+])
+
+dnl Determine the platform dependent parameters needed to use rpath:
+dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator,
+dnl hardcode_direct, hardcode_minus_L,
+dnl sys_lib_search_path_spec, sys_lib_dlsearch_path_spec.
+AC_DEFUN([AC_LIB_RPATH],
+[
+  AC_REQUIRE([AC_PROG_CC])                dnl we use $CC, $GCC, $LDFLAGS
+  AC_REQUIRE([AC_LIB_PROG_LD])            dnl we use $LD, $with_gnu_ld
+  AC_REQUIRE([AC_CANONICAL_HOST])         dnl we use $host
+  AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
+  AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [
+    CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+    ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+    . ./conftest.sh
+    rm -f ./conftest.sh
+    acl_cv_rpath=done
+  ])
+  wl="$acl_cv_wl"
+  libext="$acl_cv_libext"
+  shlibext="$acl_cv_shlibext"
+  hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+  hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+  hardcode_direct="$acl_cv_hardcode_direct"
+  hardcode_minus_L="$acl_cv_hardcode_minus_L"
+  sys_lib_search_path_spec="$acl_cv_sys_lib_search_path_spec"
+  sys_lib_dlsearch_path_spec="$acl_cv_sys_lib_dlsearch_path_spec"
+  dnl Determine whether the user wants rpath handling at all.
+  AC_ARG_ENABLE(rpath,
+    [  --disable-rpath         do not hardcode runtime library paths],
+    :, enable_rpath=yes)
+])
+
+dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
+AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
+[
+  define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+                               [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+  dnl By default, look in $includedir and $libdir.
+  use_additional=yes
+  AC_LIB_WITH_FINAL_PREFIX([
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+  ])
+  AC_ARG_WITH([lib$1-prefix],
+[  --with-lib$1-prefix[=DIR]  search for lib$1 in DIR/include and DIR/lib
+  --without-lib$1-prefix     don't search for lib$1 in includedir and libdir],
+[
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+        AC_LIB_WITH_FINAL_PREFIX([
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+        ])
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/lib"
+      fi
+    fi
+])
+  dnl Search the library and its dependencies in $additional_libdir and
+  dnl $LDFLAGS. Using breadth-first-seach.
+  LIB[]NAME=
+  LTLIB[]NAME=
+  INC[]NAME=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='$1 $2'
+  while test -n "$names_next_round"; do
+    names_this_round="$names_next_round"
+    names_next_round=
+    for name in $names_this_round; do
+      already_handled=
+      for n in $names_already_handled; do
+        if test "$n" = "$name"; then
+          already_handled=yes
+          break
+        fi
+      done
+      if test -z "$already_handled"; then
+        names_already_handled="$names_already_handled $name"
+        dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
+        dnl or AC_LIB_HAVE_LINKFLAGS call.
+        uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+        eval value=\"\$HAVE_LIB$uppername\"
+        if test -n "$value"; then
+          if test "$value" = yes; then
+            eval value=\"\$LIB$uppername\"
+            test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
+          else
+            dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
+            dnl that this library doesn't exist. So just drop it.
+            :
+          fi
+        else
+          dnl Search the library lib$name in $additional_libdir and $LDFLAGS
+          dnl and the already constructed $LIBNAME/$LTLIBNAME.
+          found_dir=
+          found_la=
+          found_so=
+          found_a=
+          if test $use_additional = yes; then
+            if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then
+              found_dir="$additional_libdir"
+              found_so="$additional_libdir/lib$name.$shlibext"
+              if test -f "$additional_libdir/lib$name.la"; then
+                found_la="$additional_libdir/lib$name.la"
+              fi
+            else
+              if test -f "$additional_libdir/lib$name.$libext"; then
+                found_dir="$additional_libdir"
+                found_a="$additional_libdir/lib$name.$libext"
+                if test -f "$additional_libdir/lib$name.la"; then
+                  found_la="$additional_libdir/lib$name.la"
+                fi
+              fi
+            fi
+          fi
+          if test "X$found_dir" = "X"; then
+            for x in $LDFLAGS $LTLIB[]NAME; do
+              AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+              case "$x" in
+                -L*)
+                  dir=`echo "X$x" | sed -e 's/^X-L//'`
+                  if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then
+                    found_dir="$dir"
+                    found_so="$dir/lib$name.$shlibext"
+                    if test -f "$dir/lib$name.la"; then
+                      found_la="$dir/lib$name.la"
+                    fi
+                  else
+                    if test -f "$dir/lib$name.$libext"; then
+                      found_dir="$dir"
+                      found_a="$dir/lib$name.$libext"
+                      if test -f "$dir/lib$name.la"; then
+                        found_la="$dir/lib$name.la"
+                      fi
+                    fi
+                  fi
+                  ;;
+              esac
+              if test "X$found_dir" != "X"; then
+                break
+              fi
+            done
+          fi
+          if test "X$found_dir" != "X"; then
+            dnl Found the library.
+            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
+            if test "X$found_so" != "X"; then
+              dnl Linking with a shared library. We attempt to hardcode its
+              dnl directory into the executable's runpath, unless it's the
+              dnl standard /usr/lib.
+              if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then
+                dnl No hardcoding is needed.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+              else
+                dnl Use an explicit option to hardcode DIR into the resulting
+                dnl binary.
+                dnl Potentially add DIR to ltrpathdirs.
+                dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+                haveit=
+                for x in $ltrpathdirs; do
+                  if test "X$x" = "X$found_dir"; then
+                    haveit=yes
+                    break
+                  fi
+                done
+                if test -z "$haveit"; then
+                  ltrpathdirs="$ltrpathdirs $found_dir"
+                fi
+                dnl The hardcoding into $LIBNAME is system dependent.
+                if test "$hardcode_direct" = yes; then
+                  dnl Using DIR/libNAME.so during linking hardcodes DIR into the
+                  dnl resulting binary.
+                  LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                else
+                  if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+                    dnl Use an explicit option to hardcode DIR into the resulting
+                    dnl binary.
+                    LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                    dnl Potentially add DIR to rpathdirs.
+                    dnl The rpathdirs will be appended to $LIBNAME at the end.
+                    haveit=
+                    for x in $rpathdirs; do
+                      if test "X$x" = "X$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      rpathdirs="$rpathdirs $found_dir"
+                    fi
+                  else
+                    dnl Rely on "-L$found_dir".
+                    dnl But don't add it if it's already contained in the LDFLAGS
+                    dnl or the already constructed $LIBNAME
+                    haveit=
+                    for x in $LDFLAGS $LIB[]NAME; do
+                      AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                      if test "X$x" = "X-L$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
+                    fi
+                    if test "$hardcode_minus_L" != no; then
+                      dnl FIXME: Not sure whether we should use
+                      dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+                      dnl here.
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                    else
+                      dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH
+                      dnl here, because this doesn't fit in flags passed to the
+                      dnl compiler. So give up. No hardcoding. This affects only
+                      dnl very old systems.
+                      dnl FIXME: Not sure whether we should use
+                      dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+                      dnl here.
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                dnl Linking with a static library.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
+              else
+                dnl We shouldn't come here, but anyway it's good to have a
+                dnl fallback.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
+              fi
+            fi
+            dnl Assume the include files are nearby.
+            additional_includedir=
+            case "$found_dir" in
+              */lib | */lib/)
+                basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
+                additional_includedir="$basedir/include"
+                ;;
+            esac
+            if test "X$additional_includedir" != "X"; then
+              dnl Potentially add $additional_includedir to $INCNAME.
+              dnl But don't add it
+              dnl   1. if it's the standard /usr/include,
+              dnl   2. if it's /usr/local/include and we are using GCC on Linux,
+              dnl   3. if it's already present in $CPPFLAGS or the already
+              dnl      constructed $INCNAME,
+              dnl   4. if it doesn't exist as a directory.
+              if test "X$additional_includedir" != "X/usr/include"; then
+                haveit=
+                if test "X$additional_includedir" = "X/usr/local/include"; then
+                  if test -n "$GCC"; then
+                    case $host_os in
+                      linux*) haveit=yes;;
+                    esac
+                  fi
+                fi
+                if test -z "$haveit"; then
+                  for x in $CPPFLAGS $INC[]NAME; do
+                    AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                    if test "X$x" = "X-I$additional_includedir"; then
+                      haveit=yes
+                      break
+                    fi
+                  done
+                  if test -z "$haveit"; then
+                    if test -d "$additional_includedir"; then
+                      dnl Really add $additional_includedir to $INCNAME.
+                      INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
+                    fi
+                  fi
+                fi
+              fi
+            fi
+            dnl Look for dependencies.
+            if test -n "$found_la"; then
+              dnl Read the .la file. It defines the variables
+              dnl dlname, library_names, old_library, dependency_libs, current,
+              dnl age, revision, installed, dlopen, dlpreopen, libdir.
+              save_libdir="$libdir"
+              case "$found_la" in
+                */* | *\\*) . "$found_la" ;;
+                *) . "./$found_la" ;;
+              esac
+              libdir="$save_libdir"
+              dnl We use only dependency_libs.
+              for dep in $dependency_libs; do
+                case "$dep" in
+                  -L*)
+                    additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+                    dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
+                    dnl But don't add it
+                    dnl   1. if it's the standard /usr/lib,
+                    dnl   2. if it's /usr/local/lib and we are using GCC on Linux,
+                    dnl   3. if it's already present in $LDFLAGS or the already
+                    dnl      constructed $LIBNAME,
+                    dnl   4. if it doesn't exist as a directory.
+                    if test "X$additional_libdir" != "X/usr/lib"; then
+                      haveit=
+                      if test "X$additional_libdir" = "X/usr/local/lib"; then
+                        if test -n "$GCC"; then
+                          case $host_os in
+                            linux*) haveit=yes;;
+                          esac
+                        fi
+                      fi
+                      if test -z "$haveit"; then
+                        haveit=
+                        for x in $LDFLAGS $LIB[]NAME; do
+                          AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                            dnl Really add $additional_libdir to $LIBNAME.
+                            LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIB[]NAME; do
+                          AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                            dnl Really add $additional_libdir to $LTLIBNAME.
+                            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
+                          fi
+                        fi
+                      fi
+                    fi
+                    ;;
+                  -R*)
+                    dir=`echo "X$dep" | sed -e 's/^X-R//'`
+                    if test "$enable_rpath" != no; then
+                      dnl Potentially add DIR to rpathdirs.
+                      dnl The rpathdirs will be appended to $LIBNAME at the end.
+                      haveit=
+                      for x in $rpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        rpathdirs="$rpathdirs $dir"
+                      fi
+                      dnl Potentially add DIR to ltrpathdirs.
+                      dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+                      haveit=
+                      for x in $ltrpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        ltrpathdirs="$ltrpathdirs $dir"
+                      fi
+                    fi
+                    ;;
+                  -l*)
+                    dnl Handle this in the next round.
+                    names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+                    ;;
+                  *.la)
+                    dnl Handle this in the next round. Throw away the .la's
+                    dnl directory; it is already contained in a preceding -L
+                    dnl option.
+                    names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+                    ;;
+                  *)
+                    dnl Most likely an immediate library name.
+                    LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
+                    LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+            dnl Didn't find the library; assume it is in the system directories
+            dnl known to the linker and runtime loader. (All the system
+            dnl directories known to the linker should also be known to the
+            dnl runtime loader, otherwise the system is severely misconfigured.)
+            LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
+          fi
+        fi
+      fi
+    done
+  done
+  if test "X$rpathdirs" != "X"; then
+    if test -n "$hardcode_libdir_separator"; then
+      dnl Weird platform: only the last -rpath option counts, the user must
+      dnl pass all path elements in one option. We can arrange that for a
+      dnl single library, but not when more than one $LIBNAMEs are used.
+      alldirs=
+      for found_dir in $rpathdirs; do
+        alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
+      done
+      dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl.
+      acl_save_libdir="$libdir"
+      libdir="$alldirs"
+      eval flag=\"$hardcode_libdir_flag_spec\"
+      libdir="$acl_save_libdir"
+      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+    else
+      dnl The -rpath options are cumulative.
+      for found_dir in $rpathdirs; do
+        acl_save_libdir="$libdir"
+        libdir="$found_dir"
+        eval flag=\"$hardcode_libdir_flag_spec\"
+        libdir="$acl_save_libdir"
+        LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+    dnl When using libtool, the option that works for both libraries and
+    dnl executables is -R. The -R options are cumulative.
+    for found_dir in $ltrpathdirs; do
+      LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
+    done
+  fi
+])
+
+dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
+dnl unless already present in VAR.
+dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
+dnl contains two or three consecutive elements that belong together.
+AC_DEFUN([AC_LIB_APPENDTOVAR],
+[
+  for element in [$2]; do
+    haveit=
+    for x in $[$1]; do
+      AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+      if test "X$x" = "X$element"; then
+        haveit=yes
+        break
+      fi
+    done
+    if test -z "$haveit"; then
+      [$1]="${[$1]}${[$1]:+ }$element"
+    fi
+  done
+])
+
+# lib-ld.m4 serial 1 (gettext-0.11)
+dnl Copyright (C) 1996-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl Subroutines of libtool.m4,
+dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
+dnl with libtool.m4.
+
+dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
+AC_DEFUN([AC_LIB_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  acl_cv_prog_gnu_ld=yes
+else
+  acl_cv_prog_gnu_ld=no
+fi])
+with_gnu_ld=$acl_cv_prog_gnu_ld
+])
+
+dnl From libtool-1.4. Sets the variable LD.
+AC_DEFUN([AC_LIB_PROG_LD],
+[AC_ARG_WITH(gnu-ld,
+[  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by GCC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]* | [A-Za-z]:[\\/]*)]
+      [re_direlt='/[^/][^/]*/\.\./']
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(acl_cv_path_LD,
+[if test -z "$LD"; then
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      acl_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$acl_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+	test "$with_gnu_ld" != no && break
+      else
+	test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_LIB_PROG_LD_GNU
+])
+
Index: /indexers/branches/3.03a/packages/unac/config.h.in
===================================================================
--- /indexers/branches/3.03a/packages/unac/config.h.in	(revision 14757)
+++ /indexers/branches/3.03a/packages/unac/config.h.in	(revision 14757)
@@ -0,0 +1,29 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the `iconv_open' function. */
+#undef HAVE_ICONV_OPEN
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
Index: /indexers/branches/3.03a/packages/unac/configure
===================================================================
--- /indexers/branches/3.03a/packages/unac/configure	(revision 14757)
+++ /indexers/branches/3.03a/packages/unac/configure	(revision 14757)
@@ -0,0 +1,9667 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Find the correct PATH separator.  Usually this is `:', but
+# DJGPP uses `;' like DOS.
+if test "X${PATH_SEPARATOR+set}" != Xset; then
+  UNAME=${UNAME-`uname 2>/dev/null`}
+  case X$UNAME in
+    *-DOS) lt_cv_sys_path_separator=';' ;;
+    *)     lt_cv_sys_path_separator=':' ;;
+  esac
+  PATH_SEPARATOR=$lt_cv_sys_path_separator
+fi
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','`
+  ;;
+esac
+
+echo=${ECHO-echo}
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+
+EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+  for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+       echo_test_string="`eval $cmd`" &&
+       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+    then
+      break
+    fi
+  done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+   test "X$echo_testing_string" = "X$echo_test_string"; then
+  :
+else
+  # The Solaris, AIX, and Digital Unix default echo programs unquote
+  # backslashes.  This makes it impossible to quote backslashes using
+  #   echo "$something" | sed 's/\\/\\\\/g'
+  #
+  # So, first we look for a working echo in the user's PATH.
+
+  IFS="${IFS= 	}"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for dir in $PATH /usr/ucb; do
+    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      echo="$dir/echo"
+      break
+    fi
+  done
+  IFS="$save_ifs"
+
+  if test "X$echo" = Xecho; then
+    # We didn't find a better echo, so look for alternatives.
+    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      # This shell has a builtin print -r that does the trick.
+      echo='print -r'
+    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+	 test "X$CONFIG_SHELL" != X/bin/ksh; then
+      # If we have ksh, try running configure again with it.
+      ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+      export ORIGINAL_CONFIG_SHELL
+      CONFIG_SHELL=/bin/ksh
+      export CONFIG_SHELL
+      exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+    else
+      # Try using printf.
+      echo='printf %s\n'
+      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+	 echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+	 test "X$echo_testing_string" = "X$echo_test_string"; then
+	# Cool, printf works
+	:
+      elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+	   test "X$echo_testing_string" = 'X\t' &&
+	   echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	   test "X$echo_testing_string" = "X$echo_test_string"; then
+	CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+	export CONFIG_SHELL
+	SHELL="$CONFIG_SHELL"
+	export SHELL
+	echo="$CONFIG_SHELL $0 --fallback-echo"
+      elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+	   test "X$echo_testing_string" = 'X\t' &&
+	   echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	   test "X$echo_testing_string" = "X$echo_test_string"; then
+	echo="$CONFIG_SHELL $0 --fallback-echo"
+      else
+	# maybe with a smaller string...
+	prev=:
+
+	for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+	  if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+	  then
+	    break
+	  fi
+	  prev="$cmd"
+	done
+
+	if test "$prev" != 'sed 50q "$0"'; then
+	  echo_test_string=`eval $prev`
+	  export echo_test_string
+	  exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+	else
+	  # Oops.  We lost completely, so just stick with echo.
+	  echo=echo
+	fi
+      fi
+    fi
+  fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+   ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="config.h.in"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS VERSION SET_MAKE UNICODE_VERSION CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP build build_cpu build_vendor build_os host host_cpu host_vendor host_os LN_S ECHO RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP LIBTOOL PERL SH MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBICONV LTLIBICONV LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+	      localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$0" : 'X\(//\)[^/]' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+			  [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+			  [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-shared=PKGS  build shared libraries default=yes
+  --enable-static=PKGS  build static libraries default=yes
+  --enable-fast-install=PKGS  optimize for fast installation default=yes
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --enable-maintainer-mode enable make rules and dependencies not useful
+                          (and sometimes confusing) to the casual installer
+  --disable-rpath         do not hardcode runtime library paths
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-gnu-ld           assume the C compiler uses GNU ld default=no
+  --with-pic              try to use only PIC/non-PIC objects default=use both
+  --with-libiconv-prefix=DIR  search for libiconv in DIR/include and DIR/lib
+  --without-libiconv-prefix     don't search for libiconv in includedir and libdir
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+	   test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+	"s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=$`echo $ac_var`
+	echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+	       sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+	ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+VERSION=`cat .version`
+
+
+
+          ac_config_headers="$ac_config_headers config.h"
+
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+all:
+	@echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  SET_MAKE=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+UNICODE_VERSION=3.2.0
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+	;;
+    conftest.$ac_ext )
+	# This is the source file.
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	# FIXME: I believe we export ac_cv_exeext for Libtool,
+	# but it would be cool to find out if it's true.  Does anybody
+	# maintain Libtool? --akim.
+	export ac_cv_exeext
+	break;;
+    * )
+	break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  export ac_cv_exeext
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX 10.20 and later	-Ae
+# HP-UX older versions	-Aa -D_HPUX_SOURCE
+# SVR4			-Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+
+echo "$as_me:$LINENO: checking for AIX" >&5
+echo $ECHO_N "checking for AIX... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef _AIX
+  yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+cat >>confdefs.h <<\_ACEOF
+#define _ALL_SOURCE 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+
+echo "$as_me:$LINENO: checking maximum warning verbosity option" >&5
+echo $ECHO_N "checking maximum warning verbosity option... $ECHO_C" >&6
+if test -n "$CXX"
+then
+  if test "$GXX" = "yes"
+  then
+    ac_compile_warnings_opt='-Wall -Woverloaded-virtual'
+  fi
+  CXXFLAGS="$CXXFLAGS $ac_compile_warnings_opt"
+  ac_compile_warnings_msg="$ac_compile_warnings_opt for C++"
+fi
+
+if test -n "$CC"
+then
+  if test "$GCC" = "yes"
+  then
+    ac_compile_warnings_opt='-Wall -Wmissing-declarations -Wmissing-prototypes'
+  fi
+  CFLAGS="$CFLAGS $ac_compile_warnings_opt"
+  ac_compile_warnings_msg="$ac_compile_warnings_msg $ac_compile_warnings_opt for C"
+fi
+echo "$as_me:$LINENO: result: $ac_compile_warnings_msg" >&5
+echo "${ECHO_T}$ac_compile_warnings_msg" >&6
+unset ac_compile_warnings_msg
+unset ac_compile_warnings_opt
+
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+  enableval="$enable_shared"
+  p=${PACKAGE-default}
+case $enableval in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_shared=yes
+fi;
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+  enableval="$enable_static"
+  p=${PACKAGE-default}
+case $enableval in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_static=yes
+fi;
+# Check whether --enable-fast-install or --disable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+  enableval="$enable_fast_install"
+  p=${PACKAGE-default}
+case $enableval in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_fast_install=yes
+fi;
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Make sure we can run config.sub.
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+  ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
+build=$ac_cv_build
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+  ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
+host=$ac_cv_host
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+# Find the correct PATH separator.  Usually this is `:', but
+# DJGPP uses `;' like DOS.
+if test "X${PATH_SEPARATOR+set}" != Xset; then
+  UNAME=${UNAME-`uname 2>/dev/null`}
+  case X$UNAME in
+    *-DOS) lt_cv_sys_path_separator=';' ;;
+    *)     lt_cv_sys_path_separator=':' ;;
+  esac
+  PATH_SEPARATOR=$lt_cv_sys_path_separator
+fi
+
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval="$with_gnu_ld"
+  test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi;
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  echo "$as_me:$LINENO: checking for ld used by GCC" >&5
+echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+else
+  echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$LD"; then
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+	test "$with_gnu_ld" != no && break
+      else
+	test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  lt_cv_prog_gnu_ld=yes
+else
+  lt_cv_prog_gnu_ld=no
+fi
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
+echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6
+if test "${lt_cv_ld_reload_flag+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
+echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6
+reload_flag=$lt_cv_ld_reload_flag
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
+echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6
+if test "${lt_cv_path_NM+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    tmp_nm=$ac_dir/${ac_tool_prefix}nm
+    if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      # Tru64's nm complains that /dev/null is an invalid object file
+      if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then
+	lt_cv_path_NM="$tmp_nm -B"
+	break
+      elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+	lt_cv_path_NM="$tmp_nm -p"
+	break
+      else
+	lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi
+fi
+
+NM="$lt_cv_path_NM"
+echo "$as_me:$LINENO: result: $NM" >&5
+echo "${ECHO_T}$NM" >&6
+
+echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
+echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6
+if test "${lt_cv_path_SED+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_executable_p="test -f"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+        _sed_list="$_sed_list $as_dir/$ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+
+  # Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+: ${TMPDIR=/tmp}
+{
+  tmp=`(umask 077 && mktemp -d -q "$TMPDIR/sedXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=$TMPDIR/sed$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in $TMPDIR" >&2
+   { (exit 1); exit 1; }
+}
+  _max=0
+  _count=0
+  # Add /usr/xpg4/bin/sed as it is typically found on Solaris
+  # along with /bin/sed that truncates output.
+  for _sed in $_sed_list /usr/xpg4/bin/sed; do
+    test ! -f ${_sed} && break
+    cat /dev/null > "$tmp/sed.in"
+    _count=0
+    echo ${ECHO_N-$ac_n} "0123456789${ECHO_C-$ac_c}" >"$tmp/sed.in"
+    # Check for GNU sed and select it if it is found.
+    if "${_sed}" --version 2>&1 < /dev/null | egrep '(GNU)' > /dev/null; then
+      lt_cv_path_SED=${_sed}
+      break;
+    fi
+    while true; do
+      cat "$tmp/sed.in" "$tmp/sed.in" >"$tmp/sed.tmp"
+      mv "$tmp/sed.tmp" "$tmp/sed.in"
+      cp "$tmp/sed.in" "$tmp/sed.nl"
+      echo >>"$tmp/sed.nl"
+      ${_sed} -e 's/a$//' < "$tmp/sed.nl" >"$tmp/sed.out" || break
+      cmp -s "$tmp/sed.out" "$tmp/sed.nl" || break
+      # 40000 chars as input seems more than enough
+      test $_count -gt 10 && break
+      _count=`expr $_count + 1`
+      if test $_count -gt $_max; then
+        _max=$_count
+        lt_cv_path_SED=$_sed
+      fi
+    done
+  done
+  rm -rf "$tmp"
+
+fi
+
+if test "X$SED" != "X"; then
+  lt_cv_path_SED=$SED
+else
+  SED=$lt_cv_path_SED
+fi
+echo "$as_me:$LINENO: result: $SED" >&5
+echo "${ECHO_T}$SED" >&6
+
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5
+echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6
+if test "${lt_cv_deplibs_check_method+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given egrep regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi4*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin* | mingw* | pw32*)
+  lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  case "$host_os" in
+  rhapsody* | darwin1.[012])
+    lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1`
+    ;;
+  *) # Darwin 1.3 on
+    lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib'
+    ;;
+  esac
+  ;;
+
+freebsd*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20*|hpux11*)
+  lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libc.sl
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+  irix5* | nonstopux*)
+    # this will be overridden with pass_all, but let us keep it just in case
+    lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+    ;;
+  *)
+    case $LD in
+    *-32|*"-32 ") libmagic=32-bit;;
+    *-n32|*"-n32 ") libmagic=N32;;
+    *-64|*"-64 ") libmagic=64-bit;;
+    *) libmagic=never-match;;
+    esac
+    # this will be overridden with pass_all, but let us keep it just in case
+    lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1"
+    ;;
+  esac
+  lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+  case $host_cpu in
+  alpha* | hppa* | i*86 | mips | mipsel | powerpc* | sparc* | ia64*)
+    lt_cv_deplibs_check_method=pass_all ;;
+  *)
+    # glibc up to 2.1.1 does not perform some relocations on ARM
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;;
+  esac
+  lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+openbsd*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
+  else
+    lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  # this will be overridden with pass_all, but let us keep it just in case
+  lt_cv_deplibs_check_method='file_magic COFF format alpha shared library'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sco3.2v5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  lt_cv_file_magic_test_file=/lib/libc.so
+  ;;
+
+sysv5uw[78]* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+esac
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
+echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+
+
+
+
+
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo "$as_me:$LINENO: checking command to parse $NM output" >&5
+echo $ECHO_N "checking command to parse $NM output... $ECHO_C" >&6
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*) # Its linker distinguishes data from code symbols
+  lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+  lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+solaris* | sysv5*)
+  symcode='[BDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $host_os in
+mingw*)
+  opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+  symcode='[ABCDGISTW]'
+fi
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Write the raw and C identifiers.
+lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ 	]\($symcode$symcode*\)[ 	][ 	]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+  rm -f conftest*
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5
+  (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+	if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext'
+
+	  cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+	  sed "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext
+	  cat <<\EOF >> conftest.$ac_ext
+  {0, (lt_ptr) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  save_LIBS="$LIBS"
+	  save_CFLAGS="$CFLAGS"
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$no_builtin_flag"
+	  if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest; then
+	    pipe_works=yes
+	  fi
+	  LIBS="$save_LIBS"
+	  CFLAGS="$save_CFLAGS"
+	else
+	  echo "cannot find nm_test_func in $nlist" >&5
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -f conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+global_symbol_pipe="$lt_cv_sys_global_symbol_pipe"
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  global_symbol_to_cdecl=
+  global_symbol_to_c_name_address=
+else
+  global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl"
+  global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address"
+fi
+if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address";
+then
+  echo "$as_me:$LINENO: result: failed" >&5
+echo "${ECHO_T}failed" >&6
+else
+  echo "$as_me:$LINENO: result: ok" >&5
+echo "${ECHO_T}ok" >&6
+fi
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in dlfcn.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
+echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $MAGIC_CMD in
+  /*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+  ?:/*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
+  ;;
+  *)
+  ac_save_MAGIC_CMD="$MAGIC_CMD"
+  IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="/usr/bin:$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    egrep "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  MAGIC_CMD="$ac_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    echo "$as_me:$LINENO: checking for file" >&5
+echo $ECHO_N "checking for file... $ECHO_C" >&6
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $MAGIC_CMD in
+  /*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+  ?:/*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
+  ;;
+  *)
+  ac_save_MAGIC_CMD="$MAGIC_CMD"
+  IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="/usr/bin:$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    egrep "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  MAGIC_CMD="$ac_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  STRIP=$ac_ct_STRIP
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+
+enable_dlopen=no
+enable_win32_dll=no
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+  enableval="$enable_libtool_lock"
+
+fi;
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line 4244 "configure"' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6
+if test "${lt_cv_cc_needs_belf+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  lt_cv_cc_needs_belf=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+lt_cv_cc_needs_belf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+need_locks="$enable_libtool_lock"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+if test x"$host" != x"$build"; then
+  ac_tool_prefix=${host_alias}-
+else
+  ac_tool_prefix=
+fi
+
+# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+case $host_os in
+linux-gnu*) ;;
+linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+esac
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
+    ;;
+  *)
+    old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+# Allow CC to be a program name with arguments.
+set dummy $CC
+compiler="$2"
+
+echo "$as_me:$LINENO: checking for objdir" >&5
+echo $ECHO_N "checking for objdir... $ECHO_C" >&6
+rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+echo "$as_me:$LINENO: result: $objdir" >&5
+echo "${ECHO_T}$objdir" >&6
+
+
+
+# Check whether --with-pic or --without-pic was given.
+if test "${with_pic+set}" = set; then
+  withval="$with_pic"
+  pic_mode="$withval"
+else
+  pic_mode=default
+fi;
+test -z "$pic_mode" && pic_mode=default
+
+# We assume here that the value for lt_cv_prog_cc_pic will not be cached
+# in isolation, and that seeing it set (from the cache) indicates that
+# the associated values are set (in the cache) correctly too.
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+if test "${lt_cv_prog_cc_pic+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+   lt_cv_prog_cc_pic=
+  lt_cv_prog_cc_shlib=
+  lt_cv_prog_cc_wl=
+  lt_cv_prog_cc_static=
+  lt_cv_prog_cc_no_builtin=
+  lt_cv_prog_cc_can_build_shared=$can_build_shared
+
+  if test "$GCC" = yes; then
+    lt_cv_prog_cc_wl='-Wl,'
+    lt_cv_prog_cc_static='-static'
+
+    case $host_os in
+    aix*)
+      # Below there is a dirty hack to force normal static linking with -ldl
+      # The problem is because libdl dynamically linked with both libc and
+      # libC (AIX C++ library), which obviously doesn't included in libraries
+      # list by gcc. This cause undefined symbols with -static flags.
+      # This hack allows C programs to be linked with "-static -ldl", but
+      # not sure about C++ programs.
+      lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC"
+      ;;
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4'
+      ;;
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_cv_prog_cc_pic='-fno-common'
+      ;;
+    cygwin* | mingw* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_cv_prog_cc_pic='-DDLL_EXPORT'
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	 lt_cv_prog_cc_pic=-Kconform_pic
+      fi
+      ;;
+    *)
+      lt_cv_prog_cc_pic='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for PIC flags for the system compiler.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      lt_cv_prog_cc_wl='-Wl,'
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_cv_prog_cc_static='-Bstatic'
+      else
+	lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      # Is there a better lt_cv_prog_cc_static that works with the bundled CC?
+      lt_cv_prog_cc_wl='-Wl,'
+      lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive"
+      lt_cv_prog_cc_pic='+Z'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_cv_prog_cc_wl='-Wl,'
+      lt_cv_prog_cc_static='-non_shared'
+      # PIC (with -KPIC) is the default.
+      ;;
+
+    cygwin* | mingw* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_cv_prog_cc_pic='-DDLL_EXPORT'
+      ;;
+
+    newsos6)
+      lt_cv_prog_cc_pic='-KPIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      # All OSF/1 code is PIC.
+      lt_cv_prog_cc_wl='-Wl,'
+      lt_cv_prog_cc_static='-non_shared'
+      ;;
+
+    sco3.2v5*)
+      lt_cv_prog_cc_pic='-Kpic'
+      lt_cv_prog_cc_static='-dn'
+      lt_cv_prog_cc_shlib='-belf'
+      ;;
+
+    solaris*)
+      lt_cv_prog_cc_pic='-KPIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      lt_cv_prog_cc_wl='-Wl,'
+      ;;
+
+    sunos4*)
+      lt_cv_prog_cc_pic='-PIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      lt_cv_prog_cc_wl='-Qoption ld '
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+      lt_cv_prog_cc_pic='-KPIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      lt_cv_prog_cc_wl='-Wl,'
+      ;;
+
+    uts4*)
+      lt_cv_prog_cc_pic='-pic'
+      lt_cv_prog_cc_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	lt_cv_prog_cc_pic='-Kconform_pic'
+	lt_cv_prog_cc_static='-Bstatic'
+      fi
+      ;;
+
+    *)
+      lt_cv_prog_cc_can_build_shared=no
+      ;;
+    esac
+  fi
+
+fi
+
+if test -z "$lt_cv_prog_cc_pic"; then
+  echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+else
+  echo "$as_me:$LINENO: result: $lt_cv_prog_cc_pic" >&5
+echo "${ECHO_T}$lt_cv_prog_cc_pic" >&6
+
+  # Check to make sure the pic_flag actually works.
+  echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_cv_prog_cc_pic works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_cv_prog_cc_pic works... $ECHO_C" >&6
+  if test "${lt_cv_prog_cc_pic_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      save_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+        case $host_os in
+      hpux9* | hpux10* | hpux11*)
+	# On HP-UX, both CC and GCC only warn that PIC is supported... then
+	# they create non-PIC objects.  So, if there were any warnings, we
+	# assume that PIC is not supported.
+	if test -s conftest.err; then
+	  lt_cv_prog_cc_pic_works=no
+	else
+	  lt_cv_prog_cc_pic_works=yes
+	fi
+	;;
+      *)
+	lt_cv_prog_cc_pic_works=yes
+	;;
+      esac
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+      lt_cv_prog_cc_pic_works=no
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+    CFLAGS="$save_CFLAGS"
+
+fi
+
+
+  if test "X$lt_cv_prog_cc_pic_works" = Xno; then
+    lt_cv_prog_cc_pic=
+    lt_cv_prog_cc_can_build_shared=no
+  else
+    lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic"
+  fi
+
+  echo "$as_me:$LINENO: result: $lt_cv_prog_cc_pic_works" >&5
+echo "${ECHO_T}$lt_cv_prog_cc_pic_works" >&6
+fi
+
+# Check for any special shared library compilation flags.
+if test -n "$lt_cv_prog_cc_shlib"; then
+  { echo "$as_me:$LINENO: WARNING: \`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries" >&5
+echo "$as_me: WARNING: \`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries" >&2;}
+  if echo "$old_CC $old_CFLAGS " | egrep -e "[ 	]$lt_cv_prog_cc_shlib[ 	]" >/dev/null; then :
+  else
+   { echo "$as_me:$LINENO: WARNING: add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&5
+echo "$as_me: WARNING: add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&2;}
+    lt_cv_prog_cc_can_build_shared=no
+  fi
+fi
+
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_cv_prog_cc_static works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_cv_prog_cc_static works... $ECHO_C" >&6
+if test "${lt_cv_prog_cc_static_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+    lt_cv_prog_cc_static_works=no
+  save_LDFLAGS="$LDFLAGS"
+  LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  lt_cv_prog_cc_static_works=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  LDFLAGS="$save_LDFLAGS"
+
+fi
+
+
+# Belt *and* braces to stop my trousers falling down:
+test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static=
+echo "$as_me:$LINENO: result: $lt_cv_prog_cc_static_works" >&5
+echo "${ECHO_T}$lt_cv_prog_cc_static_works" >&6
+
+pic_flag="$lt_cv_prog_cc_pic"
+special_shlib_compile_flags="$lt_cv_prog_cc_shlib"
+wl="$lt_cv_prog_cc_wl"
+link_static_flag="$lt_cv_prog_cc_static"
+no_builtin_flag="$lt_cv_prog_cc_no_builtin"
+can_build_shared="$lt_cv_prog_cc_can_build_shared"
+
+
+# Check to see if options -o and -c are simultaneously supported by compiler
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_compiler_c_o+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+$rm -r conftest 2>/dev/null
+mkdir conftest
+cd conftest
+echo "int some_variable = 0;" > conftest.$ac_ext
+mkdir out
+# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
+# that will create temporary files in the current directory regardless of
+# the output directory.  Thus, making CWD read-only will cause this test
+# to fail, enabling locking or at least warning the user not to do parallel
+# builds.
+chmod -w .
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+compiler_c_o=no
+if { (eval echo configure:4802: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+  # The compiler can only warn and ignore the option if not recognized
+  # So say no if there are warnings
+  if test -s out/conftest.err; then
+    lt_cv_compiler_c_o=no
+  else
+    lt_cv_compiler_c_o=yes
+  fi
+else
+  # Append any errors to the config.log.
+  cat out/conftest.err 1>&5
+  lt_cv_compiler_c_o=no
+fi
+CFLAGS="$save_CFLAGS"
+chmod u+w .
+$rm conftest* out/*
+rmdir out
+cd ..
+rmdir conftest
+$rm -r conftest 2>/dev/null
+
+fi
+
+compiler_c_o=$lt_cv_compiler_c_o
+echo "$as_me:$LINENO: result: $compiler_c_o" >&5
+echo "${ECHO_T}$compiler_c_o" >&6
+
+if test x"$compiler_c_o" = x"yes"; then
+  # Check to see if we can write to a .lo
+  echo "$as_me:$LINENO: checking if $compiler supports -c -o file.lo" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.lo... $ECHO_C" >&6
+  if test "${lt_cv_compiler_o_lo+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+  lt_cv_compiler_o_lo=no
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -c -o conftest.lo"
+  save_objext="$ac_objext"
+  ac_objext=lo
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+int some_variable = 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+      # The compiler can only warn and ignore the option if not recognized
+    # So say no if there are warnings
+    if test -s conftest.err; then
+      lt_cv_compiler_o_lo=no
+    else
+      lt_cv_compiler_o_lo=yes
+    fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_objext="$save_objext"
+  CFLAGS="$save_CFLAGS"
+
+fi
+
+  compiler_o_lo=$lt_cv_compiler_o_lo
+  echo "$as_me:$LINENO: result: $compiler_o_lo" >&5
+echo "${ECHO_T}$compiler_o_lo" >&6
+else
+  compiler_o_lo=no
+fi
+
+# Check to see if we can do hard links to lock some files if needed
+hard_links="nottested"
+if test "$compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+  if test "$hard_links" = no; then
+    { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+if test "$GCC" = yes; then
+  # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+  echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext"
+  compiler_rtti_exceptions=no
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+int some_variable = 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+      # The compiler can only warn and ignore the option if not recognized
+    # So say no if there are warnings
+    if test -s conftest.err; then
+      compiler_rtti_exceptions=no
+    else
+      compiler_rtti_exceptions=yes
+    fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS="$save_CFLAGS"
+  echo "$as_me:$LINENO: result: $compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$compiler_rtti_exceptions" >&6
+
+  if test "$compiler_rtti_exceptions" = "yes"; then
+    no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
+  else
+    no_builtin_flag=' -fno-builtin'
+  fi
+fi
+
+# See if the linker supports building shared libraries.
+echo "$as_me:$LINENO: checking whether the linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+allow_undefined_flag=
+no_undefined_flag=
+need_lib_prefix=unknown
+need_version=unknown
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+archive_cmds=
+archive_expsym_cmds=
+old_archive_from_new_cmds=
+old_archive_from_expsyms_cmds=
+export_dynamic_flag_spec=
+whole_archive_flag_spec=
+thread_safe_flag_spec=
+hardcode_into_libs=no
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+hardcode_shlibpath_var=unsupported
+runpath_var=
+link_all_deplibs=unknown
+always_export_symbols=no
+export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
+# include_expsyms should be a list of space-separated symbols to be *always*
+# included in the symbol list
+include_expsyms=
+# exclude_expsyms can be an egrep regular expression of symbols to exclude
+# it will be wrapped by ` (' and `)$', so one must not match beginning or
+# end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+# as well as any symbol that contains `d'.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+# platforms (ab)use it in PIC code, but their linkers get confused if
+# the symbol is explicitly referenced.  Since portable code cannot
+# rely on this symbol name, it's probably fine to never include it in
+# preloaded symbol tables.
+extract_expsyms_cmds=
+
+case $host_os in
+cygwin* | mingw* | pw32*)
+  # FIXME: the MSVC++ port hasn't been tested in a loooong time
+  # When not using gcc, we currently assume that we are using
+  # Microsoft Visual C++.
+  if test "$GCC" != yes; then
+    with_gnu_ld=no
+  fi
+  ;;
+openbsd*)
+  with_gnu_ld=no
+  ;;
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+  # If archive_cmds runs LD, not CC, wlarc should be empty
+  wlarc='${wl}'
+
+  # See if GNU ld supports shared libraries.
+  case $host_os in
+  aix3* | aix4* | aix5*)
+    # On AIX, the GNU linker is very broken
+    # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available.
+    ld_shlibs=no
+    cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+    ;;
+
+  amigaos*)
+    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+
+    # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+    # that the semantics of dynamic libraries on AmigaOS, at least up
+    # to version 4, is to share data among multiple programs linked
+    # with the same dynamic library.  Since this doesn't match the
+    # behavior of shared libraries on other platforms, we can use
+    # them.
+    ld_shlibs=no
+    ;;
+
+  beos*)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      allow_undefined_flag=unsupported
+      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+      # support --undefined.  This deserves some investigation.  FIXME
+      archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # hardcode_libdir_flag_spec is actually meaningless, as there is
+    # no search path for DLLs.
+    hardcode_libdir_flag_spec='-L$libdir'
+    allow_undefined_flag=unsupported
+    always_export_symbols=yes
+
+    extract_expsyms_cmds='test -f $output_objdir/impgen.c || \
+      sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~
+      test -f $output_objdir/impgen.exe || (cd $output_objdir && \
+      if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \
+      else $CC -o impgen impgen.c ; fi)~
+      $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def'
+
+    old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib'
+
+    # cygwin and mingw dlls have different entry points and sets of symbols
+    # to exclude.
+    # FIXME: what about values for MSVC?
+    dll_entry=__cygwin_dll_entry@12
+    dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~
+    case $host_os in
+    mingw*)
+      # mingw values
+      dll_entry=_DllMainCRTStartup@12
+      dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~
+      ;;
+    esac
+
+    # mingw and cygwin differ, and it's simplest to just exclude the union
+    # of the two symbol sets.
+    dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12
+
+    # recent cygwin and mingw systems supply a stub DllMain which the user
+    # can override, but on older systems we have to supply one (in ltdll.c)
+    if test "x$lt_cv_need_dllmain" = "xyes"; then
+      ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext "
+      ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~
+	test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~'
+    else
+      ltdll_obj=
+      ltdll_cmds=
+    fi
+
+    # Extract the symbol export list from an `--export-all' def file,
+    # then regenerate the def file from the symbol export list, so that
+    # the compiled dll only exports the symbol export list.
+    # Be careful not to strip the DATA tag left be newer dlltools.
+    export_symbols_cmds="$ltdll_cmds"'
+      $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~
+      sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols'
+
+    # If the export-symbols file already is a .def file (1st line
+    # is EXPORTS), use it as is.
+    # If DATA tags from a recent dlltool are present, honour them!
+    archive_expsym_cmds='if test "x`sed 1q $export_symbols`" = xEXPORTS; then
+	cp $export_symbols $output_objdir/$soname-def;
+      else
+	echo EXPORTS > $output_objdir/$soname-def;
+	_lt_hint=1;
+	cat $export_symbols | while read symbol; do
+	 set dummy \$symbol;
+	 case \$# in
+	   2) echo "   \$2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;;
+	   4) echo "   \$2 \$3 \$4 ; " >> $output_objdir/$soname-def; _lt_hint=`expr \$_lt_hint - 1`;;
+	   *) echo "     \$2 @ \$_lt_hint \$3 ; " >> $output_objdir/$soname-def;;
+	 esac;
+	 _lt_hint=`expr 1 + \$_lt_hint`;
+	done;
+      fi~
+      '"$ltdll_cmds"'
+      $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~
+      $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~
+      $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags'
+    ;;
+
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+      wlarc=
+    else
+      archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    fi
+    ;;
+
+  solaris* | sysv5*)
+    if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
+      ld_shlibs=no
+      cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+    elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+
+  sunos4*)
+    archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+    wlarc=
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  *)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+  esac
+
+  if test "$ld_shlibs" = yes; then
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    case $host_os in
+    cygwin* | mingw* | pw32*)
+      # dlltool doesn't understand --whole-archive et. al.
+      whole_archive_flag_spec=
+      ;;
+    *)
+      # ancient GNU ld didn't support --whole-archive et. al.
+      if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
+	whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+	whole_archive_flag_spec=
+      fi
+      ;;
+    esac
+  fi
+else
+  # PORTME fill in a description of your system's linker (not GNU ld)
+  case $host_os in
+  aix3*)
+    allow_undefined_flag=unsupported
+    always_export_symbols=yes
+    archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+    # Note: this linker hardcodes the directories in LIBPATH if there
+    # are no directories specified by -L.
+    hardcode_minus_L=yes
+    if test "$GCC" = yes && test -z "$link_static_flag"; then
+      # Neither direct hardcoding nor static linking is supported with a
+      # broken collect2.
+      hardcode_direct=unsupported
+    fi
+    ;;
+
+  aix4* | aix5*)
+    if test "$host_cpu" = ia64; then
+      # On IA64, the linker does run time linking by default, so we don't
+      # have to do anything special.
+      aix_use_runtimelinking=no
+      exp_sym_flag='-Bexport'
+      no_entry_flag=""
+    else
+      aix_use_runtimelinking=no
+
+      # Test if we are trying to use run time linking or normal
+      # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+      # need to do runtime linking.
+      case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+	for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	done
+      esac
+
+      exp_sym_flag='-bexport'
+      no_entry_flag='-bnoentry'
+    fi
+
+    # When large executables or shared objects are built, AIX ld can
+    # have problems creating the table of contents.  If linking a library
+    # or program results in "error TOC overflow" add -mminimal-toc to
+    # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+    # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+    hardcode_direct=yes
+    archive_cmds=''
+    hardcode_libdir_separator=':'
+    if test "$GCC" = yes; then
+      case $host_os in aix4.[012]|aix4.[012].*)
+	collect2name=`${CC} -print-prog-name=collect2`
+	if test -f "$collect2name" && \
+	  strings "$collect2name" | grep resolve_lib_name >/dev/null
+	then
+	  # We have reworked collect2
+	  hardcode_direct=yes
+	else
+	  # We have old collect2
+	  hardcode_direct=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  hardcode_minus_L=yes
+	  hardcode_libdir_flag_spec='-L$libdir'
+	  hardcode_libdir_separator=
+	fi
+      esac
+
+      shared_flag='-shared'
+    else
+      # not using gcc
+      if test "$host_cpu" = ia64; then
+	shared_flag='${wl}-G'
+      else
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag='${wl}-G'
+	else
+	  shared_flag='${wl}-bM:SRE'
+	fi
+      fi
+    fi
+
+    # It seems that -bexpall can do strange things, so it is better to
+    # generate a list of symbols to export.
+    always_export_symbols=yes
+    if test "$aix_use_runtimelinking" = yes; then
+      # Warning - without using the other runtime loading flags (-brtl),
+      # -berok will link without error, but may produce a broken library.
+      allow_undefined_flag='-berok'
+      hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib'
+      archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+    else
+      if test "$host_cpu" = ia64; then
+	hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+	allow_undefined_flag="-z nodefs"
+	archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+      else
+	hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib'
+	# Warning - without using the other run time loading flags,
+	# -berok will link without error, but may produce a broken library.
+	allow_undefined_flag='${wl}-berok'
+	# This is a bit strange, but is similar to how AIX traditionally builds
+	# it's shared libraries.
+	archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname'
+      fi
+    fi
+    ;;
+
+  amigaos*)
+    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+    # see comment about different semantics on the GNU ld section
+    ld_shlibs=no
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    # hardcode_libdir_flag_spec is actually meaningless, as there is
+    # no search path for DLLs.
+    hardcode_libdir_flag_spec=' '
+    allow_undefined_flag=unsupported
+    # Tell ltmain to make .lib files, not .a files.
+    libext=lib
+    # FIXME: Setting linknames here is a bad hack.
+    archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+    # The linker will automatically build a .lib file if we build a DLL.
+    old_archive_from_new_cmds='true'
+    # FIXME: Should let the user specify the lib program.
+    old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
+    fix_srcfile_path='`cygpath -w "$srcfile"`'
+    ;;
+
+  darwin* | rhapsody*)
+    case "$host_os" in
+    rhapsody* | darwin1.[012])
+      allow_undefined_flag='-undefined suppress'
+      ;;
+    *) # Darwin 1.3 on
+      allow_undefined_flag='-flat_namespace -undefined suppress'
+      ;;
+    esac
+    # FIXME: Relying on posixy $() will cause problems for
+    #        cross-compilation, but unfortunately the echo tests do not
+    #        yet detect zsh echo's removal of \ escapes.  Also zsh mangles
+    #	     `"' quotes if we put them in here... so don't!
+    archive_cmds='$nonopt $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs$linker_flags -install_name $rpath/$soname $verstring'
+    # We need to add '_' to the symbols in $export_symbols first
+    #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    whole_archive_flag_spec='-all_load $convenience'
+    ;;
+
+  freebsd1*)
+    ld_shlibs=no
+    ;;
+
+  # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+  # support.  Future versions do this automatically, but an explicit c++rt0.o
+  # does not break anything, and helps significantly (at the cost of a little
+  # extra space).
+  freebsd2.2*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+  freebsd2*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_direct=yes
+    hardcode_minus_L=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+  freebsd*)
+    archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  hpux9* | hpux10* | hpux11*)
+    case $host_os in
+    hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;;
+    *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;;
+    esac
+    hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+    hardcode_libdir_separator=:
+    hardcode_direct=yes
+    hardcode_minus_L=yes # Not in the search PATH, but as the default
+			 # location of the library.
+    export_dynamic_flag_spec='${wl}-E'
+    ;;
+
+  irix5* | irix6* | nonstopux*)
+    if test "$GCC" = yes; then
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+    else
+      archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    link_all_deplibs=yes
+    ;;
+
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+    else
+      archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+    fi
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  newsos6)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_direct=yes
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    hardcode_shlibpath_var=no
+    ;;
+
+  openbsd*)
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+    else
+      case "$host_os" in
+      openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	hardcode_libdir_flag_spec='-R$libdir'
+        ;;
+      *)
+        archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags'
+        hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+        ;;
+      esac
+    fi
+    ;;
+
+  os2*)
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+    allow_undefined_flag=unsupported
+    archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+    old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+    ;;
+
+  osf3*)
+    if test "$GCC" = yes; then
+      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+    else
+      allow_undefined_flag=' -expect_unresolved \*'
+      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    ;;
+
+  osf4* | osf5*)	# as osf3* with the addition of -msym flag
+    if test "$GCC" = yes; then
+      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    else
+      allow_undefined_flag=' -expect_unresolved \*'
+      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+      $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+
+      #Both c and cxx compiler support -rpath directly
+      hardcode_libdir_flag_spec='-rpath $libdir'
+    fi
+    hardcode_libdir_separator=:
+    ;;
+
+  sco3.2v5*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_shlibpath_var=no
+    runpath_var=LD_RUN_PATH
+    hardcode_runpath_var=yes
+    export_dynamic_flag_spec='${wl}-Bexport'
+    ;;
+
+  solaris*)
+    # gcc --version < 3.0 without binutils cannot create self contained
+    # shared libraries reliably, requiring libgcc.a to resolve some of
+    # the object symbols generated in some cases.  Libraries that use
+    # assert need libgcc.a to resolve __eprintf, for example.  Linking
+    # a copy of libgcc.a into every shared library to guarantee resolving
+    # such symbols causes other problems:  According to Tim Van Holder
+    # <tim.van.holder@pandora.be>, C++ libraries end up with a separate
+    # (to the application) exception stack for one thing.
+    no_undefined_flag=' -z defs'
+    if test "$GCC" = yes; then
+      case `$CC --version 2>/dev/null` in
+      [12].*)
+	cat <<EOF 1>&2
+
+*** Warning: Releases of GCC earlier than version 3.0 cannot reliably
+*** create self contained shared libraries on Solaris systems, without
+*** introducing a dependency on libgcc.a.  Therefore, libtool is disabling
+*** -no-undefined support, which will at least allow you to build shared
+*** libraries.  However, you may find that when you link such libraries
+*** into an application without using GCC, you have to manually add
+*** \`gcc --print-libgcc-file-name\` to the link command.  We urge you to
+*** upgrade to a newer version of GCC.  Another option is to rebuild your
+*** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer.
+
+EOF
+        no_undefined_flag=
+	;;
+      esac
+    fi
+    # $CC -shared without GNU ld will not create a library from C++
+    # object files and a static libstdc++, better avoid it by now
+    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+		$LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_shlibpath_var=no
+    case $host_os in
+    solaris2.[0-5] | solaris2.[0-5].*) ;;
+    *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+      whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+    esac
+    link_all_deplibs=yes
+    ;;
+
+  sunos4*)
+    if test "x$host_vendor" = xsequent; then
+      # Use $CC to link under sequent, because it throws in some extra .o
+      # files that make .init and .fini sections work.
+      archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+    else
+      archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+    fi
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_direct=yes
+    hardcode_minus_L=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4)
+    case $host_vendor in
+      sni)
+        archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+        hardcode_direct=yes # is this really true???
+        ;;
+      siemens)
+        ## LD is ld it makes a PLAMLIB
+        ## CC just makes a GrossModule.
+        archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+        reload_cmds='$CC -r -o $output$reload_objs'
+        hardcode_direct=no
+        ;;
+      motorola)
+        archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+        hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+        ;;
+    esac
+    runpath_var='LD_RUN_PATH'
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4.3*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_shlibpath_var=no
+    export_dynamic_flag_spec='-Bexport'
+    ;;
+
+  sysv5*)
+    no_undefined_flag=' -z text'
+    # $CC -shared without GNU ld will not create a library from C++
+    # object files and a static libstdc++, better avoid it by now
+    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+		$LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+    hardcode_libdir_flag_spec=
+    hardcode_shlibpath_var=no
+    runpath_var='LD_RUN_PATH'
+    ;;
+
+  uts4*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_shlibpath_var=no
+    ;;
+
+  dgux*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4*MP*)
+    if test -d /usr/nec; then
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      runpath_var=LD_RUN_PATH
+      hardcode_runpath_var=yes
+      ld_shlibs=yes
+    fi
+    ;;
+
+  sysv4.2uw2*)
+    archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_direct=yes
+    hardcode_minus_L=no
+    hardcode_shlibpath_var=no
+    hardcode_runpath_var=yes
+    runpath_var=LD_RUN_PATH
+    ;;
+
+  sysv5uw7* | unixware7*)
+    no_undefined_flag='${wl}-z ${wl}text'
+    if test "$GCC" = yes; then
+      archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+    else
+      archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+    fi
+    runpath_var='LD_RUN_PATH'
+    hardcode_shlibpath_var=no
+    ;;
+
+  *)
+    ld_shlibs=no
+    ;;
+  esac
+fi
+echo "$as_me:$LINENO: result: $ld_shlibs" >&5
+echo "${ECHO_T}$ld_shlibs" >&6
+test "$ld_shlibs" = no && can_build_shared=no
+
+# Check hardcoding attributes.
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+   test -n "$runpath_var"; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$hardcode_shlibpath_var" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action" >&5
+echo "${ECHO_T}$hardcode_action" >&6
+
+striplib=
+old_striplib=
+echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+# PORTME Fill in your ld.so characteristics
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}.so$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+	if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	     echo ' yes '
+	     echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+	  :
+	else
+	  can_build_shared=no
+	fi
+	;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can
+    # not hardcode correct soname into executable. Probably we can
+    # add versioning support to collect2, so additional links can
+    # be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}.so$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}.so'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi4*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  export_dynamic_flag_spec=-rdynamic
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  need_version=no
+  need_lib_prefix=no
+  case $GCC,$host_os in
+  yes,cygwin*)
+    library_names_spec='$libname.dll.a'
+    soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll'
+    postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog .libs/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    ;;
+  yes,mingw*)
+    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll'
+    sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g" -e "s,=/,/,g"`
+    ;;
+  yes,pw32*)
+    library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/./-/g'`${versuffix}.dll'
+    ;;
+  *)
+    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  # FIXME: Relying on posixy $() will cause problems for
+  #        cross-compilation, but unfortunately the echo tests do not
+  #        yet detect zsh echo's removal of \ escapes.
+  library_names_spec='${libname}${release}${versuffix}.$(test .$module = .yes && echo so || echo dylib) ${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib) ${libname}.$(test .$module = .yes && echo so || echo dylib)'
+  soname_spec='${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib)'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd*)
+  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  *)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  dynamic_linker="$host_os dld.sl"
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  shlibpath_var=SHLIB_PATH
+  shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+  library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
+  soname_spec='${libname}${release}.sl$major'
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)          version_type=irix ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}.so$major'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
+    soname_spec='${libname}${release}.so$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case "$host_os" in
+    openbsd2.[89] | openbsd2.[89].*)
+      shlibpath_overrides_runpath=no
+      ;;
+    *)
+      shlibpath_overrides_runpath=yes
+      ;;
+    esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+os2*)
+  libname_spec='$name'
+  need_lib_prefix=no
+  library_names_spec='$libname.dll $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_version=no
+  soname_spec='${libname}${release}.so'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+sco3.2v5*)
+  version_type=osf
+  soname_spec='${libname}${release}.so$major'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+    soname_spec='$libname.so.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+# Report the final consequences.
+echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+
+aix4*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+  ;;
+esac
+echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6
+
+if test "$hardcode_action" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+   ;;
+
+  *)
+    echo "$as_me:$LINENO: checking for shl_load" >&5
+echo $ECHO_N "checking for shl_load... $ECHO_C" >&6
+if test "${ac_cv_func_shl_load+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define shl_load innocuous_shl_load
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char shl_load (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shl_load
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char shl_load ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_shl_load) || defined (__stub___shl_load)
+choke me
+#else
+char (*f) () = shl_load;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != shl_load;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_shl_load=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_shl_load=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+echo "${ECHO_T}$ac_cv_func_shl_load" >&6
+if test $ac_cv_func_shl_load = yes; then
+  lt_cv_dlopen="shl_load"
+else
+  echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char shl_load ();
+int
+main ()
+{
+shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_dld_shl_load=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dld_shl_load=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6
+if test $ac_cv_lib_dld_shl_load = yes; then
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
+else
+  echo "$as_me:$LINENO: checking for dlopen" >&5
+echo $ECHO_N "checking for dlopen... $ECHO_C" >&6
+if test "${ac_cv_func_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define dlopen innocuous_dlopen
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char dlopen (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef dlopen
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char dlopen ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_dlopen) || defined (__stub___dlopen)
+choke me
+#else
+char (*f) () = dlopen;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != dlopen;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+echo "${ECHO_T}$ac_cv_func_dlopen" >&6
+if test $ac_cv_func_dlopen = yes; then
+  lt_cv_dlopen="dlopen"
+else
+  echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dl_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
+if test $ac_cv_lib_dl_dlopen = yes; then
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_svld_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_svld_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6
+if test $ac_cv_lib_svld_dlopen = yes; then
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+  echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char dld_link ();
+int
+main ()
+{
+dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_dld_dld_link=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dld_dld_link=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6
+if test $ac_cv_lib_dld_dld_link = yes; then
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+        test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6
+if test "${lt_cv_dlopen_self+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self=cross
+else
+    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+#line 6720 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+
+    exit (status);
+}
+EOF
+  if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_unknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self" >&6
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      LDFLAGS="$LDFLAGS $link_static_flag"
+      echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self_static=cross
+else
+    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+#line 6818 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+
+    exit (status);
+}
+EOF
+  if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+if test "$enable_shared" = yes && test "$GCC" = yes; then
+  case $archive_cmds in
+  *'~'*)
+    # FIXME: we may have to deal with multi-command sequences.
+    ;;
+  '$CC '*)
+    # Test whether the compiler implicitly links with -lc since on some
+    # systems, -lgcc has to come before -lc. If gcc already passes -lc
+    # to ld, don't add -lc before -lgcc.
+    echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+    if test "${lt_cv_archive_cmds_need_lc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  $rm conftest*
+    echo 'static int dummy;' > conftest.$ac_ext
+
+    if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+      soname=conftest
+      lib=conftest
+      libobjs=conftest.$ac_objext
+      deplibs=
+      wl=$lt_cv_prog_cc_wl
+      compiler_flags=-v
+      linker_flags=-v
+      verstring=
+      output_objdir=.
+      libname=conftest
+      save_allow_undefined_flag=$allow_undefined_flag
+      allow_undefined_flag=
+      if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+  (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+      then
+	lt_cv_archive_cmds_need_lc=no
+      else
+	lt_cv_archive_cmds_need_lc=yes
+      fi
+      allow_undefined_flag=$save_allow_undefined_flag
+    else
+      cat conftest.err 1>&5
+    fi
+fi
+
+    echo "$as_me:$LINENO: result: $lt_cv_archive_cmds_need_lc" >&5
+echo "${ECHO_T}$lt_cv_archive_cmds_need_lc" >&6
+    ;;
+  esac
+fi
+need_lc=${lt_cv_archive_cmds_need_lc-yes}
+
+# The second clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  :
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  test -f Makefile && make "$ltmain"
+fi
+
+if test -f "$ltmain"; then
+  trap "$rm \"${ofile}T\"; exit 1" 1 2 15
+  $rm -f "${ofile}T"
+
+  echo creating $ofile
+
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS SED \
+    AR AR_FLAGS CC LD LN_S NM SHELL \
+    reload_flag reload_cmds wl \
+    pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+    thread_safe_flag_spec whole_archive_flag_spec libname_spec \
+    library_names_spec soname_spec \
+    RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+    old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \
+    postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \
+    old_striplib striplib file_magic_cmd export_symbols_cmds \
+    deplibs_check_method allow_undefined_flag no_undefined_flag \
+    finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
+    global_symbol_to_c_name_address \
+    hardcode_libdir_flag_spec hardcode_libdir_separator  \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+
+    case $var in
+    reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
+    extract_expsyms_cmds | old_archive_from_expsyms_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  cat <<__EOF__ > "${ofile}T"
+#! $SHELL
+
+# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996-2000 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="${SED} -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$need_lc
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# The default C compiler.
+CC=$lt_CC
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_wl
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_pic_flag
+pic_mode=$pic_mode
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_compiler_c_o
+
+# Can we write directly to a .lo ?
+compiler_o_lo=$lt_compiler_o_lo
+
+# Must we lock files when doing compilation ?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_link_static_flag
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# ### END LIBTOOL CONFIG
+
+__EOF__
+
+  case $host_os in
+  aix3*)
+    cat <<\EOF >> "${ofile}T"
+
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+EOF
+    ;;
+  esac
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | os2*)
+    cat <<'EOF' >> "${ofile}T"
+      # This is a source program that is used to create dlls on Windows
+      # Don't remove nor modify the starting and closing comments
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# #  ifdef __CYGWIN32__
+# #    define __CYGWIN__ __CYGWIN32__
+# #  endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+#   __hDllInstance_base = hInst;
+#   return TRUE;
+# }
+# /* ltdll.c ends here */
+	# This is a source program that is used to create import libraries
+	# on Windows for dlls which lack them. Don't remove nor modify the
+	# starting and closing comments
+# /* impgen.c starts here */
+# /*   Copyright (C) 1999-2000 Free Software Foundation, Inc.
+#
+#  This file is part of GNU libtool.
+#
+#  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 of the License, 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 program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#  */
+#
+# #include <stdio.h>		/* for printf() */
+# #include <unistd.h>		/* for open(), lseek(), read() */
+# #include <fcntl.h>		/* for O_RDONLY, O_BINARY */
+# #include <string.h>		/* for strdup() */
+#
+# /* O_BINARY isn't required (or even defined sometimes) under Unix */
+# #ifndef O_BINARY
+# #define O_BINARY 0
+# #endif
+#
+# static unsigned int
+# pe_get16 (fd, offset)
+#      int fd;
+#      int offset;
+# {
+#   unsigned char b[2];
+#   lseek (fd, offset, SEEK_SET);
+#   read (fd, b, 2);
+#   return b[0] + (b[1]<<8);
+# }
+#
+# static unsigned int
+# pe_get32 (fd, offset)
+#     int fd;
+#     int offset;
+# {
+#   unsigned char b[4];
+#   lseek (fd, offset, SEEK_SET);
+#   read (fd, b, 4);
+#   return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# static unsigned int
+# pe_as32 (ptr)
+#      void *ptr;
+# {
+#   unsigned char *b = ptr;
+#   return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# int
+# main (argc, argv)
+#     int argc;
+#     char *argv[];
+# {
+#     int dll;
+#     unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+#     unsigned long export_rva, export_size, nsections, secptr, expptr;
+#     unsigned long name_rvas, nexp;
+#     unsigned char *expdata, *erva;
+#     char *filename, *dll_name;
+#
+#     filename = argv[1];
+#
+#     dll = open(filename, O_RDONLY|O_BINARY);
+#     if (dll < 1)
+# 	return 1;
+#
+#     dll_name = filename;
+#
+#     for (i=0; filename[i]; i++)
+# 	if (filename[i] == '/' || filename[i] == '\\'  || filename[i] == ':')
+# 	    dll_name = filename + i +1;
+#
+#     pe_header_offset = pe_get32 (dll, 0x3c);
+#     opthdr_ofs = pe_header_offset + 4 + 20;
+#     num_entries = pe_get32 (dll, opthdr_ofs + 92);
+#
+#     if (num_entries < 1) /* no exports */
+# 	return 1;
+#
+#     export_rva = pe_get32 (dll, opthdr_ofs + 96);
+#     export_size = pe_get32 (dll, opthdr_ofs + 100);
+#     nsections = pe_get16 (dll, pe_header_offset + 4 +2);
+#     secptr = (pe_header_offset + 4 + 20 +
+# 	      pe_get16 (dll, pe_header_offset + 4 + 16));
+#
+#     expptr = 0;
+#     for (i = 0; i < nsections; i++)
+#     {
+# 	char sname[8];
+# 	unsigned long secptr1 = secptr + 40 * i;
+# 	unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+# 	unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+# 	unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+# 	lseek(dll, secptr1, SEEK_SET);
+# 	read(dll, sname, 8);
+# 	if (vaddr <= export_rva && vaddr+vsize > export_rva)
+# 	{
+# 	    expptr = fptr + (export_rva - vaddr);
+# 	    if (export_rva + export_size > vaddr + vsize)
+# 		export_size = vsize - (export_rva - vaddr);
+# 	    break;
+# 	}
+#     }
+#
+#     expdata = (unsigned char*)malloc(export_size);
+#     lseek (dll, expptr, SEEK_SET);
+#     read (dll, expdata, export_size);
+#     erva = expdata - export_rva;
+#
+#     nexp = pe_as32 (expdata+24);
+#     name_rvas = pe_as32 (expdata+32);
+#
+#     printf ("EXPORTS\n");
+#     for (i = 0; i<nexp; i++)
+#     {
+# 	unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
+# 	printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
+#     }
+#
+#     return 0;
+# }
+# /* impgen.c ends here */
+
+EOF
+    ;;
+  esac
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "${ofile}T" || (rm -f "${ofile}T"; exit 1)
+
+  mv -f "${ofile}T" "$ofile" || \
+    (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T")
+  chmod +x "$ofile"
+fi
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Prevent multiple expansion
+
+
+
+# Extract the first word of "perl", so it can be a program name with args.
+set dummy perl; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_PERL+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $PERL in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_path_PERL" && ac_cv_path_PERL="/usr/bin/perl"
+  ;;
+esac
+fi
+PERL=$ac_cv_path_PERL
+
+if test -n "$PERL"; then
+  echo "$as_me:$LINENO: result: $PERL" >&5
+echo "${ECHO_T}$PERL" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+# Extract the first word of "sh", so it can be a program name with args.
+set dummy sh; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_SH+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $SH in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_SH="$SH" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_SH="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_path_SH" && ac_cv_path_SH="/bin/sh"
+  ;;
+esac
+fi
+SH=$ac_cv_path_SH
+
+if test -n "$SH"; then
+  echo "$as_me:$LINENO: result: $SH" >&5
+echo "${ECHO_T}$SH" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+
+echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5
+echo $ECHO_N "checking whether to enable maintainer-specific portions of Makefiles... $ECHO_C" >&6
+    # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then
+  enableval="$enable_maintainer_mode"
+  USE_MAINTAINER_MODE=$enableval
+else
+  USE_MAINTAINER_MODE=no
+fi;
+  echo "$as_me:$LINENO: result: $USE_MAINTAINER_MODE" >&5
+echo "${ECHO_T}$USE_MAINTAINER_MODE" >&6
+
+
+if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+  MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+
+      if test "X$prefix" = "XNONE"; then
+    acl_final_prefix="$ac_default_prefix"
+  else
+    acl_final_prefix="$prefix"
+  fi
+  if test "X$exec_prefix" = "XNONE"; then
+    acl_final_exec_prefix='${prefix}'
+  else
+    acl_final_exec_prefix="$exec_prefix"
+  fi
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+  prefix="$acl_save_prefix"
+
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval="$with_gnu_ld"
+  test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi;
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  echo "$as_me:$LINENO: checking for ld used by GCC" >&5
+echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+else
+  echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+fi
+if test "${acl_cv_path_LD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$LD"; then
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      acl_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$acl_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+	test "$with_gnu_ld" != no && break
+      else
+	test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+  echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${acl_cv_prog_gnu_ld+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  acl_cv_prog_gnu_ld=yes
+else
+  acl_cv_prog_gnu_ld=no
+fi
+fi
+echo "$as_me:$LINENO: result: $acl_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$acl_cv_prog_gnu_ld" >&6
+with_gnu_ld=$acl_cv_prog_gnu_ld
+
+
+
+                                                echo "$as_me:$LINENO: checking for shared library run path origin" >&5
+echo $ECHO_N "checking for shared library run path origin... $ECHO_C" >&6
+if test "${acl_cv_rpath+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+    CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+    ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+    . ./conftest.sh
+    rm -f ./conftest.sh
+    acl_cv_rpath=done
+
+fi
+echo "$as_me:$LINENO: result: $acl_cv_rpath" >&5
+echo "${ECHO_T}$acl_cv_rpath" >&6
+  wl="$acl_cv_wl"
+  libext="$acl_cv_libext"
+  shlibext="$acl_cv_shlibext"
+  hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+  hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+  hardcode_direct="$acl_cv_hardcode_direct"
+  hardcode_minus_L="$acl_cv_hardcode_minus_L"
+  sys_lib_search_path_spec="$acl_cv_sys_lib_search_path_spec"
+  sys_lib_dlsearch_path_spec="$acl_cv_sys_lib_dlsearch_path_spec"
+    # Check whether --enable-rpath or --disable-rpath was given.
+if test "${enable_rpath+set}" = set; then
+  enableval="$enable_rpath"
+  :
+else
+  enable_rpath=yes
+fi;
+
+
+
+
+
+
+
+    use_additional=yes
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+
+# Check whether --with-libiconv-prefix or --without-libiconv-prefix was given.
+if test "${with_libiconv_prefix+set}" = set; then
+  withval="$with_libiconv_prefix"
+
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/lib"
+      fi
+    fi
+
+fi;
+      LIBICONV=
+  LTLIBICONV=
+  INCICONV=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='iconv '
+  while test -n "$names_next_round"; do
+    names_this_round="$names_next_round"
+    names_next_round=
+    for name in $names_this_round; do
+      already_handled=
+      for n in $names_already_handled; do
+        if test "$n" = "$name"; then
+          already_handled=yes
+          break
+        fi
+      done
+      if test -z "$already_handled"; then
+        names_already_handled="$names_already_handled $name"
+                        uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+        eval value=\"\$HAVE_LIB$uppername\"
+        if test -n "$value"; then
+          if test "$value" = yes; then
+            eval value=\"\$LIB$uppername\"
+            test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value"
+          else
+                                    :
+          fi
+        else
+                              found_dir=
+          found_la=
+          found_so=
+          found_a=
+          if test $use_additional = yes; then
+            if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then
+              found_dir="$additional_libdir"
+              found_so="$additional_libdir/lib$name.$shlibext"
+              if test -f "$additional_libdir/lib$name.la"; then
+                found_la="$additional_libdir/lib$name.la"
+              fi
+            else
+              if test -f "$additional_libdir/lib$name.$libext"; then
+                found_dir="$additional_libdir"
+                found_a="$additional_libdir/lib$name.$libext"
+                if test -f "$additional_libdir/lib$name.la"; then
+                  found_la="$additional_libdir/lib$name.la"
+                fi
+              fi
+            fi
+          fi
+          if test "X$found_dir" = "X"; then
+            for x in $LDFLAGS $LTLIBICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+              case "$x" in
+                -L*)
+                  dir=`echo "X$x" | sed -e 's/^X-L//'`
+                  if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then
+                    found_dir="$dir"
+                    found_so="$dir/lib$name.$shlibext"
+                    if test -f "$dir/lib$name.la"; then
+                      found_la="$dir/lib$name.la"
+                    fi
+                  else
+                    if test -f "$dir/lib$name.$libext"; then
+                      found_dir="$dir"
+                      found_a="$dir/lib$name.$libext"
+                      if test -f "$dir/lib$name.la"; then
+                        found_la="$dir/lib$name.la"
+                      fi
+                    fi
+                  fi
+                  ;;
+              esac
+              if test "X$found_dir" != "X"; then
+                break
+              fi
+            done
+          fi
+          if test "X$found_dir" != "X"; then
+                        LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name"
+            if test "X$found_so" != "X"; then
+                                                        if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then
+                                LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+              else
+                                                                                haveit=
+                for x in $ltrpathdirs; do
+                  if test "X$x" = "X$found_dir"; then
+                    haveit=yes
+                    break
+                  fi
+                done
+                if test -z "$haveit"; then
+                  ltrpathdirs="$ltrpathdirs $found_dir"
+                fi
+                                if test "$hardcode_direct" = yes; then
+                                                      LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+                else
+                  if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+                                                            LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+                                                            haveit=
+                    for x in $rpathdirs; do
+                      if test "X$x" = "X$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      rpathdirs="$rpathdirs $found_dir"
+                    fi
+                  else
+                                                                                haveit=
+                    for x in $LDFLAGS $LIBICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                      if test "X$x" = "X-L$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir"
+                    fi
+                    if test "$hardcode_minus_L" != no; then
+                                                                                        LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+                    else
+                                                                                                                                                                                LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                                LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a"
+              else
+                                                LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name"
+              fi
+            fi
+                        additional_includedir=
+            case "$found_dir" in
+              */lib | */lib/)
+                basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
+                additional_includedir="$basedir/include"
+                ;;
+            esac
+            if test "X$additional_includedir" != "X"; then
+                                                                                                                if test "X$additional_includedir" != "X/usr/include"; then
+                haveit=
+                if test "X$additional_includedir" = "X/usr/local/include"; then
+                  if test -n "$GCC"; then
+                    case $host_os in
+                      linux*) haveit=yes;;
+                    esac
+                  fi
+                fi
+                if test -z "$haveit"; then
+                  for x in $CPPFLAGS $INCICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                    if test "X$x" = "X-I$additional_includedir"; then
+                      haveit=yes
+                      break
+                    fi
+                  done
+                  if test -z "$haveit"; then
+                    if test -d "$additional_includedir"; then
+                                            INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir"
+                    fi
+                  fi
+                fi
+              fi
+            fi
+                        if test -n "$found_la"; then
+                                                        save_libdir="$libdir"
+              case "$found_la" in
+                */* | *\\*) . "$found_la" ;;
+                *) . "./$found_la" ;;
+              esac
+              libdir="$save_libdir"
+                            for dep in $dependency_libs; do
+                case "$dep" in
+                  -L*)
+                    additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+                                                                                                                                                                if test "X$additional_libdir" != "X/usr/lib"; then
+                      haveit=
+                      if test "X$additional_libdir" = "X/usr/local/lib"; then
+                        if test -n "$GCC"; then
+                          case $host_os in
+                            linux*) haveit=yes;;
+                          esac
+                        fi
+                      fi
+                      if test -z "$haveit"; then
+                        haveit=
+                        for x in $LDFLAGS $LIBICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                                                        LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIBICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                                                        LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir"
+                          fi
+                        fi
+                      fi
+                    fi
+                    ;;
+                  -R*)
+                    dir=`echo "X$dep" | sed -e 's/^X-R//'`
+                    if test "$enable_rpath" != no; then
+                                                                  haveit=
+                      for x in $rpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        rpathdirs="$rpathdirs $dir"
+                      fi
+                                                                  haveit=
+                      for x in $ltrpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        ltrpathdirs="$ltrpathdirs $dir"
+                      fi
+                    fi
+                    ;;
+                  -l*)
+                                        names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+                    ;;
+                  *.la)
+                                                                                names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+                    ;;
+                  *)
+                                        LIBICONV="${LIBICONV}${LIBICONV:+ }$dep"
+                    LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+                                                            LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+            LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name"
+          fi
+        fi
+      fi
+    done
+  done
+  if test "X$rpathdirs" != "X"; then
+    if test -n "$hardcode_libdir_separator"; then
+                        alldirs=
+      for found_dir in $rpathdirs; do
+        alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
+      done
+            acl_save_libdir="$libdir"
+      libdir="$alldirs"
+      eval flag=\"$hardcode_libdir_flag_spec\"
+      libdir="$acl_save_libdir"
+      LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+    else
+            for found_dir in $rpathdirs; do
+        acl_save_libdir="$libdir"
+        libdir="$found_dir"
+        eval flag=\"$hardcode_libdir_flag_spec\"
+        libdir="$acl_save_libdir"
+        LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+            for found_dir in $ltrpathdirs; do
+      LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir"
+    done
+  fi
+
+
+
+
+
+
+
+          am_save_CPPFLAGS="$CPPFLAGS"
+
+  for element in $INCICONV; do
+    haveit=
+    for x in $CPPFLAGS; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+      if test "X$x" = "X$element"; then
+        haveit=yes
+        break
+      fi
+    done
+    if test -z "$haveit"; then
+      CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element"
+    fi
+  done
+
+
+  echo "$as_me:$LINENO: checking for iconv" >&5
+echo $ECHO_N "checking for iconv... $ECHO_C" >&6
+if test "${am_cv_func_iconv+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+    am_cv_func_iconv="no, consider installing GNU libiconv"
+    am_cv_lib_iconv=no
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+       iconv(cd,NULL,NULL,NULL,NULL);
+       iconv_close(cd);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  am_cv_func_iconv=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+    if test "$am_cv_func_iconv" != yes; then
+      am_save_LIBS="$LIBS"
+      LIBS="$LIBS $LIBICONV"
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+         iconv(cd,NULL,NULL,NULL,NULL);
+         iconv_close(cd);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  am_cv_lib_iconv=yes
+        am_cv_func_iconv=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+      LIBS="$am_save_LIBS"
+    fi
+
+fi
+echo "$as_me:$LINENO: result: $am_cv_func_iconv" >&5
+echo "${ECHO_T}$am_cv_func_iconv" >&6
+  if test "$am_cv_func_iconv" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ICONV 1
+_ACEOF
+
+  fi
+  if test "$am_cv_lib_iconv" = yes; then
+    echo "$as_me:$LINENO: checking how to link with libiconv" >&5
+echo $ECHO_N "checking how to link with libiconv... $ECHO_C" >&6
+    echo "$as_me:$LINENO: result: $LIBICONV" >&5
+echo "${ECHO_T}$LIBICONV" >&6
+  else
+            CPPFLAGS="$am_save_CPPFLAGS"
+    LIBICONV=
+    LTLIBICONV=
+  fi
+
+
+
+  if test "$am_cv_func_iconv" = yes; then
+    echo "$as_me:$LINENO: checking for iconv declaration" >&5
+echo $ECHO_N "checking for iconv declaration... $ECHO_C" >&6
+    if test "${am_cv_proto_iconv+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  am_cv_proto_iconv_arg1=""
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+am_cv_proto_iconv_arg1="const"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+      am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"
+fi
+
+    am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+    echo "$as_me:$LINENO: result: ${ac_t:-
+         }$am_cv_proto_iconv" >&5
+echo "${ECHO_T}${ac_t:-
+         }$am_cv_proto_iconv" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define ICONV_CONST $am_cv_proto_iconv_arg1
+_ACEOF
+
+  fi
+
+
+#AC_CHECK_FUNCS(iconv_open,,AC_MSG_ERROR([
+#iconv_open not found try to install replacement from
+#http://www.gnu.org/software/libiconv/
+#ftp://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.8.tar.gz]))
+
+
+for ac_func in vsnprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+          ac_config_files="$ac_config_files Makefile"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[	 ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[	 ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+	 sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+		   instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+		   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@VERSION@,$VERSION,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@UNICODE_VERSION@,$UNICODE_VERSION,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@build@,$build,;t t
+s,@build_cpu@,$build_cpu,;t t
+s,@build_vendor@,$build_vendor,;t t
+s,@build_os@,$build_os,;t t
+s,@host@,$host,;t t
+s,@host_cpu@,$host_cpu,;t t
+s,@host_vendor@,$host_vendor,;t t
+s,@host_os@,$host_os,;t t
+s,@LN_S@,$LN_S,;t t
+s,@ECHO@,$ECHO,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@STRIP@,$STRIP,;t t
+s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t
+s,@LIBTOOL@,$LIBTOOL,;t t
+s,@PERL@,$PERL,;t t
+s,@SH@,$SH,;t t
+s,@MAINTAINER_MODE_TRUE@,$MAINTAINER_MODE_TRUE,;t t
+s,@MAINTAINER_MODE_FALSE@,$MAINTAINER_MODE_FALSE,;t t
+s,@MAINT@,$MAINT,;t t
+s,@LIBICONV@,$LIBICONV,;t t
+s,@LTLIBICONV@,$LTLIBICONV,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+	cat >$tmp/stdin
+	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+				     sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+	 # Absolute (can't be DOS-style, as IFS=:)
+	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 echo "$f";;
+      *) # Relative
+	 if test -f "$f"; then
+	   # Build tree
+	   echo "$f"
+	 elif test -f "$srcdir/$f"; then
+	   # Source tree
+	   echo "$srcdir/$f"
+	 else
+	   # /dev/null tree
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([	 ]*\)#\([	 ]*define[	 ][	 ]*\)'
+ac_dB='[	 ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([	 ]*\)#\([	 ]*\)undef\([	 ][	 ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+	cat >$tmp/stdin
+	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+	 # Absolute (can't be DOS-style, as IFS=:)
+	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 # Do quote $f, to prevent DOS paths from being IFS'd.
+	 echo "$f";;
+      *) # Relative
+	 if test -f "$f"; then
+	   # Build tree
+	   echo "$f"
+	 elif test -f "$srcdir/$f"; then
+	   # Source tree
+	   echo "$srcdir/$f"
+	 else
+	   # /dev/null tree
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[	 ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*\)\(([^)]*)\)[	 ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[	 ]*#[	 ]*undef[	 ][	 ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if grep "^[	 ]*#[	 ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[	 ]*#[	 ]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo '  fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[	 ]*#[	 ]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+      { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
Index: /indexers/branches/3.03a/packages/unac/configure.ac
===================================================================
--- /indexers/branches/3.03a/packages/unac/configure.ac	(revision 14757)
+++ /indexers/branches/3.03a/packages/unac/configure.ac	(revision 14757)
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2000, 2001, 2002 Loic Dachary <loic@senga.org>
+#
+# 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 of the License, 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 program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+AC_INIT(config.h.in)
+VERSION=`cat .version`
+AC_SUBST(VERSION)
+AC_PREREQ(2.13)
+
+AC_CONFIG_HEADER(config.h)
+
+AC_PROG_MAKE_SET
+
+dnl
+dnl Unicode version used by unac, as published at http://www.unicode.org/Public/
+dnl
+UNICODE_VERSION=3.2.0
+AC_SUBST(UNICODE_VERSION)
+
+AC_PROG_CC
+AC_AIX
+AC_COMPILE_WARNINGS
+
+AC_PROG_LIBTOOL
+
+AC_PATH_PROG(PERL, perl, /usr/bin/perl)
+AC_PATH_PROG(SH, sh, /bin/sh)
+
+AM_MAINTAINER_MODE
+
+AM_ICONV
+
+#AC_CHECK_FUNCS(iconv_open,,AC_MSG_ERROR([
+#iconv_open not found try to install replacement from
+#http://www.gnu.org/software/libiconv/
+#ftp://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.8.tar.gz]))
+
+AC_CHECK_FUNCS(vsnprintf)
+
+AC_OUTPUT(Makefile)
Index: /indexers/branches/3.03a/packages/unac/iconv.h
===================================================================
--- /indexers/branches/3.03a/packages/unac/iconv.h	(revision 14757)
+++ /indexers/branches/3.03a/packages/unac/iconv.h	(revision 14757)
@@ -0,0 +1,131 @@
+/* Copyright (C) 1999-2003 Free Software Foundation, Inc.
+   This file is part of the GNU LIBICONV Library.
+
+   The GNU LIBICONV Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either version 2
+   of the License, or (at your option) any later version.
+
+   The GNU LIBICONV Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU LIBICONV Library; see the file COPYING.LIB.
+   If not, write to the Free Software Foundation, Inc., 59 Temple Place -
+   Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* When installed, this file is called "iconv.h". */
+
+#ifndef _LIBICONV_H
+#define _LIBICONV_H
+
+#define _LIBICONV_VERSION 0x0109    /* version number: (major<<8) + minor */
+extern int _libiconv_version;       /* Likewise */
+
+/* We would like to #include any system header file which could define
+   iconv_t, 1. in order to eliminate the risk that the user gets compilation
+   errors because some other system header file includes /usr/include/iconv.h
+   which defines iconv_t or declares iconv after this file, 2. when compiling
+   for LIBICONV_PLUG, we need the proper iconv_t type in order to produce
+   binary compatible code.
+   But gcc's #include_next is not portable. Thus, once libiconv's iconv.h
+   has been installed in /usr/local/include, there is no way any more to
+   include the original /usr/include/iconv.h. We simply have to get away
+   without it.
+   Ad 1. The risk that a system header file does
+   #include "iconv.h"  or  #include_next "iconv.h"
+   is small. They all do #include <iconv.h>.
+   Ad 2. The iconv_t type is a pointer type in all cases I have seen. (It
+   has to be a scalar type because (iconv_t)(-1) is a possible return value
+   from iconv_open().) */
+
+/* Define iconv_t ourselves. */
+#undef iconv_t
+#define iconv_t libiconv_t
+typedef void* iconv_t;
+
+/* Get size_t declaration. */
+#include <stddef.h>
+
+/* Get errno declaration and values. */
+#include <errno.h>
+/* Some systems, like SunOS 4, don't have EILSEQ. Some systems, like BSD/OS,
+   have EILSEQ in a different header.  On these systems, define EILSEQ
+   ourselves. */
+#ifndef EILSEQ
+#define EILSEQ @EILSEQ@
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Allocates descriptor for code conversion from encoding `fromcode' to
+   encoding `tocode'. */
+#ifndef LIBICONV_PLUG
+#define iconv_open libiconv_open
+#endif
+extern iconv_t iconv_open (const char* tocode, const char* fromcode);
+
+/* Converts, using conversion descriptor `cd', at most `*inbytesleft' bytes
+   starting at `*inbuf', writing at most `*outbytesleft' bytes starting at
+   `*outbuf'.
+   Decrements `*inbytesleft' and increments `*inbuf' by the same amount.
+   Decrements `*outbytesleft' and increments `*outbuf' by the same amount. */
+#ifndef LIBICONV_PLUG
+#define iconv libiconv
+#endif
+extern size_t iconv (iconv_t cd, const char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);
+
+/* Frees resources allocated for conversion descriptor `cd'. */
+#ifndef LIBICONV_PLUG
+#define iconv_close libiconv_close
+#endif
+extern int iconv_close (iconv_t cd);
+
+
+#ifndef LIBICONV_PLUG
+
+/* Nonstandard extensions. */
+
+/* Control of attributes. */
+#define iconvctl libiconvctl
+extern int iconvctl (iconv_t cd, int request, void* argument);
+
+/* Requests for iconvctl. */
+#define ICONV_TRIVIALP            0  /* int *argument */
+#define ICONV_GET_TRANSLITERATE   1  /* int *argument */
+#define ICONV_SET_TRANSLITERATE   2  /* const int *argument */
+#define ICONV_GET_DISCARD_ILSEQ   3  /* int *argument */
+#define ICONV_SET_DISCARD_ILSEQ   4  /* const int *argument */
+
+/* Listing of locale independent encodings. */
+#define iconvlist libiconvlist
+extern void iconvlist (int (*do_one) (unsigned int namescount,
+                                      const char * const * names,
+                                      void* data),
+                       void* data);
+
+/* Support for relocatable packages.  */
+
+/* Sets the original and the current installation prefix of the package.
+   Relocation simply replaces a pathname starting with the original prefix
+   by the corresponding pathname with the current prefix instead.  Both
+   prefixes should be directory names without trailing slash (i.e. use ""
+   instead of "/").  */
+extern void libiconv_set_relocation_prefix (const char *orig_prefix,
+					    const char *curr_prefix);
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _LIBICONV_H */
Index: /indexers/branches/3.03a/packages/unac/unac.c
===================================================================
--- /indexers/branches/3.03a/packages/unac/unac.c	(revision 14757)
+++ /indexers/branches/3.03a/packages/unac/unac.c	(revision 14757)
@@ -0,0 +1,12843 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Loic Dachary <loic@senga.org>
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+/*
+ * If configure.in has not defined this symbol, assume const. It
+ * does not harm much: a warning will be issued during compilation.
+ */
+#ifndef ICONV_CONST
+#define ICONV_CONST
+#endif /* ICONV_CONST */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iconv.h>
+#include <errno.h>
+#ifdef HAVE_VSNPRINTF
+#include <stdio.h>
+#include <stdarg.h>
+#endif /* HAVE_VSNPRINTF */
+
+#include "unac.h"
+
+/* Generated by builder. Do not modify. Start tables */
+/*
+ * 00A0 NO-BREAK SPACE
+ * 	0020 SPACE
+ * 00A8 DIAERESIS
+ * 	0020 SPACE
+ * 00AA FEMININE ORDINAL INDICATOR
+ * 	0061 LATIN SMALL LETTER A
+ * 00AF MACRON
+ * 	0020 SPACE
+ * 00B2 SUPERSCRIPT TWO
+ * 	0032 DIGIT TWO
+ * 00B3 SUPERSCRIPT THREE
+ * 	0033 DIGIT THREE
+ * 00B4 ACUTE ACCENT
+ * 	0020 SPACE
+ * 00B5 MICRO SIGN
+ * 	03BC GREEK SMALL LETTER MU
+ * 00B8 CEDILLA
+ * 	0020 SPACE
+ * 00B9 SUPERSCRIPT ONE
+ * 	0031 DIGIT ONE
+ * 00BA MASCULINE ORDINAL INDICATOR
+ * 	006F LATIN SMALL LETTER O
+ * 00BC VULGAR FRACTION ONE QUARTER
+ * 	0031 DIGIT ONE
+ * 	2044 FRACTION SLASH
+ * 	0034 DIGIT FOUR
+ * 00BD VULGAR FRACTION ONE HALF
+ * 	0031 DIGIT ONE
+ * 	2044 FRACTION SLASH
+ * 	0032 DIGIT TWO
+ * 00BE VULGAR FRACTION THREE QUARTERS
+ * 	0033 DIGIT THREE
+ * 	2044 FRACTION SLASH
+ * 	0034 DIGIT FOUR
+ * 00C0 LATIN CAPITAL LETTER A WITH GRAVE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 00C1 LATIN CAPITAL LETTER A WITH ACUTE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+ * 	0041 LATIN CAPITAL LETTER A
+ * 00C3 LATIN CAPITAL LETTER A WITH TILDE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 00C4 LATIN CAPITAL LETTER A WITH DIAERESIS
+ * 	0041 LATIN CAPITAL LETTER A
+ * 00C5 LATIN CAPITAL LETTER A WITH RING ABOVE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 00C6 LATIN CAPITAL LETTER AE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 	0045 LATIN CAPITAL LETTER E
+ * 00C7 LATIN CAPITAL LETTER C WITH CEDILLA
+ * 	0043 LATIN CAPITAL LETTER C
+ * 00C8 LATIN CAPITAL LETTER E WITH GRAVE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 00C9 LATIN CAPITAL LETTER E WITH ACUTE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+ * 	0045 LATIN CAPITAL LETTER E
+ * 00CB LATIN CAPITAL LETTER E WITH DIAERESIS
+ * 	0045 LATIN CAPITAL LETTER E
+ * 00CC LATIN CAPITAL LETTER I WITH GRAVE
+ * 	0049 LATIN CAPITAL LETTER I
+ * 00CD LATIN CAPITAL LETTER I WITH ACUTE
+ * 	0049 LATIN CAPITAL LETTER I
+ * 00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+ * 	0049 LATIN CAPITAL LETTER I
+ * 00CF LATIN CAPITAL LETTER I WITH DIAERESIS
+ * 	0049 LATIN CAPITAL LETTER I
+ * 00D1 LATIN CAPITAL LETTER N WITH TILDE
+ * 	004E LATIN CAPITAL LETTER N
+ * 00D2 LATIN CAPITAL LETTER O WITH GRAVE
+ * 	004F LATIN CAPITAL LETTER O
+ * 00D3 LATIN CAPITAL LETTER O WITH ACUTE
+ * 	004F LATIN CAPITAL LETTER O
+ * 00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+ * 	004F LATIN CAPITAL LETTER O
+ * 00D5 LATIN CAPITAL LETTER O WITH TILDE
+ * 	004F LATIN CAPITAL LETTER O
+ * 00D6 LATIN CAPITAL LETTER O WITH DIAERESIS
+ * 	004F LATIN CAPITAL LETTER O
+ * 00D8 LATIN CAPITAL LETTER O WITH STROKE
+ * 	004F LATIN CAPITAL LETTER O
+ * 00D9 LATIN CAPITAL LETTER U WITH GRAVE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 00DA LATIN CAPITAL LETTER U WITH ACUTE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+ * 	0055 LATIN CAPITAL LETTER U
+ * 00DC LATIN CAPITAL LETTER U WITH DIAERESIS
+ * 	0055 LATIN CAPITAL LETTER U
+ * 00DD LATIN CAPITAL LETTER Y WITH ACUTE
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 00E0 LATIN SMALL LETTER A WITH GRAVE
+ * 	0061 LATIN SMALL LETTER A
+ * 00E1 LATIN SMALL LETTER A WITH ACUTE
+ * 	0061 LATIN SMALL LETTER A
+ * 00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX
+ * 	0061 LATIN SMALL LETTER A
+ * 00E3 LATIN SMALL LETTER A WITH TILDE
+ * 	0061 LATIN SMALL LETTER A
+ * 00E4 LATIN SMALL LETTER A WITH DIAERESIS
+ * 	0061 LATIN SMALL LETTER A
+ * 00E5 LATIN SMALL LETTER A WITH RING ABOVE
+ * 	0061 LATIN SMALL LETTER A
+ * 00E6 LATIN SMALL LETTER AE
+ * 	0061 LATIN SMALL LETTER A
+ * 	0065 LATIN SMALL LETTER E
+ * 00E7 LATIN SMALL LETTER C WITH CEDILLA
+ * 	0063 LATIN SMALL LETTER C
+ * 00E8 LATIN SMALL LETTER E WITH GRAVE
+ * 	0065 LATIN SMALL LETTER E
+ * 00E9 LATIN SMALL LETTER E WITH ACUTE
+ * 	0065 LATIN SMALL LETTER E
+ * 00EA LATIN SMALL LETTER E WITH CIRCUMFLEX
+ * 	0065 LATIN SMALL LETTER E
+ * 00EB LATIN SMALL LETTER E WITH DIAERESIS
+ * 	0065 LATIN SMALL LETTER E
+ * 00EC LATIN SMALL LETTER I WITH GRAVE
+ * 	0069 LATIN SMALL LETTER I
+ * 00ED LATIN SMALL LETTER I WITH ACUTE
+ * 	0069 LATIN SMALL LETTER I
+ * 00EE LATIN SMALL LETTER I WITH CIRCUMFLEX
+ * 	0069 LATIN SMALL LETTER I
+ * 00EF LATIN SMALL LETTER I WITH DIAERESIS
+ * 	0069 LATIN SMALL LETTER I
+ * 00F1 LATIN SMALL LETTER N WITH TILDE
+ * 	006E LATIN SMALL LETTER N
+ * 00F2 LATIN SMALL LETTER O WITH GRAVE
+ * 	006F LATIN SMALL LETTER O
+ * 00F3 LATIN SMALL LETTER O WITH ACUTE
+ * 	006F LATIN SMALL LETTER O
+ * 00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX
+ * 	006F LATIN SMALL LETTER O
+ * 00F5 LATIN SMALL LETTER O WITH TILDE
+ * 	006F LATIN SMALL LETTER O
+ * 00F6 LATIN SMALL LETTER O WITH DIAERESIS
+ * 	006F LATIN SMALL LETTER O
+ * 00F8 LATIN SMALL LETTER O WITH STROKE
+ * 	006F LATIN SMALL LETTER O
+ * 00F9 LATIN SMALL LETTER U WITH GRAVE
+ * 	0075 LATIN SMALL LETTER U
+ * 00FA LATIN SMALL LETTER U WITH ACUTE
+ * 	0075 LATIN SMALL LETTER U
+ * 00FB LATIN SMALL LETTER U WITH CIRCUMFLEX
+ * 	0075 LATIN SMALL LETTER U
+ * 00FC LATIN SMALL LETTER U WITH DIAERESIS
+ * 	0075 LATIN SMALL LETTER U
+ * 00FD LATIN SMALL LETTER Y WITH ACUTE
+ * 	0079 LATIN SMALL LETTER Y
+ * 00FF LATIN SMALL LETTER Y WITH DIAERESIS
+ * 	0079 LATIN SMALL LETTER Y
+ * 0100 LATIN CAPITAL LETTER A WITH MACRON
+ * 	0041 LATIN CAPITAL LETTER A
+ * 0101 LATIN SMALL LETTER A WITH MACRON
+ * 	0061 LATIN SMALL LETTER A
+ * 0102 LATIN CAPITAL LETTER A WITH BREVE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 0103 LATIN SMALL LETTER A WITH BREVE
+ * 	0061 LATIN SMALL LETTER A
+ * 0104 LATIN CAPITAL LETTER A WITH OGONEK
+ * 	0041 LATIN CAPITAL LETTER A
+ * 0105 LATIN SMALL LETTER A WITH OGONEK
+ * 	0061 LATIN SMALL LETTER A
+ * 0106 LATIN CAPITAL LETTER C WITH ACUTE
+ * 	0043 LATIN CAPITAL LETTER C
+ * 0107 LATIN SMALL LETTER C WITH ACUTE
+ * 	0063 LATIN SMALL LETTER C
+ * 0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+ * 	0043 LATIN CAPITAL LETTER C
+ * 0109 LATIN SMALL LETTER C WITH CIRCUMFLEX
+ * 	0063 LATIN SMALL LETTER C
+ * 010A LATIN CAPITAL LETTER C WITH DOT ABOVE
+ * 	0043 LATIN CAPITAL LETTER C
+ * 010B LATIN SMALL LETTER C WITH DOT ABOVE
+ * 	0063 LATIN SMALL LETTER C
+ * 010C LATIN CAPITAL LETTER C WITH CARON
+ * 	0043 LATIN CAPITAL LETTER C
+ * 010D LATIN SMALL LETTER C WITH CARON
+ * 	0063 LATIN SMALL LETTER C
+ * 010E LATIN CAPITAL LETTER D WITH CARON
+ * 	0044 LATIN CAPITAL LETTER D
+ * 010F LATIN SMALL LETTER D WITH CARON
+ * 	0064 LATIN SMALL LETTER D
+ * 0112 LATIN CAPITAL LETTER E WITH MACRON
+ * 	0045 LATIN CAPITAL LETTER E
+ * 0113 LATIN SMALL LETTER E WITH MACRON
+ * 	0065 LATIN SMALL LETTER E
+ * 0114 LATIN CAPITAL LETTER E WITH BREVE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 0115 LATIN SMALL LETTER E WITH BREVE
+ * 	0065 LATIN SMALL LETTER E
+ * 0116 LATIN CAPITAL LETTER E WITH DOT ABOVE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 0117 LATIN SMALL LETTER E WITH DOT ABOVE
+ * 	0065 LATIN SMALL LETTER E
+ * 0118 LATIN CAPITAL LETTER E WITH OGONEK
+ * 	0045 LATIN CAPITAL LETTER E
+ * 0119 LATIN SMALL LETTER E WITH OGONEK
+ * 	0065 LATIN SMALL LETTER E
+ * 011A LATIN CAPITAL LETTER E WITH CARON
+ * 	0045 LATIN CAPITAL LETTER E
+ * 011B LATIN SMALL LETTER E WITH CARON
+ * 	0065 LATIN SMALL LETTER E
+ * 011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+ * 	0047 LATIN CAPITAL LETTER G
+ * 011D LATIN SMALL LETTER G WITH CIRCUMFLEX
+ * 	0067 LATIN SMALL LETTER G
+ * 011E LATIN CAPITAL LETTER G WITH BREVE
+ * 	0047 LATIN CAPITAL LETTER G
+ * 011F LATIN SMALL LETTER G WITH BREVE
+ * 	0067 LATIN SMALL LETTER G
+ * 0120 LATIN CAPITAL LETTER G WITH DOT ABOVE
+ * 	0047 LATIN CAPITAL LETTER G
+ * 0121 LATIN SMALL LETTER G WITH DOT ABOVE
+ * 	0067 LATIN SMALL LETTER G
+ * 0122 LATIN CAPITAL LETTER G WITH CEDILLA
+ * 	0047 LATIN CAPITAL LETTER G
+ * 0123 LATIN SMALL LETTER G WITH CEDILLA
+ * 	0067 LATIN SMALL LETTER G
+ * 0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+ * 	0048 LATIN CAPITAL LETTER H
+ * 0125 LATIN SMALL LETTER H WITH CIRCUMFLEX
+ * 	0068 LATIN SMALL LETTER H
+ * 0128 LATIN CAPITAL LETTER I WITH TILDE
+ * 	0049 LATIN CAPITAL LETTER I
+ * 0129 LATIN SMALL LETTER I WITH TILDE
+ * 	0069 LATIN SMALL LETTER I
+ * 012A LATIN CAPITAL LETTER I WITH MACRON
+ * 	0049 LATIN CAPITAL LETTER I
+ * 012B LATIN SMALL LETTER I WITH MACRON
+ * 	0069 LATIN SMALL LETTER I
+ * 012C LATIN CAPITAL LETTER I WITH BREVE
+ * 	0049 LATIN CAPITAL LETTER I
+ * 012D LATIN SMALL LETTER I WITH BREVE
+ * 	0069 LATIN SMALL LETTER I
+ * 012E LATIN CAPITAL LETTER I WITH OGONEK
+ * 	0049 LATIN CAPITAL LETTER I
+ * 012F LATIN SMALL LETTER I WITH OGONEK
+ * 	0069 LATIN SMALL LETTER I
+ * 0130 LATIN CAPITAL LETTER I WITH DOT ABOVE
+ * 	0049 LATIN CAPITAL LETTER I
+ * 0132 LATIN CAPITAL LIGATURE IJ
+ * 	0049 LATIN CAPITAL LETTER I
+ * 	004A LATIN CAPITAL LETTER J
+ * 0133 LATIN SMALL LIGATURE IJ
+ * 	0069 LATIN SMALL LETTER I
+ * 	006A LATIN SMALL LETTER J
+ * 0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+ * 	004A LATIN CAPITAL LETTER J
+ * 0135 LATIN SMALL LETTER J WITH CIRCUMFLEX
+ * 	006A LATIN SMALL LETTER J
+ * 0136 LATIN CAPITAL LETTER K WITH CEDILLA
+ * 	004B LATIN CAPITAL LETTER K
+ * 0137 LATIN SMALL LETTER K WITH CEDILLA
+ * 	006B LATIN SMALL LETTER K
+ * 0139 LATIN CAPITAL LETTER L WITH ACUTE
+ * 	004C LATIN CAPITAL LETTER L
+ * 013A LATIN SMALL LETTER L WITH ACUTE
+ * 	006C LATIN SMALL LETTER L
+ * 013B LATIN CAPITAL LETTER L WITH CEDILLA
+ * 	004C LATIN CAPITAL LETTER L
+ * 013C LATIN SMALL LETTER L WITH CEDILLA
+ * 	006C LATIN SMALL LETTER L
+ * 013D LATIN CAPITAL LETTER L WITH CARON
+ * 	004C LATIN CAPITAL LETTER L
+ * 013E LATIN SMALL LETTER L WITH CARON
+ * 	006C LATIN SMALL LETTER L
+ * 013F LATIN CAPITAL LETTER L WITH MIDDLE DOT
+ * 	004C LATIN CAPITAL LETTER L
+ * 	00B7 MIDDLE DOT
+ * 0140 LATIN SMALL LETTER L WITH MIDDLE DOT
+ * 	006C LATIN SMALL LETTER L
+ * 	00B7 MIDDLE DOT
+ * 0143 LATIN CAPITAL LETTER N WITH ACUTE
+ * 	004E LATIN CAPITAL LETTER N
+ * 0144 LATIN SMALL LETTER N WITH ACUTE
+ * 	006E LATIN SMALL LETTER N
+ * 0145 LATIN CAPITAL LETTER N WITH CEDILLA
+ * 	004E LATIN CAPITAL LETTER N
+ * 0146 LATIN SMALL LETTER N WITH CEDILLA
+ * 	006E LATIN SMALL LETTER N
+ * 0147 LATIN CAPITAL LETTER N WITH CARON
+ * 	004E LATIN CAPITAL LETTER N
+ * 0148 LATIN SMALL LETTER N WITH CARON
+ * 	006E LATIN SMALL LETTER N
+ * 0149 LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+ * 	02BC MODIFIER LETTER APOSTROPHE
+ * 	006E LATIN SMALL LETTER N
+ * 014C LATIN CAPITAL LETTER O WITH MACRON
+ * 	004F LATIN CAPITAL LETTER O
+ * 014D LATIN SMALL LETTER O WITH MACRON
+ * 	006F LATIN SMALL LETTER O
+ * 014E LATIN CAPITAL LETTER O WITH BREVE
+ * 	004F LATIN CAPITAL LETTER O
+ * 014F LATIN SMALL LETTER O WITH BREVE
+ * 	006F LATIN SMALL LETTER O
+ * 0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+ * 	004F LATIN CAPITAL LETTER O
+ * 0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE
+ * 	006F LATIN SMALL LETTER O
+ * 0154 LATIN CAPITAL LETTER R WITH ACUTE
+ * 	0052 LATIN CAPITAL LETTER R
+ * 0155 LATIN SMALL LETTER R WITH ACUTE
+ * 	0072 LATIN SMALL LETTER R
+ * 0156 LATIN CAPITAL LETTER R WITH CEDILLA
+ * 	0052 LATIN CAPITAL LETTER R
+ * 0157 LATIN SMALL LETTER R WITH CEDILLA
+ * 	0072 LATIN SMALL LETTER R
+ * 0158 LATIN CAPITAL LETTER R WITH CARON
+ * 	0052 LATIN CAPITAL LETTER R
+ * 0159 LATIN SMALL LETTER R WITH CARON
+ * 	0072 LATIN SMALL LETTER R
+ * 015A LATIN CAPITAL LETTER S WITH ACUTE
+ * 	0053 LATIN CAPITAL LETTER S
+ * 015B LATIN SMALL LETTER S WITH ACUTE
+ * 	0073 LATIN SMALL LETTER S
+ * 015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+ * 	0053 LATIN CAPITAL LETTER S
+ * 015D LATIN SMALL LETTER S WITH CIRCUMFLEX
+ * 	0073 LATIN SMALL LETTER S
+ * 015E LATIN CAPITAL LETTER S WITH CEDILLA
+ * 	0053 LATIN CAPITAL LETTER S
+ * 015F LATIN SMALL LETTER S WITH CEDILLA
+ * 	0073 LATIN SMALL LETTER S
+ * 0160 LATIN CAPITAL LETTER S WITH CARON
+ * 	0053 LATIN CAPITAL LETTER S
+ * 0161 LATIN SMALL LETTER S WITH CARON
+ * 	0073 LATIN SMALL LETTER S
+ * 0162 LATIN CAPITAL LETTER T WITH CEDILLA
+ * 	0054 LATIN CAPITAL LETTER T
+ * 0163 LATIN SMALL LETTER T WITH CEDILLA
+ * 	0074 LATIN SMALL LETTER T
+ * 0164 LATIN CAPITAL LETTER T WITH CARON
+ * 	0054 LATIN CAPITAL LETTER T
+ * 0165 LATIN SMALL LETTER T WITH CARON
+ * 	0074 LATIN SMALL LETTER T
+ * 0168 LATIN CAPITAL LETTER U WITH TILDE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 0169 LATIN SMALL LETTER U WITH TILDE
+ * 	0075 LATIN SMALL LETTER U
+ * 016A LATIN CAPITAL LETTER U WITH MACRON
+ * 	0055 LATIN CAPITAL LETTER U
+ * 016B LATIN SMALL LETTER U WITH MACRON
+ * 	0075 LATIN SMALL LETTER U
+ * 016C LATIN CAPITAL LETTER U WITH BREVE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 016D LATIN SMALL LETTER U WITH BREVE
+ * 	0075 LATIN SMALL LETTER U
+ * 016E LATIN CAPITAL LETTER U WITH RING ABOVE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 016F LATIN SMALL LETTER U WITH RING ABOVE
+ * 	0075 LATIN SMALL LETTER U
+ * 0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE
+ * 	0075 LATIN SMALL LETTER U
+ * 0172 LATIN CAPITAL LETTER U WITH OGONEK
+ * 	0055 LATIN CAPITAL LETTER U
+ * 0173 LATIN SMALL LETTER U WITH OGONEK
+ * 	0075 LATIN SMALL LETTER U
+ * 0174 LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+ * 	0057 LATIN CAPITAL LETTER W
+ * 0175 LATIN SMALL LETTER W WITH CIRCUMFLEX
+ * 	0077 LATIN SMALL LETTER W
+ * 0176 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 0177 LATIN SMALL LETTER Y WITH CIRCUMFLEX
+ * 	0079 LATIN SMALL LETTER Y
+ * 0178 LATIN CAPITAL LETTER Y WITH DIAERESIS
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 0179 LATIN CAPITAL LETTER Z WITH ACUTE
+ * 	005A LATIN CAPITAL LETTER Z
+ * 017A LATIN SMALL LETTER Z WITH ACUTE
+ * 	007A LATIN SMALL LETTER Z
+ * 017B LATIN CAPITAL LETTER Z WITH DOT ABOVE
+ * 	005A LATIN CAPITAL LETTER Z
+ * 017C LATIN SMALL LETTER Z WITH DOT ABOVE
+ * 	007A LATIN SMALL LETTER Z
+ * 017D LATIN CAPITAL LETTER Z WITH CARON
+ * 	005A LATIN CAPITAL LETTER Z
+ * 017E LATIN SMALL LETTER Z WITH CARON
+ * 	007A LATIN SMALL LETTER Z
+ * 017F LATIN SMALL LETTER LONG S
+ * 	0073 LATIN SMALL LETTER S
+ * 01A0 LATIN CAPITAL LETTER O WITH HORN
+ * 	004F LATIN CAPITAL LETTER O
+ * 01A1 LATIN SMALL LETTER O WITH HORN
+ * 	006F LATIN SMALL LETTER O
+ * 01AF LATIN CAPITAL LETTER U WITH HORN
+ * 	0055 LATIN CAPITAL LETTER U
+ * 01B0 LATIN SMALL LETTER U WITH HORN
+ * 	0075 LATIN SMALL LETTER U
+ * 01C4 LATIN CAPITAL LETTER DZ WITH CARON
+ * 	0044 LATIN CAPITAL LETTER D
+ * 	005A LATIN CAPITAL LETTER Z
+ * 01C5 LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON
+ * 	0044 LATIN CAPITAL LETTER D
+ * 	007A LATIN SMALL LETTER Z
+ * 01C6 LATIN SMALL LETTER DZ WITH CARON
+ * 	0064 LATIN SMALL LETTER D
+ * 	007A LATIN SMALL LETTER Z
+ * 01C7 LATIN CAPITAL LETTER LJ
+ * 	004C LATIN CAPITAL LETTER L
+ * 	004A LATIN CAPITAL LETTER J
+ * 01C8 LATIN CAPITAL LETTER L WITH SMALL LETTER J
+ * 	004C LATIN CAPITAL LETTER L
+ * 	006A LATIN SMALL LETTER J
+ * 01C9 LATIN SMALL LETTER LJ
+ * 	006C LATIN SMALL LETTER L
+ * 	006A LATIN SMALL LETTER J
+ * 01CA LATIN CAPITAL LETTER NJ
+ * 	004E LATIN CAPITAL LETTER N
+ * 	004A LATIN CAPITAL LETTER J
+ * 01CB LATIN CAPITAL LETTER N WITH SMALL LETTER J
+ * 	004E LATIN CAPITAL LETTER N
+ * 	006A LATIN SMALL LETTER J
+ * 01CC LATIN SMALL LETTER NJ
+ * 	006E LATIN SMALL LETTER N
+ * 	006A LATIN SMALL LETTER J
+ * 01CD LATIN CAPITAL LETTER A WITH CARON
+ * 	0041 LATIN CAPITAL LETTER A
+ * 01CE LATIN SMALL LETTER A WITH CARON
+ * 	0061 LATIN SMALL LETTER A
+ * 01CF LATIN CAPITAL LETTER I WITH CARON
+ * 	0049 LATIN CAPITAL LETTER I
+ * 01D0 LATIN SMALL LETTER I WITH CARON
+ * 	0069 LATIN SMALL LETTER I
+ * 01D1 LATIN CAPITAL LETTER O WITH CARON
+ * 	004F LATIN CAPITAL LETTER O
+ * 01D2 LATIN SMALL LETTER O WITH CARON
+ * 	006F LATIN SMALL LETTER O
+ * 01D3 LATIN CAPITAL LETTER U WITH CARON
+ * 	0055 LATIN CAPITAL LETTER U
+ * 01D4 LATIN SMALL LETTER U WITH CARON
+ * 	0075 LATIN SMALL LETTER U
+ * 01D5 LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
+ * 	0055 LATIN CAPITAL LETTER U
+ * 01D6 LATIN SMALL LETTER U WITH DIAERESIS AND MACRON
+ * 	0075 LATIN SMALL LETTER U
+ * 01D7 LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 01D8 LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE
+ * 	0075 LATIN SMALL LETTER U
+ * 01D9 LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
+ * 	0055 LATIN CAPITAL LETTER U
+ * 01DA LATIN SMALL LETTER U WITH DIAERESIS AND CARON
+ * 	0075 LATIN SMALL LETTER U
+ * 01DB LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 01DC LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE
+ * 	0075 LATIN SMALL LETTER U
+ * 01DE LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON
+ * 	0041 LATIN CAPITAL LETTER A
+ * 01DF LATIN SMALL LETTER A WITH DIAERESIS AND MACRON
+ * 	0061 LATIN SMALL LETTER A
+ * 01E0 LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON
+ * 	0041 LATIN CAPITAL LETTER A
+ * 01E1 LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON
+ * 	0061 LATIN SMALL LETTER A
+ * 01E2 LATIN CAPITAL LETTER AE WITH MACRON
+ * 	0041 LATIN CAPITAL LETTER A
+ * 	0045 LATIN CAPITAL LETTER E
+ * 01E3 LATIN SMALL LETTER AE WITH MACRON
+ * 	0061 LATIN SMALL LETTER A
+ * 	0065 LATIN SMALL LETTER E
+ * 01E6 LATIN CAPITAL LETTER G WITH CARON
+ * 	0047 LATIN CAPITAL LETTER G
+ * 01E7 LATIN SMALL LETTER G WITH CARON
+ * 	0067 LATIN SMALL LETTER G
+ * 01E8 LATIN CAPITAL LETTER K WITH CARON
+ * 	004B LATIN CAPITAL LETTER K
+ * 01E9 LATIN SMALL LETTER K WITH CARON
+ * 	006B LATIN SMALL LETTER K
+ * 01EA LATIN CAPITAL LETTER O WITH OGONEK
+ * 	004F LATIN CAPITAL LETTER O
+ * 01EB LATIN SMALL LETTER O WITH OGONEK
+ * 	006F LATIN SMALL LETTER O
+ * 01EC LATIN CAPITAL LETTER O WITH OGONEK AND MACRON
+ * 	004F LATIN CAPITAL LETTER O
+ * 01ED LATIN SMALL LETTER O WITH OGONEK AND MACRON
+ * 	006F LATIN SMALL LETTER O
+ * 01EE LATIN CAPITAL LETTER EZH WITH CARON
+ * 	01B7 LATIN CAPITAL LETTER EZH
+ * 01EF LATIN SMALL LETTER EZH WITH CARON
+ * 	0292 LATIN SMALL LETTER EZH
+ * 01F0 LATIN SMALL LETTER J WITH CARON
+ * 	006A LATIN SMALL LETTER J
+ * 01F1 LATIN CAPITAL LETTER DZ
+ * 	0044 LATIN CAPITAL LETTER D
+ * 	005A LATIN CAPITAL LETTER Z
+ * 01F2 LATIN CAPITAL LETTER D WITH SMALL LETTER Z
+ * 	0044 LATIN CAPITAL LETTER D
+ * 	007A LATIN SMALL LETTER Z
+ * 01F3 LATIN SMALL LETTER DZ
+ * 	0064 LATIN SMALL LETTER D
+ * 	007A LATIN SMALL LETTER Z
+ * 01F4 LATIN CAPITAL LETTER G WITH ACUTE
+ * 	0047 LATIN CAPITAL LETTER G
+ * 01F5 LATIN SMALL LETTER G WITH ACUTE
+ * 	0067 LATIN SMALL LETTER G
+ * 01F8 LATIN CAPITAL LETTER N WITH GRAVE
+ * 	004E LATIN CAPITAL LETTER N
+ * 01F9 LATIN SMALL LETTER N WITH GRAVE
+ * 	006E LATIN SMALL LETTER N
+ * 01FA LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 01FB LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE
+ * 	0061 LATIN SMALL LETTER A
+ * 01FC LATIN CAPITAL LETTER AE WITH ACUTE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 	0045 LATIN CAPITAL LETTER E
+ * 01FD LATIN SMALL LETTER AE WITH ACUTE
+ * 	0061 LATIN SMALL LETTER A
+ * 	0065 LATIN SMALL LETTER E
+ * 01FE LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
+ * 	004F LATIN CAPITAL LETTER O
+ * 01FF LATIN SMALL LETTER O WITH STROKE AND ACUTE
+ * 	006F LATIN SMALL LETTER O
+ * 0200 LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 0201 LATIN SMALL LETTER A WITH DOUBLE GRAVE
+ * 	0061 LATIN SMALL LETTER A
+ * 0202 LATIN CAPITAL LETTER A WITH INVERTED BREVE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 0203 LATIN SMALL LETTER A WITH INVERTED BREVE
+ * 	0061 LATIN SMALL LETTER A
+ * 0204 LATIN CAPITAL LETTER E WITH DOUBLE GRAVE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 0205 LATIN SMALL LETTER E WITH DOUBLE GRAVE
+ * 	0065 LATIN SMALL LETTER E
+ * 0206 LATIN CAPITAL LETTER E WITH INVERTED BREVE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 0207 LATIN SMALL LETTER E WITH INVERTED BREVE
+ * 	0065 LATIN SMALL LETTER E
+ * 0208 LATIN CAPITAL LETTER I WITH DOUBLE GRAVE
+ * 	0049 LATIN CAPITAL LETTER I
+ * 0209 LATIN SMALL LETTER I WITH DOUBLE GRAVE
+ * 	0069 LATIN SMALL LETTER I
+ * 020A LATIN CAPITAL LETTER I WITH INVERTED BREVE
+ * 	0049 LATIN CAPITAL LETTER I
+ * 020B LATIN SMALL LETTER I WITH INVERTED BREVE
+ * 	0069 LATIN SMALL LETTER I
+ * 020C LATIN CAPITAL LETTER O WITH DOUBLE GRAVE
+ * 	004F LATIN CAPITAL LETTER O
+ * 020D LATIN SMALL LETTER O WITH DOUBLE GRAVE
+ * 	006F LATIN SMALL LETTER O
+ * 020E LATIN CAPITAL LETTER O WITH INVERTED BREVE
+ * 	004F LATIN CAPITAL LETTER O
+ * 020F LATIN SMALL LETTER O WITH INVERTED BREVE
+ * 	006F LATIN SMALL LETTER O
+ * 0210 LATIN CAPITAL LETTER R WITH DOUBLE GRAVE
+ * 	0052 LATIN CAPITAL LETTER R
+ * 0211 LATIN SMALL LETTER R WITH DOUBLE GRAVE
+ * 	0072 LATIN SMALL LETTER R
+ * 0212 LATIN CAPITAL LETTER R WITH INVERTED BREVE
+ * 	0052 LATIN CAPITAL LETTER R
+ * 0213 LATIN SMALL LETTER R WITH INVERTED BREVE
+ * 	0072 LATIN SMALL LETTER R
+ * 0214 LATIN CAPITAL LETTER U WITH DOUBLE GRAVE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 0215 LATIN SMALL LETTER U WITH DOUBLE GRAVE
+ * 	0075 LATIN SMALL LETTER U
+ * 0216 LATIN CAPITAL LETTER U WITH INVERTED BREVE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 0217 LATIN SMALL LETTER U WITH INVERTED BREVE
+ * 	0075 LATIN SMALL LETTER U
+ * 0218 LATIN CAPITAL LETTER S WITH COMMA BELOW
+ * 	0053 LATIN CAPITAL LETTER S
+ * 0219 LATIN SMALL LETTER S WITH COMMA BELOW
+ * 	0073 LATIN SMALL LETTER S
+ * 021A LATIN CAPITAL LETTER T WITH COMMA BELOW
+ * 	0054 LATIN CAPITAL LETTER T
+ * 021B LATIN SMALL LETTER T WITH COMMA BELOW
+ * 	0074 LATIN SMALL LETTER T
+ * 021E LATIN CAPITAL LETTER H WITH CARON
+ * 	0048 LATIN CAPITAL LETTER H
+ * 021F LATIN SMALL LETTER H WITH CARON
+ * 	0068 LATIN SMALL LETTER H
+ * 0226 LATIN CAPITAL LETTER A WITH DOT ABOVE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 0227 LATIN SMALL LETTER A WITH DOT ABOVE
+ * 	0061 LATIN SMALL LETTER A
+ * 0228 LATIN CAPITAL LETTER E WITH CEDILLA
+ * 	0045 LATIN CAPITAL LETTER E
+ * 0229 LATIN SMALL LETTER E WITH CEDILLA
+ * 	0065 LATIN SMALL LETTER E
+ * 022A LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON
+ * 	004F LATIN CAPITAL LETTER O
+ * 022B LATIN SMALL LETTER O WITH DIAERESIS AND MACRON
+ * 	006F LATIN SMALL LETTER O
+ * 022C LATIN CAPITAL LETTER O WITH TILDE AND MACRON
+ * 	004F LATIN CAPITAL LETTER O
+ * 022D LATIN SMALL LETTER O WITH TILDE AND MACRON
+ * 	006F LATIN SMALL LETTER O
+ * 022E LATIN CAPITAL LETTER O WITH DOT ABOVE
+ * 	004F LATIN CAPITAL LETTER O
+ * 022F LATIN SMALL LETTER O WITH DOT ABOVE
+ * 	006F LATIN SMALL LETTER O
+ * 0230 LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON
+ * 	004F LATIN CAPITAL LETTER O
+ * 0231 LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON
+ * 	006F LATIN SMALL LETTER O
+ * 0232 LATIN CAPITAL LETTER Y WITH MACRON
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 0233 LATIN SMALL LETTER Y WITH MACRON
+ * 	0079 LATIN SMALL LETTER Y
+ * 02B0 MODIFIER LETTER SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 02B1 MODIFIER LETTER SMALL H WITH HOOK
+ * 	0266 LATIN SMALL LETTER H WITH HOOK
+ * 02B2 MODIFIER LETTER SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 02B3 MODIFIER LETTER SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 02B4 MODIFIER LETTER SMALL TURNED R
+ * 	0279 LATIN SMALL LETTER TURNED R
+ * 02B5 MODIFIER LETTER SMALL TURNED R WITH HOOK
+ * 	027B LATIN SMALL LETTER TURNED R WITH HOOK
+ * 02B6 MODIFIER LETTER SMALL CAPITAL INVERTED R
+ * 	0281 LATIN LETTER SMALL CAPITAL INVERTED R
+ * 02B7 MODIFIER LETTER SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 02B8 MODIFIER LETTER SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 02D8 BREVE
+ * 	0020 SPACE
+ * 02D9 DOT ABOVE
+ * 	0020 SPACE
+ * 02DA RING ABOVE
+ * 	0020 SPACE
+ * 02DB OGONEK
+ * 	0020 SPACE
+ * 02DC SMALL TILDE
+ * 	0020 SPACE
+ * 02DD DOUBLE ACUTE ACCENT
+ * 	0020 SPACE
+ * 02E0 MODIFIER LETTER SMALL GAMMA
+ * 	0263 LATIN SMALL LETTER GAMMA
+ * 02E1 MODIFIER LETTER SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 02E2 MODIFIER LETTER SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 02E3 MODIFIER LETTER SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 02E4 MODIFIER LETTER SMALL REVERSED GLOTTAL STOP
+ * 	0295 LATIN LETTER PHARYNGEAL VOICED FRICATIVE
+ * 0374 GREEK NUMERAL SIGN
+ * 	02B9 MODIFIER LETTER PRIME
+ * 037A GREEK YPOGEGRAMMENI
+ * 	0020 SPACE
+ * 037E GREEK QUESTION MARK
+ * 	003B SEMICOLON
+ * 0384 GREEK TONOS
+ * 	0020 SPACE
+ * 0385 GREEK DIALYTIKA TONOS
+ * 	0020 SPACE
+ * 0386 GREEK CAPITAL LETTER ALPHA WITH TONOS
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 0387 GREEK ANO TELEIA
+ * 	00B7 MIDDLE DOT
+ * 0388 GREEK CAPITAL LETTER EPSILON WITH TONOS
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 0389 GREEK CAPITAL LETTER ETA WITH TONOS
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 038A GREEK CAPITAL LETTER IOTA WITH TONOS
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 038C GREEK CAPITAL LETTER OMICRON WITH TONOS
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 038E GREEK CAPITAL LETTER UPSILON WITH TONOS
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 038F GREEK CAPITAL LETTER OMEGA WITH TONOS
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 03AC GREEK SMALL LETTER ALPHA WITH TONOS
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 03AD GREEK SMALL LETTER EPSILON WITH TONOS
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 03AE GREEK SMALL LETTER ETA WITH TONOS
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 03AF GREEK SMALL LETTER IOTA WITH TONOS
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 03CC GREEK SMALL LETTER OMICRON WITH TONOS
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 03CD GREEK SMALL LETTER UPSILON WITH TONOS
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 03CE GREEK SMALL LETTER OMEGA WITH TONOS
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 03D0 GREEK BETA SYMBOL
+ * 	03B2 GREEK SMALL LETTER BETA
+ * 03D1 GREEK THETA SYMBOL
+ * 	03B8 GREEK SMALL LETTER THETA
+ * 03D2 GREEK UPSILON WITH HOOK SYMBOL
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 03D3 GREEK UPSILON WITH ACUTE AND HOOK SYMBOL
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 03D4 GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 03D5 GREEK PHI SYMBOL
+ * 	03C6 GREEK SMALL LETTER PHI
+ * 03D6 GREEK PI SYMBOL
+ * 	03C0 GREEK SMALL LETTER PI
+ * 03F0 GREEK KAPPA SYMBOL
+ * 	03BA GREEK SMALL LETTER KAPPA
+ * 03F1 GREEK RHO SYMBOL
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 03F2 GREEK LUNATE SIGMA SYMBOL
+ * 	03C2 GREEK SMALL LETTER FINAL SIGMA
+ * 03F4 GREEK CAPITAL THETA SYMBOL
+ * 	0398 GREEK CAPITAL LETTER THETA
+ * 03F5 GREEK LUNATE EPSILON SYMBOL
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 0400 CYRILLIC CAPITAL LETTER IE WITH GRAVE
+ * 	0415 CYRILLIC CAPITAL LETTER IE
+ * 0401 CYRILLIC CAPITAL LETTER IO
+ * 	0415 CYRILLIC CAPITAL LETTER IE
+ * 0403 CYRILLIC CAPITAL LETTER GJE
+ * 	0413 CYRILLIC CAPITAL LETTER GHE
+ * 0407 CYRILLIC CAPITAL LETTER YI
+ * 	0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+ * 040C CYRILLIC CAPITAL LETTER KJE
+ * 	041A CYRILLIC CAPITAL LETTER KA
+ * 040D CYRILLIC CAPITAL LETTER I WITH GRAVE
+ * 	0418 CYRILLIC CAPITAL LETTER I
+ * 040E CYRILLIC CAPITAL LETTER SHORT U
+ * 	0423 CYRILLIC CAPITAL LETTER U
+ * 0419 CYRILLIC CAPITAL LETTER SHORT I
+ * 	0418 CYRILLIC CAPITAL LETTER I
+ * 0439 CYRILLIC SMALL LETTER SHORT I
+ * 	0438 CYRILLIC SMALL LETTER I
+ * 0450 CYRILLIC SMALL LETTER IE WITH GRAVE
+ * 	0435 CYRILLIC SMALL LETTER IE
+ * 0451 CYRILLIC SMALL LETTER IO
+ * 	0435 CYRILLIC SMALL LETTER IE
+ * 0453 CYRILLIC SMALL LETTER GJE
+ * 	0433 CYRILLIC SMALL LETTER GHE
+ * 0457 CYRILLIC SMALL LETTER YI
+ * 	0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+ * 045C CYRILLIC SMALL LETTER KJE
+ * 	043A CYRILLIC SMALL LETTER KA
+ * 045D CYRILLIC SMALL LETTER I WITH GRAVE
+ * 	0438 CYRILLIC SMALL LETTER I
+ * 045E CYRILLIC SMALL LETTER SHORT U
+ * 	0443 CYRILLIC SMALL LETTER U
+ * 0476 CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+ * 	0474 CYRILLIC CAPITAL LETTER IZHITSA
+ * 0477 CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+ * 	0475 CYRILLIC SMALL LETTER IZHITSA
+ * 04C1 CYRILLIC CAPITAL LETTER ZHE WITH BREVE
+ * 	0416 CYRILLIC CAPITAL LETTER ZHE
+ * 04C2 CYRILLIC SMALL LETTER ZHE WITH BREVE
+ * 	0436 CYRILLIC SMALL LETTER ZHE
+ * 04D0 CYRILLIC CAPITAL LETTER A WITH BREVE
+ * 	0410 CYRILLIC CAPITAL LETTER A
+ * 04D1 CYRILLIC SMALL LETTER A WITH BREVE
+ * 	0430 CYRILLIC SMALL LETTER A
+ * 04D2 CYRILLIC CAPITAL LETTER A WITH DIAERESIS
+ * 	0410 CYRILLIC CAPITAL LETTER A
+ * 04D3 CYRILLIC SMALL LETTER A WITH DIAERESIS
+ * 	0430 CYRILLIC SMALL LETTER A
+ * 04D6 CYRILLIC CAPITAL LETTER IE WITH BREVE
+ * 	0415 CYRILLIC CAPITAL LETTER IE
+ * 04D7 CYRILLIC SMALL LETTER IE WITH BREVE
+ * 	0435 CYRILLIC SMALL LETTER IE
+ * 04DA CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS
+ * 	04D8 CYRILLIC CAPITAL LETTER SCHWA
+ * 04DB CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS
+ * 	04D9 CYRILLIC SMALL LETTER SCHWA
+ * 04DC CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS
+ * 	0416 CYRILLIC CAPITAL LETTER ZHE
+ * 04DD CYRILLIC SMALL LETTER ZHE WITH DIAERESIS
+ * 	0436 CYRILLIC SMALL LETTER ZHE
+ * 04DE CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS
+ * 	0417 CYRILLIC CAPITAL LETTER ZE
+ * 04DF CYRILLIC SMALL LETTER ZE WITH DIAERESIS
+ * 	0437 CYRILLIC SMALL LETTER ZE
+ * 04E2 CYRILLIC CAPITAL LETTER I WITH MACRON
+ * 	0418 CYRILLIC CAPITAL LETTER I
+ * 04E3 CYRILLIC SMALL LETTER I WITH MACRON
+ * 	0438 CYRILLIC SMALL LETTER I
+ * 04E4 CYRILLIC CAPITAL LETTER I WITH DIAERESIS
+ * 	0418 CYRILLIC CAPITAL LETTER I
+ * 04E5 CYRILLIC SMALL LETTER I WITH DIAERESIS
+ * 	0438 CYRILLIC SMALL LETTER I
+ * 04E6 CYRILLIC CAPITAL LETTER O WITH DIAERESIS
+ * 	041E CYRILLIC CAPITAL LETTER O
+ * 04E7 CYRILLIC SMALL LETTER O WITH DIAERESIS
+ * 	043E CYRILLIC SMALL LETTER O
+ * 04EA CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS
+ * 	04E8 CYRILLIC CAPITAL LETTER BARRED O
+ * 04EB CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS
+ * 	04E9 CYRILLIC SMALL LETTER BARRED O
+ * 04EC CYRILLIC CAPITAL LETTER E WITH DIAERESIS
+ * 	042D CYRILLIC CAPITAL LETTER E
+ * 04ED CYRILLIC SMALL LETTER E WITH DIAERESIS
+ * 	044D CYRILLIC SMALL LETTER E
+ * 04EE CYRILLIC CAPITAL LETTER U WITH MACRON
+ * 	0423 CYRILLIC CAPITAL LETTER U
+ * 04EF CYRILLIC SMALL LETTER U WITH MACRON
+ * 	0443 CYRILLIC SMALL LETTER U
+ * 04F0 CYRILLIC CAPITAL LETTER U WITH DIAERESIS
+ * 	0423 CYRILLIC CAPITAL LETTER U
+ * 04F1 CYRILLIC SMALL LETTER U WITH DIAERESIS
+ * 	0443 CYRILLIC SMALL LETTER U
+ * 04F2 CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE
+ * 	0423 CYRILLIC CAPITAL LETTER U
+ * 04F3 CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE
+ * 	0443 CYRILLIC SMALL LETTER U
+ * 04F4 CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS
+ * 	0427 CYRILLIC CAPITAL LETTER CHE
+ * 04F5 CYRILLIC SMALL LETTER CHE WITH DIAERESIS
+ * 	0447 CYRILLIC SMALL LETTER CHE
+ * 04F8 CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS
+ * 	042B CYRILLIC CAPITAL LETTER YERU
+ * 04F9 CYRILLIC SMALL LETTER YERU WITH DIAERESIS
+ * 	044B CYRILLIC SMALL LETTER YERU
+ * 0587 ARMENIAN SMALL LIGATURE ECH YIWN
+ * 	0565 ARMENIAN SMALL LETTER ECH
+ * 	0582 ARMENIAN SMALL LETTER YIWN
+ * 0622 ARABIC LETTER ALEF WITH MADDA ABOVE
+ * 	0627 ARABIC LETTER ALEF
+ * 0623 ARABIC LETTER ALEF WITH HAMZA ABOVE
+ * 	0627 ARABIC LETTER ALEF
+ * 0624 ARABIC LETTER WAW WITH HAMZA ABOVE
+ * 	0648 ARABIC LETTER WAW
+ * 0625 ARABIC LETTER ALEF WITH HAMZA BELOW
+ * 	0627 ARABIC LETTER ALEF
+ * 0626 ARABIC LETTER YEH WITH HAMZA ABOVE
+ * 	064A ARABIC LETTER YEH
+ * 0675 ARABIC LETTER HIGH HAMZA ALEF
+ * 	0627 ARABIC LETTER ALEF
+ * 	0674 ARABIC LETTER HIGH HAMZA
+ * 0676 ARABIC LETTER HIGH HAMZA WAW
+ * 	0648 ARABIC LETTER WAW
+ * 	0674 ARABIC LETTER HIGH HAMZA
+ * 0677 ARABIC LETTER U WITH HAMZA ABOVE
+ * 	06C7 ARABIC LETTER U
+ * 	0674 ARABIC LETTER HIGH HAMZA
+ * 0678 ARABIC LETTER HIGH HAMZA YEH
+ * 	064A ARABIC LETTER YEH
+ * 	0674 ARABIC LETTER HIGH HAMZA
+ * 06C0 ARABIC LETTER HEH WITH YEH ABOVE
+ * 	06D5 ARABIC LETTER AE
+ * 06C2 ARABIC LETTER HEH GOAL WITH HAMZA ABOVE
+ * 	06C1 ARABIC LETTER HEH GOAL
+ * 06D3 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
+ * 	06D2 ARABIC LETTER YEH BARREE
+ * 0929 DEVANAGARI LETTER NNNA
+ * 	0928 DEVANAGARI LETTER NA
+ * 0931 DEVANAGARI LETTER RRA
+ * 	0930 DEVANAGARI LETTER RA
+ * 0934 DEVANAGARI LETTER LLLA
+ * 	0933 DEVANAGARI LETTER LLA
+ * 0958 DEVANAGARI LETTER QA
+ * 	0915 DEVANAGARI LETTER KA
+ * 0959 DEVANAGARI LETTER KHHA
+ * 	0916 DEVANAGARI LETTER KHA
+ * 095A DEVANAGARI LETTER GHHA
+ * 	0917 DEVANAGARI LETTER GA
+ * 095B DEVANAGARI LETTER ZA
+ * 	091C DEVANAGARI LETTER JA
+ * 095C DEVANAGARI LETTER DDDHA
+ * 	0921 DEVANAGARI LETTER DDA
+ * 095D DEVANAGARI LETTER RHA
+ * 	0922 DEVANAGARI LETTER DDHA
+ * 095E DEVANAGARI LETTER FA
+ * 	092B DEVANAGARI LETTER PHA
+ * 095F DEVANAGARI LETTER YYA
+ * 	092F DEVANAGARI LETTER YA
+ * 09DC BENGALI LETTER RRA
+ * 	09A1 BENGALI LETTER DDA
+ * 09DD BENGALI LETTER RHA
+ * 	09A2 BENGALI LETTER DDHA
+ * 09DF BENGALI LETTER YYA
+ * 	09AF BENGALI LETTER YA
+ * 0A33 GURMUKHI LETTER LLA
+ * 	0A32 GURMUKHI LETTER LA
+ * 0A36 GURMUKHI LETTER SHA
+ * 	0A38 GURMUKHI LETTER SA
+ * 0A59 GURMUKHI LETTER KHHA
+ * 	0A16 GURMUKHI LETTER KHA
+ * 0A5A GURMUKHI LETTER GHHA
+ * 	0A17 GURMUKHI LETTER GA
+ * 0A5B GURMUKHI LETTER ZA
+ * 	0A1C GURMUKHI LETTER JA
+ * 0A5E GURMUKHI LETTER FA
+ * 	0A2B GURMUKHI LETTER PHA
+ * 0B5C ORIYA LETTER RRA
+ * 	0B21 ORIYA LETTER DDA
+ * 0B5D ORIYA LETTER RHA
+ * 	0B22 ORIYA LETTER DDHA
+ * 0B94 TAMIL LETTER AU
+ * 	0B92 TAMIL LETTER O
+ * 0E33 THAI CHARACTER SARA AM
+ * 	0E32 THAI CHARACTER SARA AA
+ * 0EB3 LAO VOWEL SIGN AM
+ * 	0EB2 LAO VOWEL SIGN AA
+ * 0EDC LAO HO NO
+ * 	0EAB LAO LETTER HO SUNG
+ * 	0E99 LAO LETTER NO
+ * 0EDD LAO HO MO
+ * 	0EAB LAO LETTER HO SUNG
+ * 	0EA1 LAO LETTER MO
+ * 0F0C TIBETAN MARK DELIMITER TSHEG BSTAR
+ * 	0F0B TIBETAN MARK INTERSYLLABIC TSHEG
+ * 0F43 TIBETAN LETTER GHA
+ * 	0F42 TIBETAN LETTER GA
+ * 0F4D TIBETAN LETTER DDHA
+ * 	0F4C TIBETAN LETTER DDA
+ * 0F52 TIBETAN LETTER DHA
+ * 	0F51 TIBETAN LETTER DA
+ * 0F57 TIBETAN LETTER BHA
+ * 	0F56 TIBETAN LETTER BA
+ * 0F5C TIBETAN LETTER DZHA
+ * 	0F5B TIBETAN LETTER DZA
+ * 0F69 TIBETAN LETTER KSSA
+ * 	0F40 TIBETAN LETTER KA
+ * 1026 MYANMAR LETTER UU
+ * 	1025 MYANMAR LETTER U
+ * 1D15E MUSICAL SYMBOL HALF NOTE
+ * 	1D157 MUSICAL SYMBOL VOID NOTEHEAD
+ * 1D15F MUSICAL SYMBOL QUARTER NOTE
+ * 	1D158 MUSICAL SYMBOL NOTEHEAD BLACK
+ * 1D160 MUSICAL SYMBOL EIGHTH NOTE
+ * 	1D158 MUSICAL SYMBOL NOTEHEAD BLACK
+ * 1D161 MUSICAL SYMBOL SIXTEENTH NOTE
+ * 	1D158 MUSICAL SYMBOL NOTEHEAD BLACK
+ * 1D162 MUSICAL SYMBOL THIRTY-SECOND NOTE
+ * 	1D158 MUSICAL SYMBOL NOTEHEAD BLACK
+ * 1D163 MUSICAL SYMBOL SIXTY-FOURTH NOTE
+ * 	1D158 MUSICAL SYMBOL NOTEHEAD BLACK
+ * 1D164 MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE
+ * 	1D158 MUSICAL SYMBOL NOTEHEAD BLACK
+ * 1D1BB MUSICAL SYMBOL MINIMA
+ * 	1D1B9 MUSICAL SYMBOL SEMIBREVIS WHITE
+ * 1D1BC MUSICAL SYMBOL MINIMA BLACK
+ * 	1D1BA MUSICAL SYMBOL SEMIBREVIS BLACK
+ * 1D1BD MUSICAL SYMBOL SEMIMINIMA WHITE
+ * 	1D1B9 MUSICAL SYMBOL SEMIBREVIS WHITE
+ * 1D1BE MUSICAL SYMBOL SEMIMINIMA BLACK
+ * 	1D1BA MUSICAL SYMBOL SEMIBREVIS BLACK
+ * 1D1BF MUSICAL SYMBOL FUSA WHITE
+ * 	1D1B9 MUSICAL SYMBOL SEMIBREVIS WHITE
+ * 1D1C0 MUSICAL SYMBOL FUSA BLACK
+ * 	1D1BA MUSICAL SYMBOL SEMIBREVIS BLACK
+ * 1D400 MATHEMATICAL BOLD CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D401 MATHEMATICAL BOLD CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1D402 MATHEMATICAL BOLD CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 1D403 MATHEMATICAL BOLD CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D404 MATHEMATICAL BOLD CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1D405 MATHEMATICAL BOLD CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1D406 MATHEMATICAL BOLD CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D407 MATHEMATICAL BOLD CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1D408 MATHEMATICAL BOLD CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1D409 MATHEMATICAL BOLD CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D40A MATHEMATICAL BOLD CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D40B MATHEMATICAL BOLD CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 1D40C MATHEMATICAL BOLD CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 1D40D MATHEMATICAL BOLD CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 1D40E MATHEMATICAL BOLD CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D40F MATHEMATICAL BOLD CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1D410 MATHEMATICAL BOLD CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 1D411 MATHEMATICAL BOLD CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1D412 MATHEMATICAL BOLD CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D413 MATHEMATICAL BOLD CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D414 MATHEMATICAL BOLD CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D415 MATHEMATICAL BOLD CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D416 MATHEMATICAL BOLD CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D417 MATHEMATICAL BOLD CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D418 MATHEMATICAL BOLD CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D419 MATHEMATICAL BOLD CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1D41A MATHEMATICAL BOLD SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D41B MATHEMATICAL BOLD SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D41C MATHEMATICAL BOLD SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D41D MATHEMATICAL BOLD SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D41E MATHEMATICAL BOLD SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 1D41F MATHEMATICAL BOLD SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D420 MATHEMATICAL BOLD SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 1D421 MATHEMATICAL BOLD SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 1D422 MATHEMATICAL BOLD SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D423 MATHEMATICAL BOLD SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D424 MATHEMATICAL BOLD SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D425 MATHEMATICAL BOLD SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 1D426 MATHEMATICAL BOLD SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D427 MATHEMATICAL BOLD SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D428 MATHEMATICAL BOLD SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 1D429 MATHEMATICAL BOLD SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D42A MATHEMATICAL BOLD SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D42B MATHEMATICAL BOLD SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D42C MATHEMATICAL BOLD SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D42D MATHEMATICAL BOLD SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D42E MATHEMATICAL BOLD SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D42F MATHEMATICAL BOLD SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D430 MATHEMATICAL BOLD SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D431 MATHEMATICAL BOLD SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D432 MATHEMATICAL BOLD SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D433 MATHEMATICAL BOLD SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D434 MATHEMATICAL ITALIC CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D435 MATHEMATICAL ITALIC CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1D436 MATHEMATICAL ITALIC CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 1D437 MATHEMATICAL ITALIC CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D438 MATHEMATICAL ITALIC CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1D439 MATHEMATICAL ITALIC CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1D43A MATHEMATICAL ITALIC CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D43B MATHEMATICAL ITALIC CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1D43C MATHEMATICAL ITALIC CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1D43D MATHEMATICAL ITALIC CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D43E MATHEMATICAL ITALIC CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D43F MATHEMATICAL ITALIC CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 1D440 MATHEMATICAL ITALIC CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 1D441 MATHEMATICAL ITALIC CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 1D442 MATHEMATICAL ITALIC CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D443 MATHEMATICAL ITALIC CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1D444 MATHEMATICAL ITALIC CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 1D445 MATHEMATICAL ITALIC CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1D446 MATHEMATICAL ITALIC CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D447 MATHEMATICAL ITALIC CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D448 MATHEMATICAL ITALIC CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D449 MATHEMATICAL ITALIC CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D44A MATHEMATICAL ITALIC CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D44B MATHEMATICAL ITALIC CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D44C MATHEMATICAL ITALIC CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D44D MATHEMATICAL ITALIC CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1D44E MATHEMATICAL ITALIC SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D44F MATHEMATICAL ITALIC SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D450 MATHEMATICAL ITALIC SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D451 MATHEMATICAL ITALIC SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D452 MATHEMATICAL ITALIC SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 1D453 MATHEMATICAL ITALIC SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D454 MATHEMATICAL ITALIC SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 1D456 MATHEMATICAL ITALIC SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D457 MATHEMATICAL ITALIC SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D458 MATHEMATICAL ITALIC SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D459 MATHEMATICAL ITALIC SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 1D45A MATHEMATICAL ITALIC SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D45B MATHEMATICAL ITALIC SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D45C MATHEMATICAL ITALIC SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 1D45D MATHEMATICAL ITALIC SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D45E MATHEMATICAL ITALIC SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D45F MATHEMATICAL ITALIC SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D460 MATHEMATICAL ITALIC SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D461 MATHEMATICAL ITALIC SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D462 MATHEMATICAL ITALIC SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D463 MATHEMATICAL ITALIC SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D464 MATHEMATICAL ITALIC SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D465 MATHEMATICAL ITALIC SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D466 MATHEMATICAL ITALIC SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D467 MATHEMATICAL ITALIC SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D468 MATHEMATICAL BOLD ITALIC CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D469 MATHEMATICAL BOLD ITALIC CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1D46A MATHEMATICAL BOLD ITALIC CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 1D46B MATHEMATICAL BOLD ITALIC CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D46C MATHEMATICAL BOLD ITALIC CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1D46D MATHEMATICAL BOLD ITALIC CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1D46E MATHEMATICAL BOLD ITALIC CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D46F MATHEMATICAL BOLD ITALIC CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1D470 MATHEMATICAL BOLD ITALIC CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1D471 MATHEMATICAL BOLD ITALIC CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D472 MATHEMATICAL BOLD ITALIC CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D473 MATHEMATICAL BOLD ITALIC CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 1D474 MATHEMATICAL BOLD ITALIC CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 1D475 MATHEMATICAL BOLD ITALIC CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 1D476 MATHEMATICAL BOLD ITALIC CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D477 MATHEMATICAL BOLD ITALIC CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1D478 MATHEMATICAL BOLD ITALIC CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 1D479 MATHEMATICAL BOLD ITALIC CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1D47A MATHEMATICAL BOLD ITALIC CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D47B MATHEMATICAL BOLD ITALIC CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D47C MATHEMATICAL BOLD ITALIC CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D47D MATHEMATICAL BOLD ITALIC CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D47E MATHEMATICAL BOLD ITALIC CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D47F MATHEMATICAL BOLD ITALIC CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D480 MATHEMATICAL BOLD ITALIC CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D481 MATHEMATICAL BOLD ITALIC CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1D482 MATHEMATICAL BOLD ITALIC SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D483 MATHEMATICAL BOLD ITALIC SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D484 MATHEMATICAL BOLD ITALIC SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D485 MATHEMATICAL BOLD ITALIC SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D486 MATHEMATICAL BOLD ITALIC SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 1D487 MATHEMATICAL BOLD ITALIC SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D488 MATHEMATICAL BOLD ITALIC SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 1D489 MATHEMATICAL BOLD ITALIC SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 1D48A MATHEMATICAL BOLD ITALIC SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D48B MATHEMATICAL BOLD ITALIC SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D48C MATHEMATICAL BOLD ITALIC SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D48D MATHEMATICAL BOLD ITALIC SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 1D48E MATHEMATICAL BOLD ITALIC SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D48F MATHEMATICAL BOLD ITALIC SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D490 MATHEMATICAL BOLD ITALIC SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 1D491 MATHEMATICAL BOLD ITALIC SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D492 MATHEMATICAL BOLD ITALIC SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D493 MATHEMATICAL BOLD ITALIC SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D494 MATHEMATICAL BOLD ITALIC SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D495 MATHEMATICAL BOLD ITALIC SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D496 MATHEMATICAL BOLD ITALIC SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D497 MATHEMATICAL BOLD ITALIC SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D498 MATHEMATICAL BOLD ITALIC SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D499 MATHEMATICAL BOLD ITALIC SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D49A MATHEMATICAL BOLD ITALIC SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D49B MATHEMATICAL BOLD ITALIC SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D49C MATHEMATICAL SCRIPT CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D49E MATHEMATICAL SCRIPT CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 1D49F MATHEMATICAL SCRIPT CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D4A2 MATHEMATICAL SCRIPT CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D4A5 MATHEMATICAL SCRIPT CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D4A6 MATHEMATICAL SCRIPT CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D4A9 MATHEMATICAL SCRIPT CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 1D4AA MATHEMATICAL SCRIPT CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D4AB MATHEMATICAL SCRIPT CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1D4AC MATHEMATICAL SCRIPT CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 1D4AE MATHEMATICAL SCRIPT CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D4AF MATHEMATICAL SCRIPT CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D4B0 MATHEMATICAL SCRIPT CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D4B1 MATHEMATICAL SCRIPT CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D4B2 MATHEMATICAL SCRIPT CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D4B3 MATHEMATICAL SCRIPT CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D4B4 MATHEMATICAL SCRIPT CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D4B5 MATHEMATICAL SCRIPT CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1D4B6 MATHEMATICAL SCRIPT SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D4B7 MATHEMATICAL SCRIPT SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D4B8 MATHEMATICAL SCRIPT SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D4B9 MATHEMATICAL SCRIPT SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D4BB MATHEMATICAL SCRIPT SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D4BD MATHEMATICAL SCRIPT SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 1D4BE MATHEMATICAL SCRIPT SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D4BF MATHEMATICAL SCRIPT SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D4C0 MATHEMATICAL SCRIPT SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D4C2 MATHEMATICAL SCRIPT SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D4C3 MATHEMATICAL SCRIPT SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D4C5 MATHEMATICAL SCRIPT SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D4C6 MATHEMATICAL SCRIPT SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D4C7 MATHEMATICAL SCRIPT SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D4C8 MATHEMATICAL SCRIPT SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D4C9 MATHEMATICAL SCRIPT SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D4CA MATHEMATICAL SCRIPT SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D4CB MATHEMATICAL SCRIPT SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D4CC MATHEMATICAL SCRIPT SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D4CD MATHEMATICAL SCRIPT SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D4CE MATHEMATICAL SCRIPT SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D4CF MATHEMATICAL SCRIPT SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D4D0 MATHEMATICAL BOLD SCRIPT CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D4D1 MATHEMATICAL BOLD SCRIPT CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1D4D2 MATHEMATICAL BOLD SCRIPT CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 1D4D3 MATHEMATICAL BOLD SCRIPT CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D4D4 MATHEMATICAL BOLD SCRIPT CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1D4D5 MATHEMATICAL BOLD SCRIPT CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1D4D6 MATHEMATICAL BOLD SCRIPT CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D4D7 MATHEMATICAL BOLD SCRIPT CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1D4D8 MATHEMATICAL BOLD SCRIPT CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1D4D9 MATHEMATICAL BOLD SCRIPT CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D4DA MATHEMATICAL BOLD SCRIPT CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D4DB MATHEMATICAL BOLD SCRIPT CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 1D4DC MATHEMATICAL BOLD SCRIPT CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 1D4DD MATHEMATICAL BOLD SCRIPT CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 1D4DE MATHEMATICAL BOLD SCRIPT CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D4DF MATHEMATICAL BOLD SCRIPT CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1D4E0 MATHEMATICAL BOLD SCRIPT CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 1D4E1 MATHEMATICAL BOLD SCRIPT CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1D4E2 MATHEMATICAL BOLD SCRIPT CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D4E3 MATHEMATICAL BOLD SCRIPT CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D4E4 MATHEMATICAL BOLD SCRIPT CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D4E5 MATHEMATICAL BOLD SCRIPT CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D4E6 MATHEMATICAL BOLD SCRIPT CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D4E7 MATHEMATICAL BOLD SCRIPT CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D4E8 MATHEMATICAL BOLD SCRIPT CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D4E9 MATHEMATICAL BOLD SCRIPT CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1D4EA MATHEMATICAL BOLD SCRIPT SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D4EB MATHEMATICAL BOLD SCRIPT SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D4EC MATHEMATICAL BOLD SCRIPT SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D4ED MATHEMATICAL BOLD SCRIPT SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D4EE MATHEMATICAL BOLD SCRIPT SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 1D4EF MATHEMATICAL BOLD SCRIPT SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D4F0 MATHEMATICAL BOLD SCRIPT SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 1D4F1 MATHEMATICAL BOLD SCRIPT SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 1D4F2 MATHEMATICAL BOLD SCRIPT SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D4F3 MATHEMATICAL BOLD SCRIPT SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D4F4 MATHEMATICAL BOLD SCRIPT SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D4F5 MATHEMATICAL BOLD SCRIPT SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 1D4F6 MATHEMATICAL BOLD SCRIPT SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D4F7 MATHEMATICAL BOLD SCRIPT SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D4F8 MATHEMATICAL BOLD SCRIPT SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 1D4F9 MATHEMATICAL BOLD SCRIPT SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D4FA MATHEMATICAL BOLD SCRIPT SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D4FB MATHEMATICAL BOLD SCRIPT SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D4FC MATHEMATICAL BOLD SCRIPT SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D4FD MATHEMATICAL BOLD SCRIPT SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D4FE MATHEMATICAL BOLD SCRIPT SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D4FF MATHEMATICAL BOLD SCRIPT SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D500 MATHEMATICAL BOLD SCRIPT SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D501 MATHEMATICAL BOLD SCRIPT SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D502 MATHEMATICAL BOLD SCRIPT SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D503 MATHEMATICAL BOLD SCRIPT SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D504 MATHEMATICAL FRAKTUR CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D505 MATHEMATICAL FRAKTUR CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1D507 MATHEMATICAL FRAKTUR CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D508 MATHEMATICAL FRAKTUR CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1D509 MATHEMATICAL FRAKTUR CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1D50A MATHEMATICAL FRAKTUR CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D50D MATHEMATICAL FRAKTUR CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D50E MATHEMATICAL FRAKTUR CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D50F MATHEMATICAL FRAKTUR CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 1D510 MATHEMATICAL FRAKTUR CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 1D511 MATHEMATICAL FRAKTUR CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 1D512 MATHEMATICAL FRAKTUR CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D513 MATHEMATICAL FRAKTUR CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1D514 MATHEMATICAL FRAKTUR CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 1D516 MATHEMATICAL FRAKTUR CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D517 MATHEMATICAL FRAKTUR CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D518 MATHEMATICAL FRAKTUR CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D519 MATHEMATICAL FRAKTUR CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D51A MATHEMATICAL FRAKTUR CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D51B MATHEMATICAL FRAKTUR CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D51C MATHEMATICAL FRAKTUR CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D51E MATHEMATICAL FRAKTUR SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D51F MATHEMATICAL FRAKTUR SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D520 MATHEMATICAL FRAKTUR SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D521 MATHEMATICAL FRAKTUR SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D522 MATHEMATICAL FRAKTUR SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 1D523 MATHEMATICAL FRAKTUR SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D524 MATHEMATICAL FRAKTUR SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 1D525 MATHEMATICAL FRAKTUR SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 1D526 MATHEMATICAL FRAKTUR SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D527 MATHEMATICAL FRAKTUR SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D528 MATHEMATICAL FRAKTUR SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D529 MATHEMATICAL FRAKTUR SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 1D52A MATHEMATICAL FRAKTUR SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D52B MATHEMATICAL FRAKTUR SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D52C MATHEMATICAL FRAKTUR SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 1D52D MATHEMATICAL FRAKTUR SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D52E MATHEMATICAL FRAKTUR SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D52F MATHEMATICAL FRAKTUR SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D530 MATHEMATICAL FRAKTUR SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D531 MATHEMATICAL FRAKTUR SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D532 MATHEMATICAL FRAKTUR SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D533 MATHEMATICAL FRAKTUR SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D534 MATHEMATICAL FRAKTUR SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D535 MATHEMATICAL FRAKTUR SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D536 MATHEMATICAL FRAKTUR SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D537 MATHEMATICAL FRAKTUR SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D538 MATHEMATICAL DOUBLE-STRUCK CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D539 MATHEMATICAL DOUBLE-STRUCK CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1D53B MATHEMATICAL DOUBLE-STRUCK CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D53C MATHEMATICAL DOUBLE-STRUCK CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1D53D MATHEMATICAL DOUBLE-STRUCK CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1D53E MATHEMATICAL DOUBLE-STRUCK CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D540 MATHEMATICAL DOUBLE-STRUCK CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1D541 MATHEMATICAL DOUBLE-STRUCK CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D542 MATHEMATICAL DOUBLE-STRUCK CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D543 MATHEMATICAL DOUBLE-STRUCK CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 1D544 MATHEMATICAL DOUBLE-STRUCK CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 1D546 MATHEMATICAL DOUBLE-STRUCK CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D54A MATHEMATICAL DOUBLE-STRUCK CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D54B MATHEMATICAL DOUBLE-STRUCK CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D54C MATHEMATICAL DOUBLE-STRUCK CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D54D MATHEMATICAL DOUBLE-STRUCK CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D54E MATHEMATICAL DOUBLE-STRUCK CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D54F MATHEMATICAL DOUBLE-STRUCK CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D550 MATHEMATICAL DOUBLE-STRUCK CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D552 MATHEMATICAL DOUBLE-STRUCK SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D553 MATHEMATICAL DOUBLE-STRUCK SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D554 MATHEMATICAL DOUBLE-STRUCK SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D555 MATHEMATICAL DOUBLE-STRUCK SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D556 MATHEMATICAL DOUBLE-STRUCK SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 1D557 MATHEMATICAL DOUBLE-STRUCK SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D558 MATHEMATICAL DOUBLE-STRUCK SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 1D559 MATHEMATICAL DOUBLE-STRUCK SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 1D55A MATHEMATICAL DOUBLE-STRUCK SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D55B MATHEMATICAL DOUBLE-STRUCK SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D55C MATHEMATICAL DOUBLE-STRUCK SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D55D MATHEMATICAL DOUBLE-STRUCK SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 1D55E MATHEMATICAL DOUBLE-STRUCK SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D55F MATHEMATICAL DOUBLE-STRUCK SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D560 MATHEMATICAL DOUBLE-STRUCK SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 1D561 MATHEMATICAL DOUBLE-STRUCK SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D562 MATHEMATICAL DOUBLE-STRUCK SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D563 MATHEMATICAL DOUBLE-STRUCK SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D564 MATHEMATICAL DOUBLE-STRUCK SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D565 MATHEMATICAL DOUBLE-STRUCK SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D566 MATHEMATICAL DOUBLE-STRUCK SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D567 MATHEMATICAL DOUBLE-STRUCK SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D568 MATHEMATICAL DOUBLE-STRUCK SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D569 MATHEMATICAL DOUBLE-STRUCK SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D56A MATHEMATICAL DOUBLE-STRUCK SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D56B MATHEMATICAL DOUBLE-STRUCK SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D56C MATHEMATICAL BOLD FRAKTUR CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D56D MATHEMATICAL BOLD FRAKTUR CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1D56E MATHEMATICAL BOLD FRAKTUR CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 1D56F MATHEMATICAL BOLD FRAKTUR CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D570 MATHEMATICAL BOLD FRAKTUR CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1D571 MATHEMATICAL BOLD FRAKTUR CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1D572 MATHEMATICAL BOLD FRAKTUR CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D573 MATHEMATICAL BOLD FRAKTUR CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1D574 MATHEMATICAL BOLD FRAKTUR CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1D575 MATHEMATICAL BOLD FRAKTUR CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D576 MATHEMATICAL BOLD FRAKTUR CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D577 MATHEMATICAL BOLD FRAKTUR CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 1D578 MATHEMATICAL BOLD FRAKTUR CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 1D579 MATHEMATICAL BOLD FRAKTUR CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 1D57A MATHEMATICAL BOLD FRAKTUR CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D57B MATHEMATICAL BOLD FRAKTUR CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1D57C MATHEMATICAL BOLD FRAKTUR CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 1D57D MATHEMATICAL BOLD FRAKTUR CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1D57E MATHEMATICAL BOLD FRAKTUR CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D57F MATHEMATICAL BOLD FRAKTUR CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D580 MATHEMATICAL BOLD FRAKTUR CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D581 MATHEMATICAL BOLD FRAKTUR CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D582 MATHEMATICAL BOLD FRAKTUR CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D583 MATHEMATICAL BOLD FRAKTUR CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D584 MATHEMATICAL BOLD FRAKTUR CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D585 MATHEMATICAL BOLD FRAKTUR CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1D586 MATHEMATICAL BOLD FRAKTUR SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D587 MATHEMATICAL BOLD FRAKTUR SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D588 MATHEMATICAL BOLD FRAKTUR SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D589 MATHEMATICAL BOLD FRAKTUR SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D58A MATHEMATICAL BOLD FRAKTUR SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 1D58B MATHEMATICAL BOLD FRAKTUR SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D58C MATHEMATICAL BOLD FRAKTUR SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 1D58D MATHEMATICAL BOLD FRAKTUR SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 1D58E MATHEMATICAL BOLD FRAKTUR SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D58F MATHEMATICAL BOLD FRAKTUR SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D590 MATHEMATICAL BOLD FRAKTUR SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D591 MATHEMATICAL BOLD FRAKTUR SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 1D592 MATHEMATICAL BOLD FRAKTUR SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D593 MATHEMATICAL BOLD FRAKTUR SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D594 MATHEMATICAL BOLD FRAKTUR SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 1D595 MATHEMATICAL BOLD FRAKTUR SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D596 MATHEMATICAL BOLD FRAKTUR SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D597 MATHEMATICAL BOLD FRAKTUR SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D598 MATHEMATICAL BOLD FRAKTUR SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D599 MATHEMATICAL BOLD FRAKTUR SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D59A MATHEMATICAL BOLD FRAKTUR SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D59B MATHEMATICAL BOLD FRAKTUR SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D59C MATHEMATICAL BOLD FRAKTUR SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D59D MATHEMATICAL BOLD FRAKTUR SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D59E MATHEMATICAL BOLD FRAKTUR SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D59F MATHEMATICAL BOLD FRAKTUR SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D5A0 MATHEMATICAL SANS-SERIF CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D5A1 MATHEMATICAL SANS-SERIF CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1D5A2 MATHEMATICAL SANS-SERIF CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 1D5A3 MATHEMATICAL SANS-SERIF CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D5A4 MATHEMATICAL SANS-SERIF CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1D5A5 MATHEMATICAL SANS-SERIF CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1D5A6 MATHEMATICAL SANS-SERIF CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D5A7 MATHEMATICAL SANS-SERIF CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1D5A8 MATHEMATICAL SANS-SERIF CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1D5A9 MATHEMATICAL SANS-SERIF CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D5AA MATHEMATICAL SANS-SERIF CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D5AB MATHEMATICAL SANS-SERIF CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 1D5AC MATHEMATICAL SANS-SERIF CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 1D5AD MATHEMATICAL SANS-SERIF CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 1D5AE MATHEMATICAL SANS-SERIF CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D5AF MATHEMATICAL SANS-SERIF CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1D5B0 MATHEMATICAL SANS-SERIF CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 1D5B1 MATHEMATICAL SANS-SERIF CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1D5B2 MATHEMATICAL SANS-SERIF CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D5B3 MATHEMATICAL SANS-SERIF CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D5B4 MATHEMATICAL SANS-SERIF CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D5B5 MATHEMATICAL SANS-SERIF CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D5B6 MATHEMATICAL SANS-SERIF CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D5B7 MATHEMATICAL SANS-SERIF CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D5B8 MATHEMATICAL SANS-SERIF CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D5B9 MATHEMATICAL SANS-SERIF CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1D5BA MATHEMATICAL SANS-SERIF SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D5BB MATHEMATICAL SANS-SERIF SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D5BC MATHEMATICAL SANS-SERIF SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D5BD MATHEMATICAL SANS-SERIF SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D5BE MATHEMATICAL SANS-SERIF SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 1D5BF MATHEMATICAL SANS-SERIF SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D5C0 MATHEMATICAL SANS-SERIF SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 1D5C1 MATHEMATICAL SANS-SERIF SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 1D5C2 MATHEMATICAL SANS-SERIF SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D5C3 MATHEMATICAL SANS-SERIF SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D5C4 MATHEMATICAL SANS-SERIF SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D5C5 MATHEMATICAL SANS-SERIF SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 1D5C6 MATHEMATICAL SANS-SERIF SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D5C7 MATHEMATICAL SANS-SERIF SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D5C8 MATHEMATICAL SANS-SERIF SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 1D5C9 MATHEMATICAL SANS-SERIF SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D5CA MATHEMATICAL SANS-SERIF SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D5CB MATHEMATICAL SANS-SERIF SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D5CC MATHEMATICAL SANS-SERIF SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D5CD MATHEMATICAL SANS-SERIF SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D5CE MATHEMATICAL SANS-SERIF SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D5CF MATHEMATICAL SANS-SERIF SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D5D0 MATHEMATICAL SANS-SERIF SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D5D1 MATHEMATICAL SANS-SERIF SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D5D2 MATHEMATICAL SANS-SERIF SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D5D3 MATHEMATICAL SANS-SERIF SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D5D4 MATHEMATICAL SANS-SERIF BOLD CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D5D5 MATHEMATICAL SANS-SERIF BOLD CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1D5D6 MATHEMATICAL SANS-SERIF BOLD CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 1D5D7 MATHEMATICAL SANS-SERIF BOLD CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D5D8 MATHEMATICAL SANS-SERIF BOLD CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1D5D9 MATHEMATICAL SANS-SERIF BOLD CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1D5DA MATHEMATICAL SANS-SERIF BOLD CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D5DB MATHEMATICAL SANS-SERIF BOLD CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1D5DC MATHEMATICAL SANS-SERIF BOLD CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1D5DD MATHEMATICAL SANS-SERIF BOLD CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D5DE MATHEMATICAL SANS-SERIF BOLD CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D5DF MATHEMATICAL SANS-SERIF BOLD CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 1D5E0 MATHEMATICAL SANS-SERIF BOLD CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 1D5E1 MATHEMATICAL SANS-SERIF BOLD CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 1D5E2 MATHEMATICAL SANS-SERIF BOLD CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D5E3 MATHEMATICAL SANS-SERIF BOLD CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1D5E4 MATHEMATICAL SANS-SERIF BOLD CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 1D5E5 MATHEMATICAL SANS-SERIF BOLD CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1D5E6 MATHEMATICAL SANS-SERIF BOLD CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D5E7 MATHEMATICAL SANS-SERIF BOLD CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D5E8 MATHEMATICAL SANS-SERIF BOLD CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D5E9 MATHEMATICAL SANS-SERIF BOLD CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D5EA MATHEMATICAL SANS-SERIF BOLD CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D5EB MATHEMATICAL SANS-SERIF BOLD CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D5EC MATHEMATICAL SANS-SERIF BOLD CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D5ED MATHEMATICAL SANS-SERIF BOLD CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1D5EE MATHEMATICAL SANS-SERIF BOLD SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D5EF MATHEMATICAL SANS-SERIF BOLD SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D5F0 MATHEMATICAL SANS-SERIF BOLD SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D5F1 MATHEMATICAL SANS-SERIF BOLD SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D5F2 MATHEMATICAL SANS-SERIF BOLD SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 1D5F3 MATHEMATICAL SANS-SERIF BOLD SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D5F4 MATHEMATICAL SANS-SERIF BOLD SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 1D5F5 MATHEMATICAL SANS-SERIF BOLD SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 1D5F6 MATHEMATICAL SANS-SERIF BOLD SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D5F7 MATHEMATICAL SANS-SERIF BOLD SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D5F8 MATHEMATICAL SANS-SERIF BOLD SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D5F9 MATHEMATICAL SANS-SERIF BOLD SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 1D5FA MATHEMATICAL SANS-SERIF BOLD SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D5FB MATHEMATICAL SANS-SERIF BOLD SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D5FC MATHEMATICAL SANS-SERIF BOLD SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 1D5FD MATHEMATICAL SANS-SERIF BOLD SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D5FE MATHEMATICAL SANS-SERIF BOLD SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D5FF MATHEMATICAL SANS-SERIF BOLD SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D600 MATHEMATICAL SANS-SERIF BOLD SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D601 MATHEMATICAL SANS-SERIF BOLD SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D602 MATHEMATICAL SANS-SERIF BOLD SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D603 MATHEMATICAL SANS-SERIF BOLD SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D604 MATHEMATICAL SANS-SERIF BOLD SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D605 MATHEMATICAL SANS-SERIF BOLD SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D606 MATHEMATICAL SANS-SERIF BOLD SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D607 MATHEMATICAL SANS-SERIF BOLD SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D608 MATHEMATICAL SANS-SERIF ITALIC CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D609 MATHEMATICAL SANS-SERIF ITALIC CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1D60A MATHEMATICAL SANS-SERIF ITALIC CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 1D60B MATHEMATICAL SANS-SERIF ITALIC CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D60C MATHEMATICAL SANS-SERIF ITALIC CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1D60D MATHEMATICAL SANS-SERIF ITALIC CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1D60E MATHEMATICAL SANS-SERIF ITALIC CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D60F MATHEMATICAL SANS-SERIF ITALIC CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1D610 MATHEMATICAL SANS-SERIF ITALIC CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1D611 MATHEMATICAL SANS-SERIF ITALIC CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D612 MATHEMATICAL SANS-SERIF ITALIC CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D613 MATHEMATICAL SANS-SERIF ITALIC CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 1D614 MATHEMATICAL SANS-SERIF ITALIC CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 1D615 MATHEMATICAL SANS-SERIF ITALIC CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 1D616 MATHEMATICAL SANS-SERIF ITALIC CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D617 MATHEMATICAL SANS-SERIF ITALIC CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1D618 MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 1D619 MATHEMATICAL SANS-SERIF ITALIC CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1D61A MATHEMATICAL SANS-SERIF ITALIC CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D61B MATHEMATICAL SANS-SERIF ITALIC CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D61C MATHEMATICAL SANS-SERIF ITALIC CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D61D MATHEMATICAL SANS-SERIF ITALIC CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D61E MATHEMATICAL SANS-SERIF ITALIC CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D61F MATHEMATICAL SANS-SERIF ITALIC CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D620 MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D621 MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1D622 MATHEMATICAL SANS-SERIF ITALIC SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D623 MATHEMATICAL SANS-SERIF ITALIC SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D624 MATHEMATICAL SANS-SERIF ITALIC SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D625 MATHEMATICAL SANS-SERIF ITALIC SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D626 MATHEMATICAL SANS-SERIF ITALIC SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 1D627 MATHEMATICAL SANS-SERIF ITALIC SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D628 MATHEMATICAL SANS-SERIF ITALIC SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 1D629 MATHEMATICAL SANS-SERIF ITALIC SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 1D62A MATHEMATICAL SANS-SERIF ITALIC SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D62B MATHEMATICAL SANS-SERIF ITALIC SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D62C MATHEMATICAL SANS-SERIF ITALIC SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D62D MATHEMATICAL SANS-SERIF ITALIC SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 1D62E MATHEMATICAL SANS-SERIF ITALIC SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D62F MATHEMATICAL SANS-SERIF ITALIC SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D630 MATHEMATICAL SANS-SERIF ITALIC SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 1D631 MATHEMATICAL SANS-SERIF ITALIC SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D632 MATHEMATICAL SANS-SERIF ITALIC SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D633 MATHEMATICAL SANS-SERIF ITALIC SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D634 MATHEMATICAL SANS-SERIF ITALIC SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D635 MATHEMATICAL SANS-SERIF ITALIC SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D636 MATHEMATICAL SANS-SERIF ITALIC SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D637 MATHEMATICAL SANS-SERIF ITALIC SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D638 MATHEMATICAL SANS-SERIF ITALIC SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D639 MATHEMATICAL SANS-SERIF ITALIC SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D63A MATHEMATICAL SANS-SERIF ITALIC SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D63B MATHEMATICAL SANS-SERIF ITALIC SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D63C MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D63D MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1D63E MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 1D63F MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D640 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1D641 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1D642 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D643 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1D644 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1D645 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D646 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D647 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 1D648 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 1D649 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 1D64A MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D64B MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1D64C MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 1D64D MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1D64E MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D64F MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D650 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D651 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D652 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D653 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D654 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D655 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1D656 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D657 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D658 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D659 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D65A MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 1D65B MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D65C MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 1D65D MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 1D65E MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D65F MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D660 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D661 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 1D662 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D663 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D664 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 1D665 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D666 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D667 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D668 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D669 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D66A MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D66B MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D66C MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D66D MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D66E MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D66F MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D670 MATHEMATICAL MONOSPACE CAPITAL A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1D671 MATHEMATICAL MONOSPACE CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1D672 MATHEMATICAL MONOSPACE CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 1D673 MATHEMATICAL MONOSPACE CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1D674 MATHEMATICAL MONOSPACE CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1D675 MATHEMATICAL MONOSPACE CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1D676 MATHEMATICAL MONOSPACE CAPITAL G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1D677 MATHEMATICAL MONOSPACE CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1D678 MATHEMATICAL MONOSPACE CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1D679 MATHEMATICAL MONOSPACE CAPITAL J
+ * 	004A LATIN CAPITAL LETTER J
+ * 1D67A MATHEMATICAL MONOSPACE CAPITAL K
+ * 	004B LATIN CAPITAL LETTER K
+ * 1D67B MATHEMATICAL MONOSPACE CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 1D67C MATHEMATICAL MONOSPACE CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 1D67D MATHEMATICAL MONOSPACE CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 1D67E MATHEMATICAL MONOSPACE CAPITAL O
+ * 	004F LATIN CAPITAL LETTER O
+ * 1D67F MATHEMATICAL MONOSPACE CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1D680 MATHEMATICAL MONOSPACE CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 1D681 MATHEMATICAL MONOSPACE CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1D682 MATHEMATICAL MONOSPACE CAPITAL S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1D683 MATHEMATICAL MONOSPACE CAPITAL T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1D684 MATHEMATICAL MONOSPACE CAPITAL U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1D685 MATHEMATICAL MONOSPACE CAPITAL V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1D686 MATHEMATICAL MONOSPACE CAPITAL W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1D687 MATHEMATICAL MONOSPACE CAPITAL X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1D688 MATHEMATICAL MONOSPACE CAPITAL Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1D689 MATHEMATICAL MONOSPACE CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1D68A MATHEMATICAL MONOSPACE SMALL A
+ * 	0061 LATIN SMALL LETTER A
+ * 1D68B MATHEMATICAL MONOSPACE SMALL B
+ * 	0062 LATIN SMALL LETTER B
+ * 1D68C MATHEMATICAL MONOSPACE SMALL C
+ * 	0063 LATIN SMALL LETTER C
+ * 1D68D MATHEMATICAL MONOSPACE SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 1D68E MATHEMATICAL MONOSPACE SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 1D68F MATHEMATICAL MONOSPACE SMALL F
+ * 	0066 LATIN SMALL LETTER F
+ * 1D690 MATHEMATICAL MONOSPACE SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 1D691 MATHEMATICAL MONOSPACE SMALL H
+ * 	0068 LATIN SMALL LETTER H
+ * 1D692 MATHEMATICAL MONOSPACE SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 1D693 MATHEMATICAL MONOSPACE SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 1D694 MATHEMATICAL MONOSPACE SMALL K
+ * 	006B LATIN SMALL LETTER K
+ * 1D695 MATHEMATICAL MONOSPACE SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 1D696 MATHEMATICAL MONOSPACE SMALL M
+ * 	006D LATIN SMALL LETTER M
+ * 1D697 MATHEMATICAL MONOSPACE SMALL N
+ * 	006E LATIN SMALL LETTER N
+ * 1D698 MATHEMATICAL MONOSPACE SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 1D699 MATHEMATICAL MONOSPACE SMALL P
+ * 	0070 LATIN SMALL LETTER P
+ * 1D69A MATHEMATICAL MONOSPACE SMALL Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 1D69B MATHEMATICAL MONOSPACE SMALL R
+ * 	0072 LATIN SMALL LETTER R
+ * 1D69C MATHEMATICAL MONOSPACE SMALL S
+ * 	0073 LATIN SMALL LETTER S
+ * 1D69D MATHEMATICAL MONOSPACE SMALL T
+ * 	0074 LATIN SMALL LETTER T
+ * 1D69E MATHEMATICAL MONOSPACE SMALL U
+ * 	0075 LATIN SMALL LETTER U
+ * 1D69F MATHEMATICAL MONOSPACE SMALL V
+ * 	0076 LATIN SMALL LETTER V
+ * 1D6A0 MATHEMATICAL MONOSPACE SMALL W
+ * 	0077 LATIN SMALL LETTER W
+ * 1D6A1 MATHEMATICAL MONOSPACE SMALL X
+ * 	0078 LATIN SMALL LETTER X
+ * 1D6A2 MATHEMATICAL MONOSPACE SMALL Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 1D6A3 MATHEMATICAL MONOSPACE SMALL Z
+ * 	007A LATIN SMALL LETTER Z
+ * 1D6A8 MATHEMATICAL BOLD CAPITAL ALPHA
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1D6A9 MATHEMATICAL BOLD CAPITAL BETA
+ * 	0392 GREEK CAPITAL LETTER BETA
+ * 1D6AA MATHEMATICAL BOLD CAPITAL GAMMA
+ * 	0393 GREEK CAPITAL LETTER GAMMA
+ * 1D6AB MATHEMATICAL BOLD CAPITAL DELTA
+ * 	0394 GREEK CAPITAL LETTER DELTA
+ * 1D6AC MATHEMATICAL BOLD CAPITAL EPSILON
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1D6AD MATHEMATICAL BOLD CAPITAL ZETA
+ * 	0396 GREEK CAPITAL LETTER ZETA
+ * 1D6AE MATHEMATICAL BOLD CAPITAL ETA
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1D6AF MATHEMATICAL BOLD CAPITAL THETA
+ * 	0398 GREEK CAPITAL LETTER THETA
+ * 1D6B0 MATHEMATICAL BOLD CAPITAL IOTA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1D6B1 MATHEMATICAL BOLD CAPITAL KAPPA
+ * 	039A GREEK CAPITAL LETTER KAPPA
+ * 1D6B2 MATHEMATICAL BOLD CAPITAL LAMDA
+ * 	039B GREEK CAPITAL LETTER LAMDA
+ * 1D6B3 MATHEMATICAL BOLD CAPITAL MU
+ * 	039C GREEK CAPITAL LETTER MU
+ * 1D6B4 MATHEMATICAL BOLD CAPITAL NU
+ * 	039D GREEK CAPITAL LETTER NU
+ * 1D6B5 MATHEMATICAL BOLD CAPITAL XI
+ * 	039E GREEK CAPITAL LETTER XI
+ * 1D6B6 MATHEMATICAL BOLD CAPITAL OMICRON
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1D6B7 MATHEMATICAL BOLD CAPITAL PI
+ * 	03A0 GREEK CAPITAL LETTER PI
+ * 1D6B8 MATHEMATICAL BOLD CAPITAL RHO
+ * 	03A1 GREEK CAPITAL LETTER RHO
+ * 1D6B9 MATHEMATICAL BOLD CAPITAL THETA SYMBOL
+ * 	0398 GREEK CAPITAL LETTER THETA
+ * 1D6BA MATHEMATICAL BOLD CAPITAL SIGMA
+ * 	03A3 GREEK CAPITAL LETTER SIGMA
+ * 1D6BB MATHEMATICAL BOLD CAPITAL TAU
+ * 	03A4 GREEK CAPITAL LETTER TAU
+ * 1D6BC MATHEMATICAL BOLD CAPITAL UPSILON
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1D6BD MATHEMATICAL BOLD CAPITAL PHI
+ * 	03A6 GREEK CAPITAL LETTER PHI
+ * 1D6BE MATHEMATICAL BOLD CAPITAL CHI
+ * 	03A7 GREEK CAPITAL LETTER CHI
+ * 1D6BF MATHEMATICAL BOLD CAPITAL PSI
+ * 	03A8 GREEK CAPITAL LETTER PSI
+ * 1D6C0 MATHEMATICAL BOLD CAPITAL OMEGA
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1D6C1 MATHEMATICAL BOLD NABLA
+ * 	2207 NABLA
+ * 1D6C2 MATHEMATICAL BOLD SMALL ALPHA
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1D6C3 MATHEMATICAL BOLD SMALL BETA
+ * 	03B2 GREEK SMALL LETTER BETA
+ * 1D6C4 MATHEMATICAL BOLD SMALL GAMMA
+ * 	03B3 GREEK SMALL LETTER GAMMA
+ * 1D6C5 MATHEMATICAL BOLD SMALL DELTA
+ * 	03B4 GREEK SMALL LETTER DELTA
+ * 1D6C6 MATHEMATICAL BOLD SMALL EPSILON
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1D6C7 MATHEMATICAL BOLD SMALL ZETA
+ * 	03B6 GREEK SMALL LETTER ZETA
+ * 1D6C8 MATHEMATICAL BOLD SMALL ETA
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1D6C9 MATHEMATICAL BOLD SMALL THETA
+ * 	03B8 GREEK SMALL LETTER THETA
+ * 1D6CA MATHEMATICAL BOLD SMALL IOTA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1D6CB MATHEMATICAL BOLD SMALL KAPPA
+ * 	03BA GREEK SMALL LETTER KAPPA
+ * 1D6CC MATHEMATICAL BOLD SMALL LAMDA
+ * 	03BB GREEK SMALL LETTER LAMDA
+ * 1D6CD MATHEMATICAL BOLD SMALL MU
+ * 	03BC GREEK SMALL LETTER MU
+ * 1D6CE MATHEMATICAL BOLD SMALL NU
+ * 	03BD GREEK SMALL LETTER NU
+ * 1D6CF MATHEMATICAL BOLD SMALL XI
+ * 	03BE GREEK SMALL LETTER XI
+ * 1D6D0 MATHEMATICAL BOLD SMALL OMICRON
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1D6D1 MATHEMATICAL BOLD SMALL PI
+ * 	03C0 GREEK SMALL LETTER PI
+ * 1D6D2 MATHEMATICAL BOLD SMALL RHO
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 1D6D3 MATHEMATICAL BOLD SMALL FINAL SIGMA
+ * 	03C2 GREEK SMALL LETTER FINAL SIGMA
+ * 1D6D4 MATHEMATICAL BOLD SMALL SIGMA
+ * 	03C3 GREEK SMALL LETTER SIGMA
+ * 1D6D5 MATHEMATICAL BOLD SMALL TAU
+ * 	03C4 GREEK SMALL LETTER TAU
+ * 1D6D6 MATHEMATICAL BOLD SMALL UPSILON
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1D6D7 MATHEMATICAL BOLD SMALL PHI
+ * 	03C6 GREEK SMALL LETTER PHI
+ * 1D6D8 MATHEMATICAL BOLD SMALL CHI
+ * 	03C7 GREEK SMALL LETTER CHI
+ * 1D6D9 MATHEMATICAL BOLD SMALL PSI
+ * 	03C8 GREEK SMALL LETTER PSI
+ * 1D6DA MATHEMATICAL BOLD SMALL OMEGA
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1D6DB MATHEMATICAL BOLD PARTIAL DIFFERENTIAL
+ * 	2202 PARTIAL DIFFERENTIAL
+ * 1D6DC MATHEMATICAL BOLD EPSILON SYMBOL
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1D6DD MATHEMATICAL BOLD THETA SYMBOL
+ * 	03B8 GREEK SMALL LETTER THETA
+ * 1D6DE MATHEMATICAL BOLD KAPPA SYMBOL
+ * 	03BA GREEK SMALL LETTER KAPPA
+ * 1D6DF MATHEMATICAL BOLD PHI SYMBOL
+ * 	03C6 GREEK SMALL LETTER PHI
+ * 1D6E0 MATHEMATICAL BOLD RHO SYMBOL
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 1D6E1 MATHEMATICAL BOLD PI SYMBOL
+ * 	03C0 GREEK SMALL LETTER PI
+ * 1D6E2 MATHEMATICAL ITALIC CAPITAL ALPHA
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1D6E3 MATHEMATICAL ITALIC CAPITAL BETA
+ * 	0392 GREEK CAPITAL LETTER BETA
+ * 1D6E4 MATHEMATICAL ITALIC CAPITAL GAMMA
+ * 	0393 GREEK CAPITAL LETTER GAMMA
+ * 1D6E5 MATHEMATICAL ITALIC CAPITAL DELTA
+ * 	0394 GREEK CAPITAL LETTER DELTA
+ * 1D6E6 MATHEMATICAL ITALIC CAPITAL EPSILON
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1D6E7 MATHEMATICAL ITALIC CAPITAL ZETA
+ * 	0396 GREEK CAPITAL LETTER ZETA
+ * 1D6E8 MATHEMATICAL ITALIC CAPITAL ETA
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1D6E9 MATHEMATICAL ITALIC CAPITAL THETA
+ * 	0398 GREEK CAPITAL LETTER THETA
+ * 1D6EA MATHEMATICAL ITALIC CAPITAL IOTA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1D6EB MATHEMATICAL ITALIC CAPITAL KAPPA
+ * 	039A GREEK CAPITAL LETTER KAPPA
+ * 1D6EC MATHEMATICAL ITALIC CAPITAL LAMDA
+ * 	039B GREEK CAPITAL LETTER LAMDA
+ * 1D6ED MATHEMATICAL ITALIC CAPITAL MU
+ * 	039C GREEK CAPITAL LETTER MU
+ * 1D6EE MATHEMATICAL ITALIC CAPITAL NU
+ * 	039D GREEK CAPITAL LETTER NU
+ * 1D6EF MATHEMATICAL ITALIC CAPITAL XI
+ * 	039E GREEK CAPITAL LETTER XI
+ * 1D6F0 MATHEMATICAL ITALIC CAPITAL OMICRON
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1D6F1 MATHEMATICAL ITALIC CAPITAL PI
+ * 	03A0 GREEK CAPITAL LETTER PI
+ * 1D6F2 MATHEMATICAL ITALIC CAPITAL RHO
+ * 	03A1 GREEK CAPITAL LETTER RHO
+ * 1D6F3 MATHEMATICAL ITALIC CAPITAL THETA SYMBOL
+ * 	0398 GREEK CAPITAL LETTER THETA
+ * 1D6F4 MATHEMATICAL ITALIC CAPITAL SIGMA
+ * 	03A3 GREEK CAPITAL LETTER SIGMA
+ * 1D6F5 MATHEMATICAL ITALIC CAPITAL TAU
+ * 	03A4 GREEK CAPITAL LETTER TAU
+ * 1D6F6 MATHEMATICAL ITALIC CAPITAL UPSILON
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1D6F7 MATHEMATICAL ITALIC CAPITAL PHI
+ * 	03A6 GREEK CAPITAL LETTER PHI
+ * 1D6F8 MATHEMATICAL ITALIC CAPITAL CHI
+ * 	03A7 GREEK CAPITAL LETTER CHI
+ * 1D6F9 MATHEMATICAL ITALIC CAPITAL PSI
+ * 	03A8 GREEK CAPITAL LETTER PSI
+ * 1D6FA MATHEMATICAL ITALIC CAPITAL OMEGA
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1D6FB MATHEMATICAL ITALIC NABLA
+ * 	2207 NABLA
+ * 1D6FC MATHEMATICAL ITALIC SMALL ALPHA
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1D6FD MATHEMATICAL ITALIC SMALL BETA
+ * 	03B2 GREEK SMALL LETTER BETA
+ * 1D6FE MATHEMATICAL ITALIC SMALL GAMMA
+ * 	03B3 GREEK SMALL LETTER GAMMA
+ * 1D6FF MATHEMATICAL ITALIC SMALL DELTA
+ * 	03B4 GREEK SMALL LETTER DELTA
+ * 1D700 MATHEMATICAL ITALIC SMALL EPSILON
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1D701 MATHEMATICAL ITALIC SMALL ZETA
+ * 	03B6 GREEK SMALL LETTER ZETA
+ * 1D702 MATHEMATICAL ITALIC SMALL ETA
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1D703 MATHEMATICAL ITALIC SMALL THETA
+ * 	03B8 GREEK SMALL LETTER THETA
+ * 1D704 MATHEMATICAL ITALIC SMALL IOTA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1D705 MATHEMATICAL ITALIC SMALL KAPPA
+ * 	03BA GREEK SMALL LETTER KAPPA
+ * 1D706 MATHEMATICAL ITALIC SMALL LAMDA
+ * 	03BB GREEK SMALL LETTER LAMDA
+ * 1D707 MATHEMATICAL ITALIC SMALL MU
+ * 	03BC GREEK SMALL LETTER MU
+ * 1D708 MATHEMATICAL ITALIC SMALL NU
+ * 	03BD GREEK SMALL LETTER NU
+ * 1D709 MATHEMATICAL ITALIC SMALL XI
+ * 	03BE GREEK SMALL LETTER XI
+ * 1D70A MATHEMATICAL ITALIC SMALL OMICRON
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1D70B MATHEMATICAL ITALIC SMALL PI
+ * 	03C0 GREEK SMALL LETTER PI
+ * 1D70C MATHEMATICAL ITALIC SMALL RHO
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 1D70D MATHEMATICAL ITALIC SMALL FINAL SIGMA
+ * 	03C2 GREEK SMALL LETTER FINAL SIGMA
+ * 1D70E MATHEMATICAL ITALIC SMALL SIGMA
+ * 	03C3 GREEK SMALL LETTER SIGMA
+ * 1D70F MATHEMATICAL ITALIC SMALL TAU
+ * 	03C4 GREEK SMALL LETTER TAU
+ * 1D710 MATHEMATICAL ITALIC SMALL UPSILON
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1D711 MATHEMATICAL ITALIC SMALL PHI
+ * 	03C6 GREEK SMALL LETTER PHI
+ * 1D712 MATHEMATICAL ITALIC SMALL CHI
+ * 	03C7 GREEK SMALL LETTER CHI
+ * 1D713 MATHEMATICAL ITALIC SMALL PSI
+ * 	03C8 GREEK SMALL LETTER PSI
+ * 1D714 MATHEMATICAL ITALIC SMALL OMEGA
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1D715 MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL
+ * 	2202 PARTIAL DIFFERENTIAL
+ * 1D716 MATHEMATICAL ITALIC EPSILON SYMBOL
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1D717 MATHEMATICAL ITALIC THETA SYMBOL
+ * 	03B8 GREEK SMALL LETTER THETA
+ * 1D718 MATHEMATICAL ITALIC KAPPA SYMBOL
+ * 	03BA GREEK SMALL LETTER KAPPA
+ * 1D719 MATHEMATICAL ITALIC PHI SYMBOL
+ * 	03C6 GREEK SMALL LETTER PHI
+ * 1D71A MATHEMATICAL ITALIC RHO SYMBOL
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 1D71B MATHEMATICAL ITALIC PI SYMBOL
+ * 	03C0 GREEK SMALL LETTER PI
+ * 1D71C MATHEMATICAL BOLD ITALIC CAPITAL ALPHA
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1D71D MATHEMATICAL BOLD ITALIC CAPITAL BETA
+ * 	0392 GREEK CAPITAL LETTER BETA
+ * 1D71E MATHEMATICAL BOLD ITALIC CAPITAL GAMMA
+ * 	0393 GREEK CAPITAL LETTER GAMMA
+ * 1D71F MATHEMATICAL BOLD ITALIC CAPITAL DELTA
+ * 	0394 GREEK CAPITAL LETTER DELTA
+ * 1D720 MATHEMATICAL BOLD ITALIC CAPITAL EPSILON
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1D721 MATHEMATICAL BOLD ITALIC CAPITAL ZETA
+ * 	0396 GREEK CAPITAL LETTER ZETA
+ * 1D722 MATHEMATICAL BOLD ITALIC CAPITAL ETA
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1D723 MATHEMATICAL BOLD ITALIC CAPITAL THETA
+ * 	0398 GREEK CAPITAL LETTER THETA
+ * 1D724 MATHEMATICAL BOLD ITALIC CAPITAL IOTA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1D725 MATHEMATICAL BOLD ITALIC CAPITAL KAPPA
+ * 	039A GREEK CAPITAL LETTER KAPPA
+ * 1D726 MATHEMATICAL BOLD ITALIC CAPITAL LAMDA
+ * 	039B GREEK CAPITAL LETTER LAMDA
+ * 1D727 MATHEMATICAL BOLD ITALIC CAPITAL MU
+ * 	039C GREEK CAPITAL LETTER MU
+ * 1D728 MATHEMATICAL BOLD ITALIC CAPITAL NU
+ * 	039D GREEK CAPITAL LETTER NU
+ * 1D729 MATHEMATICAL BOLD ITALIC CAPITAL XI
+ * 	039E GREEK CAPITAL LETTER XI
+ * 1D72A MATHEMATICAL BOLD ITALIC CAPITAL OMICRON
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1D72B MATHEMATICAL BOLD ITALIC CAPITAL PI
+ * 	03A0 GREEK CAPITAL LETTER PI
+ * 1D72C MATHEMATICAL BOLD ITALIC CAPITAL RHO
+ * 	03A1 GREEK CAPITAL LETTER RHO
+ * 1D72D MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL
+ * 	0398 GREEK CAPITAL LETTER THETA
+ * 1D72E MATHEMATICAL BOLD ITALIC CAPITAL SIGMA
+ * 	03A3 GREEK CAPITAL LETTER SIGMA
+ * 1D72F MATHEMATICAL BOLD ITALIC CAPITAL TAU
+ * 	03A4 GREEK CAPITAL LETTER TAU
+ * 1D730 MATHEMATICAL BOLD ITALIC CAPITAL UPSILON
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1D731 MATHEMATICAL BOLD ITALIC CAPITAL PHI
+ * 	03A6 GREEK CAPITAL LETTER PHI
+ * 1D732 MATHEMATICAL BOLD ITALIC CAPITAL CHI
+ * 	03A7 GREEK CAPITAL LETTER CHI
+ * 1D733 MATHEMATICAL BOLD ITALIC CAPITAL PSI
+ * 	03A8 GREEK CAPITAL LETTER PSI
+ * 1D734 MATHEMATICAL BOLD ITALIC CAPITAL OMEGA
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1D735 MATHEMATICAL BOLD ITALIC NABLA
+ * 	2207 NABLA
+ * 1D736 MATHEMATICAL BOLD ITALIC SMALL ALPHA
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1D737 MATHEMATICAL BOLD ITALIC SMALL BETA
+ * 	03B2 GREEK SMALL LETTER BETA
+ * 1D738 MATHEMATICAL BOLD ITALIC SMALL GAMMA
+ * 	03B3 GREEK SMALL LETTER GAMMA
+ * 1D739 MATHEMATICAL BOLD ITALIC SMALL DELTA
+ * 	03B4 GREEK SMALL LETTER DELTA
+ * 1D73A MATHEMATICAL BOLD ITALIC SMALL EPSILON
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1D73B MATHEMATICAL BOLD ITALIC SMALL ZETA
+ * 	03B6 GREEK SMALL LETTER ZETA
+ * 1D73C MATHEMATICAL BOLD ITALIC SMALL ETA
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1D73D MATHEMATICAL BOLD ITALIC SMALL THETA
+ * 	03B8 GREEK SMALL LETTER THETA
+ * 1D73E MATHEMATICAL BOLD ITALIC SMALL IOTA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1D73F MATHEMATICAL BOLD ITALIC SMALL KAPPA
+ * 	03BA GREEK SMALL LETTER KAPPA
+ * 1D740 MATHEMATICAL BOLD ITALIC SMALL LAMDA
+ * 	03BB GREEK SMALL LETTER LAMDA
+ * 1D741 MATHEMATICAL BOLD ITALIC SMALL MU
+ * 	03BC GREEK SMALL LETTER MU
+ * 1D742 MATHEMATICAL BOLD ITALIC SMALL NU
+ * 	03BD GREEK SMALL LETTER NU
+ * 1D743 MATHEMATICAL BOLD ITALIC SMALL XI
+ * 	03BE GREEK SMALL LETTER XI
+ * 1D744 MATHEMATICAL BOLD ITALIC SMALL OMICRON
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1D745 MATHEMATICAL BOLD ITALIC SMALL PI
+ * 	03C0 GREEK SMALL LETTER PI
+ * 1D746 MATHEMATICAL BOLD ITALIC SMALL RHO
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 1D747 MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA
+ * 	03C2 GREEK SMALL LETTER FINAL SIGMA
+ * 1D748 MATHEMATICAL BOLD ITALIC SMALL SIGMA
+ * 	03C3 GREEK SMALL LETTER SIGMA
+ * 1D749 MATHEMATICAL BOLD ITALIC SMALL TAU
+ * 	03C4 GREEK SMALL LETTER TAU
+ * 1D74A MATHEMATICAL BOLD ITALIC SMALL UPSILON
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1D74B MATHEMATICAL BOLD ITALIC SMALL PHI
+ * 	03C6 GREEK SMALL LETTER PHI
+ * 1D74C MATHEMATICAL BOLD ITALIC SMALL CHI
+ * 	03C7 GREEK SMALL LETTER CHI
+ * 1D74D MATHEMATICAL BOLD ITALIC SMALL PSI
+ * 	03C8 GREEK SMALL LETTER PSI
+ * 1D74E MATHEMATICAL BOLD ITALIC SMALL OMEGA
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1D74F MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL
+ * 	2202 PARTIAL DIFFERENTIAL
+ * 1D750 MATHEMATICAL BOLD ITALIC EPSILON SYMBOL
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1D751 MATHEMATICAL BOLD ITALIC THETA SYMBOL
+ * 	03B8 GREEK SMALL LETTER THETA
+ * 1D752 MATHEMATICAL BOLD ITALIC KAPPA SYMBOL
+ * 	03BA GREEK SMALL LETTER KAPPA
+ * 1D753 MATHEMATICAL BOLD ITALIC PHI SYMBOL
+ * 	03C6 GREEK SMALL LETTER PHI
+ * 1D754 MATHEMATICAL BOLD ITALIC RHO SYMBOL
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 1D755 MATHEMATICAL BOLD ITALIC PI SYMBOL
+ * 	03C0 GREEK SMALL LETTER PI
+ * 1D756 MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1D757 MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA
+ * 	0392 GREEK CAPITAL LETTER BETA
+ * 1D758 MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA
+ * 	0393 GREEK CAPITAL LETTER GAMMA
+ * 1D759 MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA
+ * 	0394 GREEK CAPITAL LETTER DELTA
+ * 1D75A MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1D75B MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA
+ * 	0396 GREEK CAPITAL LETTER ZETA
+ * 1D75C MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1D75D MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA
+ * 	0398 GREEK CAPITAL LETTER THETA
+ * 1D75E MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1D75F MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA
+ * 	039A GREEK CAPITAL LETTER KAPPA
+ * 1D760 MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA
+ * 	039B GREEK CAPITAL LETTER LAMDA
+ * 1D761 MATHEMATICAL SANS-SERIF BOLD CAPITAL MU
+ * 	039C GREEK CAPITAL LETTER MU
+ * 1D762 MATHEMATICAL SANS-SERIF BOLD CAPITAL NU
+ * 	039D GREEK CAPITAL LETTER NU
+ * 1D763 MATHEMATICAL SANS-SERIF BOLD CAPITAL XI
+ * 	039E GREEK CAPITAL LETTER XI
+ * 1D764 MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1D765 MATHEMATICAL SANS-SERIF BOLD CAPITAL PI
+ * 	03A0 GREEK CAPITAL LETTER PI
+ * 1D766 MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO
+ * 	03A1 GREEK CAPITAL LETTER RHO
+ * 1D767 MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL
+ * 	0398 GREEK CAPITAL LETTER THETA
+ * 1D768 MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA
+ * 	03A3 GREEK CAPITAL LETTER SIGMA
+ * 1D769 MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU
+ * 	03A4 GREEK CAPITAL LETTER TAU
+ * 1D76A MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1D76B MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI
+ * 	03A6 GREEK CAPITAL LETTER PHI
+ * 1D76C MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI
+ * 	03A7 GREEK CAPITAL LETTER CHI
+ * 1D76D MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI
+ * 	03A8 GREEK CAPITAL LETTER PSI
+ * 1D76E MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1D76F MATHEMATICAL SANS-SERIF BOLD NABLA
+ * 	2207 NABLA
+ * 1D770 MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1D771 MATHEMATICAL SANS-SERIF BOLD SMALL BETA
+ * 	03B2 GREEK SMALL LETTER BETA
+ * 1D772 MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA
+ * 	03B3 GREEK SMALL LETTER GAMMA
+ * 1D773 MATHEMATICAL SANS-SERIF BOLD SMALL DELTA
+ * 	03B4 GREEK SMALL LETTER DELTA
+ * 1D774 MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1D775 MATHEMATICAL SANS-SERIF BOLD SMALL ZETA
+ * 	03B6 GREEK SMALL LETTER ZETA
+ * 1D776 MATHEMATICAL SANS-SERIF BOLD SMALL ETA
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1D777 MATHEMATICAL SANS-SERIF BOLD SMALL THETA
+ * 	03B8 GREEK SMALL LETTER THETA
+ * 1D778 MATHEMATICAL SANS-SERIF BOLD SMALL IOTA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1D779 MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA
+ * 	03BA GREEK SMALL LETTER KAPPA
+ * 1D77A MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA
+ * 	03BB GREEK SMALL LETTER LAMDA
+ * 1D77B MATHEMATICAL SANS-SERIF BOLD SMALL MU
+ * 	03BC GREEK SMALL LETTER MU
+ * 1D77C MATHEMATICAL SANS-SERIF BOLD SMALL NU
+ * 	03BD GREEK SMALL LETTER NU
+ * 1D77D MATHEMATICAL SANS-SERIF BOLD SMALL XI
+ * 	03BE GREEK SMALL LETTER XI
+ * 1D77E MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1D77F MATHEMATICAL SANS-SERIF BOLD SMALL PI
+ * 	03C0 GREEK SMALL LETTER PI
+ * 1D780 MATHEMATICAL SANS-SERIF BOLD SMALL RHO
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 1D781 MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA
+ * 	03C2 GREEK SMALL LETTER FINAL SIGMA
+ * 1D782 MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA
+ * 	03C3 GREEK SMALL LETTER SIGMA
+ * 1D783 MATHEMATICAL SANS-SERIF BOLD SMALL TAU
+ * 	03C4 GREEK SMALL LETTER TAU
+ * 1D784 MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1D785 MATHEMATICAL SANS-SERIF BOLD SMALL PHI
+ * 	03C6 GREEK SMALL LETTER PHI
+ * 1D786 MATHEMATICAL SANS-SERIF BOLD SMALL CHI
+ * 	03C7 GREEK SMALL LETTER CHI
+ * 1D787 MATHEMATICAL SANS-SERIF BOLD SMALL PSI
+ * 	03C8 GREEK SMALL LETTER PSI
+ * 1D788 MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1D789 MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL
+ * 	2202 PARTIAL DIFFERENTIAL
+ * 1D78A MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1D78B MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL
+ * 	03B8 GREEK SMALL LETTER THETA
+ * 1D78C MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL
+ * 	03BA GREEK SMALL LETTER KAPPA
+ * 1D78D MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL
+ * 	03C6 GREEK SMALL LETTER PHI
+ * 1D78E MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 1D78F MATHEMATICAL SANS-SERIF BOLD PI SYMBOL
+ * 	03C0 GREEK SMALL LETTER PI
+ * 1D790 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1D791 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA
+ * 	0392 GREEK CAPITAL LETTER BETA
+ * 1D792 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA
+ * 	0393 GREEK CAPITAL LETTER GAMMA
+ * 1D793 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA
+ * 	0394 GREEK CAPITAL LETTER DELTA
+ * 1D794 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1D795 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA
+ * 	0396 GREEK CAPITAL LETTER ZETA
+ * 1D796 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1D797 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA
+ * 	0398 GREEK CAPITAL LETTER THETA
+ * 1D798 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1D799 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA
+ * 	039A GREEK CAPITAL LETTER KAPPA
+ * 1D79A MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA
+ * 	039B GREEK CAPITAL LETTER LAMDA
+ * 1D79B MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU
+ * 	039C GREEK CAPITAL LETTER MU
+ * 1D79C MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU
+ * 	039D GREEK CAPITAL LETTER NU
+ * 1D79D MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI
+ * 	039E GREEK CAPITAL LETTER XI
+ * 1D79E MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1D79F MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI
+ * 	03A0 GREEK CAPITAL LETTER PI
+ * 1D7A0 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO
+ * 	03A1 GREEK CAPITAL LETTER RHO
+ * 1D7A1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL
+ * 	0398 GREEK CAPITAL LETTER THETA
+ * 1D7A2 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA
+ * 	03A3 GREEK CAPITAL LETTER SIGMA
+ * 1D7A3 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU
+ * 	03A4 GREEK CAPITAL LETTER TAU
+ * 1D7A4 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1D7A5 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI
+ * 	03A6 GREEK CAPITAL LETTER PHI
+ * 1D7A6 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI
+ * 	03A7 GREEK CAPITAL LETTER CHI
+ * 1D7A7 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI
+ * 	03A8 GREEK CAPITAL LETTER PSI
+ * 1D7A8 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1D7A9 MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA
+ * 	2207 NABLA
+ * 1D7AA MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1D7AB MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA
+ * 	03B2 GREEK SMALL LETTER BETA
+ * 1D7AC MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA
+ * 	03B3 GREEK SMALL LETTER GAMMA
+ * 1D7AD MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA
+ * 	03B4 GREEK SMALL LETTER DELTA
+ * 1D7AE MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1D7AF MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA
+ * 	03B6 GREEK SMALL LETTER ZETA
+ * 1D7B0 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1D7B1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA
+ * 	03B8 GREEK SMALL LETTER THETA
+ * 1D7B2 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1D7B3 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA
+ * 	03BA GREEK SMALL LETTER KAPPA
+ * 1D7B4 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA
+ * 	03BB GREEK SMALL LETTER LAMDA
+ * 1D7B5 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU
+ * 	03BC GREEK SMALL LETTER MU
+ * 1D7B6 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU
+ * 	03BD GREEK SMALL LETTER NU
+ * 1D7B7 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI
+ * 	03BE GREEK SMALL LETTER XI
+ * 1D7B8 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1D7B9 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI
+ * 	03C0 GREEK SMALL LETTER PI
+ * 1D7BA MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 1D7BB MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA
+ * 	03C2 GREEK SMALL LETTER FINAL SIGMA
+ * 1D7BC MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA
+ * 	03C3 GREEK SMALL LETTER SIGMA
+ * 1D7BD MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU
+ * 	03C4 GREEK SMALL LETTER TAU
+ * 1D7BE MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1D7BF MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI
+ * 	03C6 GREEK SMALL LETTER PHI
+ * 1D7C0 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI
+ * 	03C7 GREEK SMALL LETTER CHI
+ * 1D7C1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI
+ * 	03C8 GREEK SMALL LETTER PSI
+ * 1D7C2 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1D7C3 MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL
+ * 	2202 PARTIAL DIFFERENTIAL
+ * 1D7C4 MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1D7C5 MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL
+ * 	03B8 GREEK SMALL LETTER THETA
+ * 1D7C6 MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL
+ * 	03BA GREEK SMALL LETTER KAPPA
+ * 1D7C7 MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL
+ * 	03C6 GREEK SMALL LETTER PHI
+ * 1D7C8 MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 1D7C9 MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL
+ * 	03C0 GREEK SMALL LETTER PI
+ * 1D7CE MATHEMATICAL BOLD DIGIT ZERO
+ * 	0030 DIGIT ZERO
+ * 1D7CF MATHEMATICAL BOLD DIGIT ONE
+ * 	0031 DIGIT ONE
+ * 1D7D0 MATHEMATICAL BOLD DIGIT TWO
+ * 	0032 DIGIT TWO
+ * 1D7D1 MATHEMATICAL BOLD DIGIT THREE
+ * 	0033 DIGIT THREE
+ * 1D7D2 MATHEMATICAL BOLD DIGIT FOUR
+ * 	0034 DIGIT FOUR
+ * 1D7D3 MATHEMATICAL BOLD DIGIT FIVE
+ * 	0035 DIGIT FIVE
+ * 1D7D4 MATHEMATICAL BOLD DIGIT SIX
+ * 	0036 DIGIT SIX
+ * 1D7D5 MATHEMATICAL BOLD DIGIT SEVEN
+ * 	0037 DIGIT SEVEN
+ * 1D7D6 MATHEMATICAL BOLD DIGIT EIGHT
+ * 	0038 DIGIT EIGHT
+ * 1D7D7 MATHEMATICAL BOLD DIGIT NINE
+ * 	0039 DIGIT NINE
+ * 1D7D8 MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO
+ * 	0030 DIGIT ZERO
+ * 1D7D9 MATHEMATICAL DOUBLE-STRUCK DIGIT ONE
+ * 	0031 DIGIT ONE
+ * 1D7DA MATHEMATICAL DOUBLE-STRUCK DIGIT TWO
+ * 	0032 DIGIT TWO
+ * 1D7DB MATHEMATICAL DOUBLE-STRUCK DIGIT THREE
+ * 	0033 DIGIT THREE
+ * 1D7DC MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR
+ * 	0034 DIGIT FOUR
+ * 1D7DD MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE
+ * 	0035 DIGIT FIVE
+ * 1D7DE MATHEMATICAL DOUBLE-STRUCK DIGIT SIX
+ * 	0036 DIGIT SIX
+ * 1D7DF MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN
+ * 	0037 DIGIT SEVEN
+ * 1D7E0 MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT
+ * 	0038 DIGIT EIGHT
+ * 1D7E1 MATHEMATICAL DOUBLE-STRUCK DIGIT NINE
+ * 	0039 DIGIT NINE
+ * 1D7E2 MATHEMATICAL SANS-SERIF DIGIT ZERO
+ * 	0030 DIGIT ZERO
+ * 1D7E3 MATHEMATICAL SANS-SERIF DIGIT ONE
+ * 	0031 DIGIT ONE
+ * 1D7E4 MATHEMATICAL SANS-SERIF DIGIT TWO
+ * 	0032 DIGIT TWO
+ * 1D7E5 MATHEMATICAL SANS-SERIF DIGIT THREE
+ * 	0033 DIGIT THREE
+ * 1D7E6 MATHEMATICAL SANS-SERIF DIGIT FOUR
+ * 	0034 DIGIT FOUR
+ * 1D7E7 MATHEMATICAL SANS-SERIF DIGIT FIVE
+ * 	0035 DIGIT FIVE
+ * 1D7E8 MATHEMATICAL SANS-SERIF DIGIT SIX
+ * 	0036 DIGIT SIX
+ * 1D7E9 MATHEMATICAL SANS-SERIF DIGIT SEVEN
+ * 	0037 DIGIT SEVEN
+ * 1D7EA MATHEMATICAL SANS-SERIF DIGIT EIGHT
+ * 	0038 DIGIT EIGHT
+ * 1D7EB MATHEMATICAL SANS-SERIF DIGIT NINE
+ * 	0039 DIGIT NINE
+ * 1D7EC MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO
+ * 	0030 DIGIT ZERO
+ * 1D7ED MATHEMATICAL SANS-SERIF BOLD DIGIT ONE
+ * 	0031 DIGIT ONE
+ * 1D7EE MATHEMATICAL SANS-SERIF BOLD DIGIT TWO
+ * 	0032 DIGIT TWO
+ * 1D7EF MATHEMATICAL SANS-SERIF BOLD DIGIT THREE
+ * 	0033 DIGIT THREE
+ * 1D7F0 MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR
+ * 	0034 DIGIT FOUR
+ * 1D7F1 MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE
+ * 	0035 DIGIT FIVE
+ * 1D7F2 MATHEMATICAL SANS-SERIF BOLD DIGIT SIX
+ * 	0036 DIGIT SIX
+ * 1D7F3 MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN
+ * 	0037 DIGIT SEVEN
+ * 1D7F4 MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT
+ * 	0038 DIGIT EIGHT
+ * 1D7F5 MATHEMATICAL SANS-SERIF BOLD DIGIT NINE
+ * 	0039 DIGIT NINE
+ * 1D7F6 MATHEMATICAL MONOSPACE DIGIT ZERO
+ * 	0030 DIGIT ZERO
+ * 1D7F7 MATHEMATICAL MONOSPACE DIGIT ONE
+ * 	0031 DIGIT ONE
+ * 1D7F8 MATHEMATICAL MONOSPACE DIGIT TWO
+ * 	0032 DIGIT TWO
+ * 1D7F9 MATHEMATICAL MONOSPACE DIGIT THREE
+ * 	0033 DIGIT THREE
+ * 1D7FA MATHEMATICAL MONOSPACE DIGIT FOUR
+ * 	0034 DIGIT FOUR
+ * 1D7FB MATHEMATICAL MONOSPACE DIGIT FIVE
+ * 	0035 DIGIT FIVE
+ * 1D7FC MATHEMATICAL MONOSPACE DIGIT SIX
+ * 	0036 DIGIT SIX
+ * 1D7FD MATHEMATICAL MONOSPACE DIGIT SEVEN
+ * 	0037 DIGIT SEVEN
+ * 1D7FE MATHEMATICAL MONOSPACE DIGIT EIGHT
+ * 	0038 DIGIT EIGHT
+ * 1D7FF MATHEMATICAL MONOSPACE DIGIT NINE
+ * 	0039 DIGIT NINE
+ * 1E00 LATIN CAPITAL LETTER A WITH RING BELOW
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1E01 LATIN SMALL LETTER A WITH RING BELOW
+ * 	0061 LATIN SMALL LETTER A
+ * 1E02 LATIN CAPITAL LETTER B WITH DOT ABOVE
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1E03 LATIN SMALL LETTER B WITH DOT ABOVE
+ * 	0062 LATIN SMALL LETTER B
+ * 1E04 LATIN CAPITAL LETTER B WITH DOT BELOW
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1E05 LATIN SMALL LETTER B WITH DOT BELOW
+ * 	0062 LATIN SMALL LETTER B
+ * 1E06 LATIN CAPITAL LETTER B WITH LINE BELOW
+ * 	0042 LATIN CAPITAL LETTER B
+ * 1E07 LATIN SMALL LETTER B WITH LINE BELOW
+ * 	0062 LATIN SMALL LETTER B
+ * 1E08 LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE
+ * 	0043 LATIN CAPITAL LETTER C
+ * 1E09 LATIN SMALL LETTER C WITH CEDILLA AND ACUTE
+ * 	0063 LATIN SMALL LETTER C
+ * 1E0A LATIN CAPITAL LETTER D WITH DOT ABOVE
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1E0B LATIN SMALL LETTER D WITH DOT ABOVE
+ * 	0064 LATIN SMALL LETTER D
+ * 1E0C LATIN CAPITAL LETTER D WITH DOT BELOW
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1E0D LATIN SMALL LETTER D WITH DOT BELOW
+ * 	0064 LATIN SMALL LETTER D
+ * 1E0E LATIN CAPITAL LETTER D WITH LINE BELOW
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1E0F LATIN SMALL LETTER D WITH LINE BELOW
+ * 	0064 LATIN SMALL LETTER D
+ * 1E10 LATIN CAPITAL LETTER D WITH CEDILLA
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1E11 LATIN SMALL LETTER D WITH CEDILLA
+ * 	0064 LATIN SMALL LETTER D
+ * 1E12 LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW
+ * 	0044 LATIN CAPITAL LETTER D
+ * 1E13 LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW
+ * 	0064 LATIN SMALL LETTER D
+ * 1E14 LATIN CAPITAL LETTER E WITH MACRON AND GRAVE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1E15 LATIN SMALL LETTER E WITH MACRON AND GRAVE
+ * 	0065 LATIN SMALL LETTER E
+ * 1E16 LATIN CAPITAL LETTER E WITH MACRON AND ACUTE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1E17 LATIN SMALL LETTER E WITH MACRON AND ACUTE
+ * 	0065 LATIN SMALL LETTER E
+ * 1E18 LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1E19 LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW
+ * 	0065 LATIN SMALL LETTER E
+ * 1E1A LATIN CAPITAL LETTER E WITH TILDE BELOW
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1E1B LATIN SMALL LETTER E WITH TILDE BELOW
+ * 	0065 LATIN SMALL LETTER E
+ * 1E1C LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1E1D LATIN SMALL LETTER E WITH CEDILLA AND BREVE
+ * 	0065 LATIN SMALL LETTER E
+ * 1E1E LATIN CAPITAL LETTER F WITH DOT ABOVE
+ * 	0046 LATIN CAPITAL LETTER F
+ * 1E1F LATIN SMALL LETTER F WITH DOT ABOVE
+ * 	0066 LATIN SMALL LETTER F
+ * 1E20 LATIN CAPITAL LETTER G WITH MACRON
+ * 	0047 LATIN CAPITAL LETTER G
+ * 1E21 LATIN SMALL LETTER G WITH MACRON
+ * 	0067 LATIN SMALL LETTER G
+ * 1E22 LATIN CAPITAL LETTER H WITH DOT ABOVE
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1E23 LATIN SMALL LETTER H WITH DOT ABOVE
+ * 	0068 LATIN SMALL LETTER H
+ * 1E24 LATIN CAPITAL LETTER H WITH DOT BELOW
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1E25 LATIN SMALL LETTER H WITH DOT BELOW
+ * 	0068 LATIN SMALL LETTER H
+ * 1E26 LATIN CAPITAL LETTER H WITH DIAERESIS
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1E27 LATIN SMALL LETTER H WITH DIAERESIS
+ * 	0068 LATIN SMALL LETTER H
+ * 1E28 LATIN CAPITAL LETTER H WITH CEDILLA
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1E29 LATIN SMALL LETTER H WITH CEDILLA
+ * 	0068 LATIN SMALL LETTER H
+ * 1E2A LATIN CAPITAL LETTER H WITH BREVE BELOW
+ * 	0048 LATIN CAPITAL LETTER H
+ * 1E2B LATIN SMALL LETTER H WITH BREVE BELOW
+ * 	0068 LATIN SMALL LETTER H
+ * 1E2C LATIN CAPITAL LETTER I WITH TILDE BELOW
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1E2D LATIN SMALL LETTER I WITH TILDE BELOW
+ * 	0069 LATIN SMALL LETTER I
+ * 1E2E LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1E2F LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE
+ * 	0069 LATIN SMALL LETTER I
+ * 1E30 LATIN CAPITAL LETTER K WITH ACUTE
+ * 	004B LATIN CAPITAL LETTER K
+ * 1E31 LATIN SMALL LETTER K WITH ACUTE
+ * 	006B LATIN SMALL LETTER K
+ * 1E32 LATIN CAPITAL LETTER K WITH DOT BELOW
+ * 	004B LATIN CAPITAL LETTER K
+ * 1E33 LATIN SMALL LETTER K WITH DOT BELOW
+ * 	006B LATIN SMALL LETTER K
+ * 1E34 LATIN CAPITAL LETTER K WITH LINE BELOW
+ * 	004B LATIN CAPITAL LETTER K
+ * 1E35 LATIN SMALL LETTER K WITH LINE BELOW
+ * 	006B LATIN SMALL LETTER K
+ * 1E36 LATIN CAPITAL LETTER L WITH DOT BELOW
+ * 	004C LATIN CAPITAL LETTER L
+ * 1E37 LATIN SMALL LETTER L WITH DOT BELOW
+ * 	006C LATIN SMALL LETTER L
+ * 1E38 LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON
+ * 	004C LATIN CAPITAL LETTER L
+ * 1E39 LATIN SMALL LETTER L WITH DOT BELOW AND MACRON
+ * 	006C LATIN SMALL LETTER L
+ * 1E3A LATIN CAPITAL LETTER L WITH LINE BELOW
+ * 	004C LATIN CAPITAL LETTER L
+ * 1E3B LATIN SMALL LETTER L WITH LINE BELOW
+ * 	006C LATIN SMALL LETTER L
+ * 1E3C LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW
+ * 	004C LATIN CAPITAL LETTER L
+ * 1E3D LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW
+ * 	006C LATIN SMALL LETTER L
+ * 1E3E LATIN CAPITAL LETTER M WITH ACUTE
+ * 	004D LATIN CAPITAL LETTER M
+ * 1E3F LATIN SMALL LETTER M WITH ACUTE
+ * 	006D LATIN SMALL LETTER M
+ * 1E40 LATIN CAPITAL LETTER M WITH DOT ABOVE
+ * 	004D LATIN CAPITAL LETTER M
+ * 1E41 LATIN SMALL LETTER M WITH DOT ABOVE
+ * 	006D LATIN SMALL LETTER M
+ * 1E42 LATIN CAPITAL LETTER M WITH DOT BELOW
+ * 	004D LATIN CAPITAL LETTER M
+ * 1E43 LATIN SMALL LETTER M WITH DOT BELOW
+ * 	006D LATIN SMALL LETTER M
+ * 1E44 LATIN CAPITAL LETTER N WITH DOT ABOVE
+ * 	004E LATIN CAPITAL LETTER N
+ * 1E45 LATIN SMALL LETTER N WITH DOT ABOVE
+ * 	006E LATIN SMALL LETTER N
+ * 1E46 LATIN CAPITAL LETTER N WITH DOT BELOW
+ * 	004E LATIN CAPITAL LETTER N
+ * 1E47 LATIN SMALL LETTER N WITH DOT BELOW
+ * 	006E LATIN SMALL LETTER N
+ * 1E48 LATIN CAPITAL LETTER N WITH LINE BELOW
+ * 	004E LATIN CAPITAL LETTER N
+ * 1E49 LATIN SMALL LETTER N WITH LINE BELOW
+ * 	006E LATIN SMALL LETTER N
+ * 1E4A LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW
+ * 	004E LATIN CAPITAL LETTER N
+ * 1E4B LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW
+ * 	006E LATIN SMALL LETTER N
+ * 1E4C LATIN CAPITAL LETTER O WITH TILDE AND ACUTE
+ * 	004F LATIN CAPITAL LETTER O
+ * 1E4D LATIN SMALL LETTER O WITH TILDE AND ACUTE
+ * 	006F LATIN SMALL LETTER O
+ * 1E4E LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS
+ * 	004F LATIN CAPITAL LETTER O
+ * 1E4F LATIN SMALL LETTER O WITH TILDE AND DIAERESIS
+ * 	006F LATIN SMALL LETTER O
+ * 1E50 LATIN CAPITAL LETTER O WITH MACRON AND GRAVE
+ * 	004F LATIN CAPITAL LETTER O
+ * 1E51 LATIN SMALL LETTER O WITH MACRON AND GRAVE
+ * 	006F LATIN SMALL LETTER O
+ * 1E52 LATIN CAPITAL LETTER O WITH MACRON AND ACUTE
+ * 	004F LATIN CAPITAL LETTER O
+ * 1E53 LATIN SMALL LETTER O WITH MACRON AND ACUTE
+ * 	006F LATIN SMALL LETTER O
+ * 1E54 LATIN CAPITAL LETTER P WITH ACUTE
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1E55 LATIN SMALL LETTER P WITH ACUTE
+ * 	0070 LATIN SMALL LETTER P
+ * 1E56 LATIN CAPITAL LETTER P WITH DOT ABOVE
+ * 	0050 LATIN CAPITAL LETTER P
+ * 1E57 LATIN SMALL LETTER P WITH DOT ABOVE
+ * 	0070 LATIN SMALL LETTER P
+ * 1E58 LATIN CAPITAL LETTER R WITH DOT ABOVE
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1E59 LATIN SMALL LETTER R WITH DOT ABOVE
+ * 	0072 LATIN SMALL LETTER R
+ * 1E5A LATIN CAPITAL LETTER R WITH DOT BELOW
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1E5B LATIN SMALL LETTER R WITH DOT BELOW
+ * 	0072 LATIN SMALL LETTER R
+ * 1E5C LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1E5D LATIN SMALL LETTER R WITH DOT BELOW AND MACRON
+ * 	0072 LATIN SMALL LETTER R
+ * 1E5E LATIN CAPITAL LETTER R WITH LINE BELOW
+ * 	0052 LATIN CAPITAL LETTER R
+ * 1E5F LATIN SMALL LETTER R WITH LINE BELOW
+ * 	0072 LATIN SMALL LETTER R
+ * 1E60 LATIN CAPITAL LETTER S WITH DOT ABOVE
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1E61 LATIN SMALL LETTER S WITH DOT ABOVE
+ * 	0073 LATIN SMALL LETTER S
+ * 1E62 LATIN CAPITAL LETTER S WITH DOT BELOW
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1E63 LATIN SMALL LETTER S WITH DOT BELOW
+ * 	0073 LATIN SMALL LETTER S
+ * 1E64 LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1E65 LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE
+ * 	0073 LATIN SMALL LETTER S
+ * 1E66 LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1E67 LATIN SMALL LETTER S WITH CARON AND DOT ABOVE
+ * 	0073 LATIN SMALL LETTER S
+ * 1E68 LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE
+ * 	0053 LATIN CAPITAL LETTER S
+ * 1E69 LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE
+ * 	0073 LATIN SMALL LETTER S
+ * 1E6A LATIN CAPITAL LETTER T WITH DOT ABOVE
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1E6B LATIN SMALL LETTER T WITH DOT ABOVE
+ * 	0074 LATIN SMALL LETTER T
+ * 1E6C LATIN CAPITAL LETTER T WITH DOT BELOW
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1E6D LATIN SMALL LETTER T WITH DOT BELOW
+ * 	0074 LATIN SMALL LETTER T
+ * 1E6E LATIN CAPITAL LETTER T WITH LINE BELOW
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1E6F LATIN SMALL LETTER T WITH LINE BELOW
+ * 	0074 LATIN SMALL LETTER T
+ * 1E70 LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW
+ * 	0054 LATIN CAPITAL LETTER T
+ * 1E71 LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW
+ * 	0074 LATIN SMALL LETTER T
+ * 1E72 LATIN CAPITAL LETTER U WITH DIAERESIS BELOW
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1E73 LATIN SMALL LETTER U WITH DIAERESIS BELOW
+ * 	0075 LATIN SMALL LETTER U
+ * 1E74 LATIN CAPITAL LETTER U WITH TILDE BELOW
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1E75 LATIN SMALL LETTER U WITH TILDE BELOW
+ * 	0075 LATIN SMALL LETTER U
+ * 1E76 LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1E77 LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW
+ * 	0075 LATIN SMALL LETTER U
+ * 1E78 LATIN CAPITAL LETTER U WITH TILDE AND ACUTE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1E79 LATIN SMALL LETTER U WITH TILDE AND ACUTE
+ * 	0075 LATIN SMALL LETTER U
+ * 1E7A LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1E7B LATIN SMALL LETTER U WITH MACRON AND DIAERESIS
+ * 	0075 LATIN SMALL LETTER U
+ * 1E7C LATIN CAPITAL LETTER V WITH TILDE
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1E7D LATIN SMALL LETTER V WITH TILDE
+ * 	0076 LATIN SMALL LETTER V
+ * 1E7E LATIN CAPITAL LETTER V WITH DOT BELOW
+ * 	0056 LATIN CAPITAL LETTER V
+ * 1E7F LATIN SMALL LETTER V WITH DOT BELOW
+ * 	0076 LATIN SMALL LETTER V
+ * 1E80 LATIN CAPITAL LETTER W WITH GRAVE
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1E81 LATIN SMALL LETTER W WITH GRAVE
+ * 	0077 LATIN SMALL LETTER W
+ * 1E82 LATIN CAPITAL LETTER W WITH ACUTE
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1E83 LATIN SMALL LETTER W WITH ACUTE
+ * 	0077 LATIN SMALL LETTER W
+ * 1E84 LATIN CAPITAL LETTER W WITH DIAERESIS
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1E85 LATIN SMALL LETTER W WITH DIAERESIS
+ * 	0077 LATIN SMALL LETTER W
+ * 1E86 LATIN CAPITAL LETTER W WITH DOT ABOVE
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1E87 LATIN SMALL LETTER W WITH DOT ABOVE
+ * 	0077 LATIN SMALL LETTER W
+ * 1E88 LATIN CAPITAL LETTER W WITH DOT BELOW
+ * 	0057 LATIN CAPITAL LETTER W
+ * 1E89 LATIN SMALL LETTER W WITH DOT BELOW
+ * 	0077 LATIN SMALL LETTER W
+ * 1E8A LATIN CAPITAL LETTER X WITH DOT ABOVE
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1E8B LATIN SMALL LETTER X WITH DOT ABOVE
+ * 	0078 LATIN SMALL LETTER X
+ * 1E8C LATIN CAPITAL LETTER X WITH DIAERESIS
+ * 	0058 LATIN CAPITAL LETTER X
+ * 1E8D LATIN SMALL LETTER X WITH DIAERESIS
+ * 	0078 LATIN SMALL LETTER X
+ * 1E8E LATIN CAPITAL LETTER Y WITH DOT ABOVE
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1E8F LATIN SMALL LETTER Y WITH DOT ABOVE
+ * 	0079 LATIN SMALL LETTER Y
+ * 1E90 LATIN CAPITAL LETTER Z WITH CIRCUMFLEX
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1E91 LATIN SMALL LETTER Z WITH CIRCUMFLEX
+ * 	007A LATIN SMALL LETTER Z
+ * 1E92 LATIN CAPITAL LETTER Z WITH DOT BELOW
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1E93 LATIN SMALL LETTER Z WITH DOT BELOW
+ * 	007A LATIN SMALL LETTER Z
+ * 1E94 LATIN CAPITAL LETTER Z WITH LINE BELOW
+ * 	005A LATIN CAPITAL LETTER Z
+ * 1E95 LATIN SMALL LETTER Z WITH LINE BELOW
+ * 	007A LATIN SMALL LETTER Z
+ * 1E96 LATIN SMALL LETTER H WITH LINE BELOW
+ * 	0068 LATIN SMALL LETTER H
+ * 1E97 LATIN SMALL LETTER T WITH DIAERESIS
+ * 	0074 LATIN SMALL LETTER T
+ * 1E98 LATIN SMALL LETTER W WITH RING ABOVE
+ * 	0077 LATIN SMALL LETTER W
+ * 1E99 LATIN SMALL LETTER Y WITH RING ABOVE
+ * 	0079 LATIN SMALL LETTER Y
+ * 1E9A LATIN SMALL LETTER A WITH RIGHT HALF RING
+ * 	0061 LATIN SMALL LETTER A
+ * 	02BE MODIFIER LETTER RIGHT HALF RING
+ * 1E9B LATIN SMALL LETTER LONG S WITH DOT ABOVE
+ * 	0073 LATIN SMALL LETTER S
+ * 1EA0 LATIN CAPITAL LETTER A WITH DOT BELOW
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1EA1 LATIN SMALL LETTER A WITH DOT BELOW
+ * 	0061 LATIN SMALL LETTER A
+ * 1EA2 LATIN CAPITAL LETTER A WITH HOOK ABOVE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1EA3 LATIN SMALL LETTER A WITH HOOK ABOVE
+ * 	0061 LATIN SMALL LETTER A
+ * 1EA4 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1EA5 LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
+ * 	0061 LATIN SMALL LETTER A
+ * 1EA6 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1EA7 LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE
+ * 	0061 LATIN SMALL LETTER A
+ * 1EA8 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1EA9 LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
+ * 	0061 LATIN SMALL LETTER A
+ * 1EAA LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1EAB LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE
+ * 	0061 LATIN SMALL LETTER A
+ * 1EAC LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1EAD LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW
+ * 	0061 LATIN SMALL LETTER A
+ * 1EAE LATIN CAPITAL LETTER A WITH BREVE AND ACUTE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1EAF LATIN SMALL LETTER A WITH BREVE AND ACUTE
+ * 	0061 LATIN SMALL LETTER A
+ * 1EB0 LATIN CAPITAL LETTER A WITH BREVE AND GRAVE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1EB1 LATIN SMALL LETTER A WITH BREVE AND GRAVE
+ * 	0061 LATIN SMALL LETTER A
+ * 1EB2 LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1EB3 LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE
+ * 	0061 LATIN SMALL LETTER A
+ * 1EB4 LATIN CAPITAL LETTER A WITH BREVE AND TILDE
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1EB5 LATIN SMALL LETTER A WITH BREVE AND TILDE
+ * 	0061 LATIN SMALL LETTER A
+ * 1EB6 LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW
+ * 	0041 LATIN CAPITAL LETTER A
+ * 1EB7 LATIN SMALL LETTER A WITH BREVE AND DOT BELOW
+ * 	0061 LATIN SMALL LETTER A
+ * 1EB8 LATIN CAPITAL LETTER E WITH DOT BELOW
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1EB9 LATIN SMALL LETTER E WITH DOT BELOW
+ * 	0065 LATIN SMALL LETTER E
+ * 1EBA LATIN CAPITAL LETTER E WITH HOOK ABOVE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1EBB LATIN SMALL LETTER E WITH HOOK ABOVE
+ * 	0065 LATIN SMALL LETTER E
+ * 1EBC LATIN CAPITAL LETTER E WITH TILDE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1EBD LATIN SMALL LETTER E WITH TILDE
+ * 	0065 LATIN SMALL LETTER E
+ * 1EBE LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1EBF LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE
+ * 	0065 LATIN SMALL LETTER E
+ * 1EC0 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1EC1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE
+ * 	0065 LATIN SMALL LETTER E
+ * 1EC2 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1EC3 LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+ * 	0065 LATIN SMALL LETTER E
+ * 1EC4 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1EC5 LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE
+ * 	0065 LATIN SMALL LETTER E
+ * 1EC6 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+ * 	0045 LATIN CAPITAL LETTER E
+ * 1EC7 LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+ * 	0065 LATIN SMALL LETTER E
+ * 1EC8 LATIN CAPITAL LETTER I WITH HOOK ABOVE
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1EC9 LATIN SMALL LETTER I WITH HOOK ABOVE
+ * 	0069 LATIN SMALL LETTER I
+ * 1ECA LATIN CAPITAL LETTER I WITH DOT BELOW
+ * 	0049 LATIN CAPITAL LETTER I
+ * 1ECB LATIN SMALL LETTER I WITH DOT BELOW
+ * 	0069 LATIN SMALL LETTER I
+ * 1ECC LATIN CAPITAL LETTER O WITH DOT BELOW
+ * 	004F LATIN CAPITAL LETTER O
+ * 1ECD LATIN SMALL LETTER O WITH DOT BELOW
+ * 	006F LATIN SMALL LETTER O
+ * 1ECE LATIN CAPITAL LETTER O WITH HOOK ABOVE
+ * 	004F LATIN CAPITAL LETTER O
+ * 1ECF LATIN SMALL LETTER O WITH HOOK ABOVE
+ * 	006F LATIN SMALL LETTER O
+ * 1ED0 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE
+ * 	004F LATIN CAPITAL LETTER O
+ * 1ED1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE
+ * 	006F LATIN SMALL LETTER O
+ * 1ED2 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE
+ * 	004F LATIN CAPITAL LETTER O
+ * 1ED3 LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE
+ * 	006F LATIN SMALL LETTER O
+ * 1ED4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
+ * 	004F LATIN CAPITAL LETTER O
+ * 1ED5 LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
+ * 	006F LATIN SMALL LETTER O
+ * 1ED6 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE
+ * 	004F LATIN CAPITAL LETTER O
+ * 1ED7 LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE
+ * 	006F LATIN SMALL LETTER O
+ * 1ED8 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW
+ * 	004F LATIN CAPITAL LETTER O
+ * 1ED9 LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW
+ * 	006F LATIN SMALL LETTER O
+ * 1EDA LATIN CAPITAL LETTER O WITH HORN AND ACUTE
+ * 	004F LATIN CAPITAL LETTER O
+ * 1EDB LATIN SMALL LETTER O WITH HORN AND ACUTE
+ * 	006F LATIN SMALL LETTER O
+ * 1EDC LATIN CAPITAL LETTER O WITH HORN AND GRAVE
+ * 	004F LATIN CAPITAL LETTER O
+ * 1EDD LATIN SMALL LETTER O WITH HORN AND GRAVE
+ * 	006F LATIN SMALL LETTER O
+ * 1EDE LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE
+ * 	004F LATIN CAPITAL LETTER O
+ * 1EDF LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE
+ * 	006F LATIN SMALL LETTER O
+ * 1EE0 LATIN CAPITAL LETTER O WITH HORN AND TILDE
+ * 	004F LATIN CAPITAL LETTER O
+ * 1EE1 LATIN SMALL LETTER O WITH HORN AND TILDE
+ * 	006F LATIN SMALL LETTER O
+ * 1EE2 LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW
+ * 	004F LATIN CAPITAL LETTER O
+ * 1EE3 LATIN SMALL LETTER O WITH HORN AND DOT BELOW
+ * 	006F LATIN SMALL LETTER O
+ * 1EE4 LATIN CAPITAL LETTER U WITH DOT BELOW
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1EE5 LATIN SMALL LETTER U WITH DOT BELOW
+ * 	0075 LATIN SMALL LETTER U
+ * 1EE6 LATIN CAPITAL LETTER U WITH HOOK ABOVE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1EE7 LATIN SMALL LETTER U WITH HOOK ABOVE
+ * 	0075 LATIN SMALL LETTER U
+ * 1EE8 LATIN CAPITAL LETTER U WITH HORN AND ACUTE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1EE9 LATIN SMALL LETTER U WITH HORN AND ACUTE
+ * 	0075 LATIN SMALL LETTER U
+ * 1EEA LATIN CAPITAL LETTER U WITH HORN AND GRAVE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1EEB LATIN SMALL LETTER U WITH HORN AND GRAVE
+ * 	0075 LATIN SMALL LETTER U
+ * 1EEC LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1EED LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE
+ * 	0075 LATIN SMALL LETTER U
+ * 1EEE LATIN CAPITAL LETTER U WITH HORN AND TILDE
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1EEF LATIN SMALL LETTER U WITH HORN AND TILDE
+ * 	0075 LATIN SMALL LETTER U
+ * 1EF0 LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW
+ * 	0055 LATIN CAPITAL LETTER U
+ * 1EF1 LATIN SMALL LETTER U WITH HORN AND DOT BELOW
+ * 	0075 LATIN SMALL LETTER U
+ * 1EF2 LATIN CAPITAL LETTER Y WITH GRAVE
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1EF3 LATIN SMALL LETTER Y WITH GRAVE
+ * 	0079 LATIN SMALL LETTER Y
+ * 1EF4 LATIN CAPITAL LETTER Y WITH DOT BELOW
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1EF5 LATIN SMALL LETTER Y WITH DOT BELOW
+ * 	0079 LATIN SMALL LETTER Y
+ * 1EF6 LATIN CAPITAL LETTER Y WITH HOOK ABOVE
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1EF7 LATIN SMALL LETTER Y WITH HOOK ABOVE
+ * 	0079 LATIN SMALL LETTER Y
+ * 1EF8 LATIN CAPITAL LETTER Y WITH TILDE
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 1EF9 LATIN SMALL LETTER Y WITH TILDE
+ * 	0079 LATIN SMALL LETTER Y
+ * 1F00 GREEK SMALL LETTER ALPHA WITH PSILI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F01 GREEK SMALL LETTER ALPHA WITH DASIA
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F02 GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F03 GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F04 GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F05 GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F06 GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F07 GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F08 GREEK CAPITAL LETTER ALPHA WITH PSILI
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F09 GREEK CAPITAL LETTER ALPHA WITH DASIA
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F0A GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F0B GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F0C GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F0D GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F0E GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F0F GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F10 GREEK SMALL LETTER EPSILON WITH PSILI
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1F11 GREEK SMALL LETTER EPSILON WITH DASIA
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1F12 GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1F13 GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1F14 GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1F15 GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1F18 GREEK CAPITAL LETTER EPSILON WITH PSILI
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1F19 GREEK CAPITAL LETTER EPSILON WITH DASIA
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1F1A GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1F1B GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1F1C GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1F1D GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1F20 GREEK SMALL LETTER ETA WITH PSILI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F21 GREEK SMALL LETTER ETA WITH DASIA
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F22 GREEK SMALL LETTER ETA WITH PSILI AND VARIA
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F23 GREEK SMALL LETTER ETA WITH DASIA AND VARIA
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F24 GREEK SMALL LETTER ETA WITH PSILI AND OXIA
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F25 GREEK SMALL LETTER ETA WITH DASIA AND OXIA
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F26 GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F27 GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F28 GREEK CAPITAL LETTER ETA WITH PSILI
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F29 GREEK CAPITAL LETTER ETA WITH DASIA
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F2A GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F2B GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F2C GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F2D GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F2E GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F2F GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F30 GREEK SMALL LETTER IOTA WITH PSILI
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1F31 GREEK SMALL LETTER IOTA WITH DASIA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1F32 GREEK SMALL LETTER IOTA WITH PSILI AND VARIA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1F33 GREEK SMALL LETTER IOTA WITH DASIA AND VARIA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1F34 GREEK SMALL LETTER IOTA WITH PSILI AND OXIA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1F35 GREEK SMALL LETTER IOTA WITH DASIA AND OXIA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1F36 GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1F37 GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1F38 GREEK CAPITAL LETTER IOTA WITH PSILI
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1F39 GREEK CAPITAL LETTER IOTA WITH DASIA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1F3A GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1F3B GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1F3C GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1F3D GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1F3E GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1F3F GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1F40 GREEK SMALL LETTER OMICRON WITH PSILI
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1F41 GREEK SMALL LETTER OMICRON WITH DASIA
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1F42 GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1F43 GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1F44 GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1F45 GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1F48 GREEK CAPITAL LETTER OMICRON WITH PSILI
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1F49 GREEK CAPITAL LETTER OMICRON WITH DASIA
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1F4A GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1F4B GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1F4C GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1F4D GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1F50 GREEK SMALL LETTER UPSILON WITH PSILI
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1F51 GREEK SMALL LETTER UPSILON WITH DASIA
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1F52 GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1F53 GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1F54 GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1F55 GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1F56 GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1F57 GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1F59 GREEK CAPITAL LETTER UPSILON WITH DASIA
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1F5B GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1F5D GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1F5F GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1F60 GREEK SMALL LETTER OMEGA WITH PSILI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1F61 GREEK SMALL LETTER OMEGA WITH DASIA
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1F62 GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1F63 GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1F64 GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1F65 GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1F66 GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1F67 GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1F68 GREEK CAPITAL LETTER OMEGA WITH PSILI
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1F69 GREEK CAPITAL LETTER OMEGA WITH DASIA
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1F6A GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1F6B GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1F6C GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1F6D GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1F6E GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1F6F GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1F70 GREEK SMALL LETTER ALPHA WITH VARIA
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F71 GREEK SMALL LETTER ALPHA WITH OXIA
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F72 GREEK SMALL LETTER EPSILON WITH VARIA
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1F73 GREEK SMALL LETTER EPSILON WITH OXIA
+ * 	03B5 GREEK SMALL LETTER EPSILON
+ * 1F74 GREEK SMALL LETTER ETA WITH VARIA
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F75 GREEK SMALL LETTER ETA WITH OXIA
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F76 GREEK SMALL LETTER IOTA WITH VARIA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1F77 GREEK SMALL LETTER IOTA WITH OXIA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1F78 GREEK SMALL LETTER OMICRON WITH VARIA
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1F79 GREEK SMALL LETTER OMICRON WITH OXIA
+ * 	03BF GREEK SMALL LETTER OMICRON
+ * 1F7A GREEK SMALL LETTER UPSILON WITH VARIA
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1F7B GREEK SMALL LETTER UPSILON WITH OXIA
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1F7C GREEK SMALL LETTER OMEGA WITH VARIA
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1F7D GREEK SMALL LETTER OMEGA WITH OXIA
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1F80 GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F81 GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F82 GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F83 GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F84 GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F85 GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F86 GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F87 GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1F88 GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F89 GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F8A GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F8B GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F8C GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F8D GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F8E GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F8F GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1F90 GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F91 GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F92 GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F93 GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F94 GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F95 GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F96 GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F97 GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1F98 GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F99 GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F9A GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F9B GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F9C GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F9D GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F9E GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1F9F GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1FA0 GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FA1 GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FA2 GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FA3 GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FA4 GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FA5 GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FA6 GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FA7 GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FA8 GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1FA9 GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1FAA GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1FAB GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1FAC GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1FAD GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1FAE GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1FAF GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1FB0 GREEK SMALL LETTER ALPHA WITH VRACHY
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1FB1 GREEK SMALL LETTER ALPHA WITH MACRON
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1FB2 GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1FB3 GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1FB4 GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1FB6 GREEK SMALL LETTER ALPHA WITH PERISPOMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1FB7 GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI
+ * 	03B1 GREEK SMALL LETTER ALPHA
+ * 1FB8 GREEK CAPITAL LETTER ALPHA WITH VRACHY
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1FB9 GREEK CAPITAL LETTER ALPHA WITH MACRON
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1FBA GREEK CAPITAL LETTER ALPHA WITH VARIA
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1FBB GREEK CAPITAL LETTER ALPHA WITH OXIA
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1FBC GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
+ * 	0391 GREEK CAPITAL LETTER ALPHA
+ * 1FBD GREEK KORONIS
+ * 	0020 SPACE
+ * 1FBE GREEK PROSGEGRAMMENI
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1FBF GREEK PSILI
+ * 	0020 SPACE
+ * 1FC0 GREEK PERISPOMENI
+ * 	0020 SPACE
+ * 1FC1 GREEK DIALYTIKA AND PERISPOMENI
+ * 	0020 SPACE
+ * 1FC2 GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1FC3 GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1FC4 GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1FC6 GREEK SMALL LETTER ETA WITH PERISPOMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1FC7 GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI
+ * 	03B7 GREEK SMALL LETTER ETA
+ * 1FC8 GREEK CAPITAL LETTER EPSILON WITH VARIA
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1FC9 GREEK CAPITAL LETTER EPSILON WITH OXIA
+ * 	0395 GREEK CAPITAL LETTER EPSILON
+ * 1FCA GREEK CAPITAL LETTER ETA WITH VARIA
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1FCB GREEK CAPITAL LETTER ETA WITH OXIA
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1FCC GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
+ * 	0397 GREEK CAPITAL LETTER ETA
+ * 1FCD GREEK PSILI AND VARIA
+ * 	0020 SPACE
+ * 1FCE GREEK PSILI AND OXIA
+ * 	0020 SPACE
+ * 1FCF GREEK PSILI AND PERISPOMENI
+ * 	0020 SPACE
+ * 1FD0 GREEK SMALL LETTER IOTA WITH VRACHY
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1FD1 GREEK SMALL LETTER IOTA WITH MACRON
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1FD2 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1FD3 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1FD6 GREEK SMALL LETTER IOTA WITH PERISPOMENI
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1FD7 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI
+ * 	03B9 GREEK SMALL LETTER IOTA
+ * 1FD8 GREEK CAPITAL LETTER IOTA WITH VRACHY
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1FD9 GREEK CAPITAL LETTER IOTA WITH MACRON
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1FDA GREEK CAPITAL LETTER IOTA WITH VARIA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1FDB GREEK CAPITAL LETTER IOTA WITH OXIA
+ * 	0399 GREEK CAPITAL LETTER IOTA
+ * 1FDD GREEK DASIA AND VARIA
+ * 	0020 SPACE
+ * 1FDE GREEK DASIA AND OXIA
+ * 	0020 SPACE
+ * 1FDF GREEK DASIA AND PERISPOMENI
+ * 	0020 SPACE
+ * 1FE0 GREEK SMALL LETTER UPSILON WITH VRACHY
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1FE1 GREEK SMALL LETTER UPSILON WITH MACRON
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1FE2 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1FE3 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1FE4 GREEK SMALL LETTER RHO WITH PSILI
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 1FE5 GREEK SMALL LETTER RHO WITH DASIA
+ * 	03C1 GREEK SMALL LETTER RHO
+ * 1FE6 GREEK SMALL LETTER UPSILON WITH PERISPOMENI
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1FE7 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI
+ * 	03C5 GREEK SMALL LETTER UPSILON
+ * 1FE8 GREEK CAPITAL LETTER UPSILON WITH VRACHY
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1FE9 GREEK CAPITAL LETTER UPSILON WITH MACRON
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1FEA GREEK CAPITAL LETTER UPSILON WITH VARIA
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1FEB GREEK CAPITAL LETTER UPSILON WITH OXIA
+ * 	03A5 GREEK CAPITAL LETTER UPSILON
+ * 1FEC GREEK CAPITAL LETTER RHO WITH DASIA
+ * 	03A1 GREEK CAPITAL LETTER RHO
+ * 1FED GREEK DIALYTIKA AND VARIA
+ * 	0020 SPACE
+ * 1FEE GREEK DIALYTIKA AND OXIA
+ * 	0020 SPACE
+ * 1FEF GREEK VARIA
+ * 	0060 GRAVE ACCENT
+ * 1FF2 GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FF3 GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FF4 GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FF6 GREEK SMALL LETTER OMEGA WITH PERISPOMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FF7 GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI
+ * 	03C9 GREEK SMALL LETTER OMEGA
+ * 1FF8 GREEK CAPITAL LETTER OMICRON WITH VARIA
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1FF9 GREEK CAPITAL LETTER OMICRON WITH OXIA
+ * 	039F GREEK CAPITAL LETTER OMICRON
+ * 1FFA GREEK CAPITAL LETTER OMEGA WITH VARIA
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1FFB GREEK CAPITAL LETTER OMEGA WITH OXIA
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1FFC GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 1FFD GREEK OXIA
+ * 	0020 SPACE
+ * 1FFE GREEK DASIA
+ * 	0020 SPACE
+ * 2000 EN QUAD
+ * 	0020 SPACE
+ * 2001 EM QUAD
+ * 	0020 SPACE
+ * 2002 EN SPACE
+ * 	0020 SPACE
+ * 2003 EM SPACE
+ * 	0020 SPACE
+ * 2004 THREE-PER-EM SPACE
+ * 	0020 SPACE
+ * 2005 FOUR-PER-EM SPACE
+ * 	0020 SPACE
+ * 2006 SIX-PER-EM SPACE
+ * 	0020 SPACE
+ * 2007 FIGURE SPACE
+ * 	0020 SPACE
+ * 2008 PUNCTUATION SPACE
+ * 	0020 SPACE
+ * 2009 THIN SPACE
+ * 	0020 SPACE
+ * 200A HAIR SPACE
+ * 	0020 SPACE
+ * 2011 NON-BREAKING HYPHEN
+ * 	2010 HYPHEN
+ * 2017 DOUBLE LOW LINE
+ * 	0020 SPACE
+ * 2024 ONE DOT LEADER
+ * 	002E FULL STOP
+ * 2025 TWO DOT LEADER
+ * 	002E FULL STOP
+ * 	002E FULL STOP
+ * 2026 HORIZONTAL ELLIPSIS
+ * 	002E FULL STOP
+ * 	002E FULL STOP
+ * 	002E FULL STOP
+ * 202F NARROW NO-BREAK SPACE
+ * 	0020 SPACE
+ * 2033 DOUBLE PRIME
+ * 	2032 PRIME
+ * 	2032 PRIME
+ * 2034 TRIPLE PRIME
+ * 	2032 PRIME
+ * 	2032 PRIME
+ * 	2032 PRIME
+ * 2036 REVERSED DOUBLE PRIME
+ * 	2035 REVERSED PRIME
+ * 	2035 REVERSED PRIME
+ * 2037 REVERSED TRIPLE PRIME
+ * 	2035 REVERSED PRIME
+ * 	2035 REVERSED PRIME
+ * 	2035 REVERSED PRIME
+ * 203C DOUBLE EXCLAMATION MARK
+ * 	0021 EXCLAMATION MARK
+ * 	0021 EXCLAMATION MARK
+ * 203E OVERLINE
+ * 	0020 SPACE
+ * 2047 DOUBLE QUESTION MARK
+ * 	003F QUESTION MARK
+ * 	003F QUESTION MARK
+ * 2048 QUESTION EXCLAMATION MARK
+ * 	003F QUESTION MARK
+ * 	0021 EXCLAMATION MARK
+ * 2049 EXCLAMATION QUESTION MARK
+ * 	0021 EXCLAMATION MARK
+ * 	003F QUESTION MARK
+ * 2057 QUADRUPLE PRIME
+ * 	2032 PRIME
+ * 	2032 PRIME
+ * 	2032 PRIME
+ * 	2032 PRIME
+ * 205F MEDIUM MATHEMATICAL SPACE
+ * 	0020 SPACE
+ * 2070 SUPERSCRIPT ZERO
+ * 	0030 DIGIT ZERO
+ * 2071 SUPERSCRIPT LATIN SMALL LETTER I
+ * 	0069 LATIN SMALL LETTER I
+ * 2074 SUPERSCRIPT FOUR
+ * 	0034 DIGIT FOUR
+ * 2075 SUPERSCRIPT FIVE
+ * 	0035 DIGIT FIVE
+ * 2076 SUPERSCRIPT SIX
+ * 	0036 DIGIT SIX
+ * 2077 SUPERSCRIPT SEVEN
+ * 	0037 DIGIT SEVEN
+ * 2078 SUPERSCRIPT EIGHT
+ * 	0038 DIGIT EIGHT
+ * 2079 SUPERSCRIPT NINE
+ * 	0039 DIGIT NINE
+ * 207A SUPERSCRIPT PLUS SIGN
+ * 	002B PLUS SIGN
+ * 207B SUPERSCRIPT MINUS
+ * 	2212 MINUS SIGN
+ * 207C SUPERSCRIPT EQUALS SIGN
+ * 	003D EQUALS SIGN
+ * 207D SUPERSCRIPT LEFT PARENTHESIS
+ * 	0028 LEFT PARENTHESIS
+ * 207E SUPERSCRIPT RIGHT PARENTHESIS
+ * 	0029 RIGHT PARENTHESIS
+ * 207F SUPERSCRIPT LATIN SMALL LETTER N
+ * 	006E LATIN SMALL LETTER N
+ * 2080 SUBSCRIPT ZERO
+ * 	0030 DIGIT ZERO
+ * 2081 SUBSCRIPT ONE
+ * 	0031 DIGIT ONE
+ * 2082 SUBSCRIPT TWO
+ * 	0032 DIGIT TWO
+ * 2083 SUBSCRIPT THREE
+ * 	0033 DIGIT THREE
+ * 2084 SUBSCRIPT FOUR
+ * 	0034 DIGIT FOUR
+ * 2085 SUBSCRIPT FIVE
+ * 	0035 DIGIT FIVE
+ * 2086 SUBSCRIPT SIX
+ * 	0036 DIGIT SIX
+ * 2087 SUBSCRIPT SEVEN
+ * 	0037 DIGIT SEVEN
+ * 2088 SUBSCRIPT EIGHT
+ * 	0038 DIGIT EIGHT
+ * 2089 SUBSCRIPT NINE
+ * 	0039 DIGIT NINE
+ * 208A SUBSCRIPT PLUS SIGN
+ * 	002B PLUS SIGN
+ * 208B SUBSCRIPT MINUS
+ * 	2212 MINUS SIGN
+ * 208C SUBSCRIPT EQUALS SIGN
+ * 	003D EQUALS SIGN
+ * 208D SUBSCRIPT LEFT PARENTHESIS
+ * 	0028 LEFT PARENTHESIS
+ * 208E SUBSCRIPT RIGHT PARENTHESIS
+ * 	0029 RIGHT PARENTHESIS
+ * 20A8 RUPEE SIGN
+ * 	0052 LATIN CAPITAL LETTER R
+ * 	0073 LATIN SMALL LETTER S
+ * 2100 ACCOUNT OF
+ * 	0061 LATIN SMALL LETTER A
+ * 	002F SOLIDUS
+ * 	0063 LATIN SMALL LETTER C
+ * 2101 ADDRESSED TO THE SUBJECT
+ * 	0061 LATIN SMALL LETTER A
+ * 	002F SOLIDUS
+ * 	0073 LATIN SMALL LETTER S
+ * 2102 DOUBLE-STRUCK CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 2103 DEGREE CELSIUS
+ * 	00B0 DEGREE SIGN
+ * 	0043 LATIN CAPITAL LETTER C
+ * 2105 CARE OF
+ * 	0063 LATIN SMALL LETTER C
+ * 	002F SOLIDUS
+ * 	006F LATIN SMALL LETTER O
+ * 2106 CADA UNA
+ * 	0063 LATIN SMALL LETTER C
+ * 	002F SOLIDUS
+ * 	0075 LATIN SMALL LETTER U
+ * 2107 EULER CONSTANT
+ * 	0190 LATIN CAPITAL LETTER OPEN E
+ * 2109 DEGREE FAHRENHEIT
+ * 	00B0 DEGREE SIGN
+ * 	0046 LATIN CAPITAL LETTER F
+ * 210A SCRIPT SMALL G
+ * 	0067 LATIN SMALL LETTER G
+ * 210B SCRIPT CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 210C BLACK-LETTER CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 210D DOUBLE-STRUCK CAPITAL H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 210E PLANCK CONSTANT
+ * 	0068 LATIN SMALL LETTER H
+ * 210F PLANCK CONSTANT OVER TWO PI
+ * 	0127 LATIN SMALL LETTER H WITH STROKE
+ * 2110 SCRIPT CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 2111 BLACK-LETTER CAPITAL I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 2112 SCRIPT CAPITAL L
+ * 	004C LATIN CAPITAL LETTER L
+ * 2113 SCRIPT SMALL L
+ * 	006C LATIN SMALL LETTER L
+ * 2115 DOUBLE-STRUCK CAPITAL N
+ * 	004E LATIN CAPITAL LETTER N
+ * 2116 NUMERO SIGN
+ * 	004E LATIN CAPITAL LETTER N
+ * 	006F LATIN SMALL LETTER O
+ * 2119 DOUBLE-STRUCK CAPITAL P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 211A DOUBLE-STRUCK CAPITAL Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 211B SCRIPT CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 211C BLACK-LETTER CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 211D DOUBLE-STRUCK CAPITAL R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 2120 SERVICE MARK
+ * 	0053 LATIN CAPITAL LETTER S
+ * 	004D LATIN CAPITAL LETTER M
+ * 2121 TELEPHONE SIGN
+ * 	0054 LATIN CAPITAL LETTER T
+ * 	0045 LATIN CAPITAL LETTER E
+ * 	004C LATIN CAPITAL LETTER L
+ * 2122 TRADE MARK SIGN
+ * 	0054 LATIN CAPITAL LETTER T
+ * 	004D LATIN CAPITAL LETTER M
+ * 2124 DOUBLE-STRUCK CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 2126 OHM SIGN
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 2128 BLACK-LETTER CAPITAL Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 212A KELVIN SIGN
+ * 	004B LATIN CAPITAL LETTER K
+ * 212B ANGSTROM SIGN
+ * 	0041 LATIN CAPITAL LETTER A
+ * 212C SCRIPT CAPITAL B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 212D BLACK-LETTER CAPITAL C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 212F SCRIPT SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 2130 SCRIPT CAPITAL E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 2131 SCRIPT CAPITAL F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 2133 SCRIPT CAPITAL M
+ * 	004D LATIN CAPITAL LETTER M
+ * 2134 SCRIPT SMALL O
+ * 	006F LATIN SMALL LETTER O
+ * 2135 ALEF SYMBOL
+ * 	05D0 HEBREW LETTER ALEF
+ * 2136 BET SYMBOL
+ * 	05D1 HEBREW LETTER BET
+ * 2137 GIMEL SYMBOL
+ * 	05D2 HEBREW LETTER GIMEL
+ * 2138 DALET SYMBOL
+ * 	05D3 HEBREW LETTER DALET
+ * 2139 INFORMATION SOURCE
+ * 	0069 LATIN SMALL LETTER I
+ * 213D DOUBLE-STRUCK SMALL GAMMA
+ * 	03B3 GREEK SMALL LETTER GAMMA
+ * 213E DOUBLE-STRUCK CAPITAL GAMMA
+ * 	0393 GREEK CAPITAL LETTER GAMMA
+ * 213F DOUBLE-STRUCK CAPITAL PI
+ * 	03A0 GREEK CAPITAL LETTER PI
+ * 2140 DOUBLE-STRUCK N-ARY SUMMATION
+ * 	2211 N-ARY SUMMATION
+ * 2145 DOUBLE-STRUCK ITALIC CAPITAL D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 2146 DOUBLE-STRUCK ITALIC SMALL D
+ * 	0064 LATIN SMALL LETTER D
+ * 2147 DOUBLE-STRUCK ITALIC SMALL E
+ * 	0065 LATIN SMALL LETTER E
+ * 2148 DOUBLE-STRUCK ITALIC SMALL I
+ * 	0069 LATIN SMALL LETTER I
+ * 2149 DOUBLE-STRUCK ITALIC SMALL J
+ * 	006A LATIN SMALL LETTER J
+ * 2153 VULGAR FRACTION ONE THIRD
+ * 	0031 DIGIT ONE
+ * 	2044 FRACTION SLASH
+ * 	0033 DIGIT THREE
+ * 2154 VULGAR FRACTION TWO THIRDS
+ * 	0032 DIGIT TWO
+ * 	2044 FRACTION SLASH
+ * 	0033 DIGIT THREE
+ * 2155 VULGAR FRACTION ONE FIFTH
+ * 	0031 DIGIT ONE
+ * 	2044 FRACTION SLASH
+ * 	0035 DIGIT FIVE
+ * 2156 VULGAR FRACTION TWO FIFTHS
+ * 	0032 DIGIT TWO
+ * 	2044 FRACTION SLASH
+ * 	0035 DIGIT FIVE
+ * 2157 VULGAR FRACTION THREE FIFTHS
+ * 	0033 DIGIT THREE
+ * 	2044 FRACTION SLASH
+ * 	0035 DIGIT FIVE
+ * 2158 VULGAR FRACTION FOUR FIFTHS
+ * 	0034 DIGIT FOUR
+ * 	2044 FRACTION SLASH
+ * 	0035 DIGIT FIVE
+ * 2159 VULGAR FRACTION ONE SIXTH
+ * 	0031 DIGIT ONE
+ * 	2044 FRACTION SLASH
+ * 	0036 DIGIT SIX
+ * 215A VULGAR FRACTION FIVE SIXTHS
+ * 	0035 DIGIT FIVE
+ * 	2044 FRACTION SLASH
+ * 	0036 DIGIT SIX
+ * 215B VULGAR FRACTION ONE EIGHTH
+ * 	0031 DIGIT ONE
+ * 	2044 FRACTION SLASH
+ * 	0038 DIGIT EIGHT
+ * 215C VULGAR FRACTION THREE EIGHTHS
+ * 	0033 DIGIT THREE
+ * 	2044 FRACTION SLASH
+ * 	0038 DIGIT EIGHT
+ * 215D VULGAR FRACTION FIVE EIGHTHS
+ * 	0035 DIGIT FIVE
+ * 	2044 FRACTION SLASH
+ * 	0038 DIGIT EIGHT
+ * 215E VULGAR FRACTION SEVEN EIGHTHS
+ * 	0037 DIGIT SEVEN
+ * 	2044 FRACTION SLASH
+ * 	0038 DIGIT EIGHT
+ * 215F FRACTION NUMERATOR ONE
+ * 	0031 DIGIT ONE
+ * 	2044 FRACTION SLASH
+ * 2160 ROMAN NUMERAL ONE
+ * 	0049 LATIN CAPITAL LETTER I
+ * 2161 ROMAN NUMERAL TWO
+ * 	0049 LATIN CAPITAL LETTER I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 2162 ROMAN NUMERAL THREE
+ * 	0049 LATIN CAPITAL LETTER I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 2163 ROMAN NUMERAL FOUR
+ * 	0049 LATIN CAPITAL LETTER I
+ * 	0056 LATIN CAPITAL LETTER V
+ * 2164 ROMAN NUMERAL FIVE
+ * 	0056 LATIN CAPITAL LETTER V
+ * 2165 ROMAN NUMERAL SIX
+ * 	0056 LATIN CAPITAL LETTER V
+ * 	0049 LATIN CAPITAL LETTER I
+ * 2166 ROMAN NUMERAL SEVEN
+ * 	0056 LATIN CAPITAL LETTER V
+ * 	0049 LATIN CAPITAL LETTER I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 2167 ROMAN NUMERAL EIGHT
+ * 	0056 LATIN CAPITAL LETTER V
+ * 	0049 LATIN CAPITAL LETTER I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 2168 ROMAN NUMERAL NINE
+ * 	0049 LATIN CAPITAL LETTER I
+ * 	0058 LATIN CAPITAL LETTER X
+ * 2169 ROMAN NUMERAL TEN
+ * 	0058 LATIN CAPITAL LETTER X
+ * 216A ROMAN NUMERAL ELEVEN
+ * 	0058 LATIN CAPITAL LETTER X
+ * 	0049 LATIN CAPITAL LETTER I
+ * 216B ROMAN NUMERAL TWELVE
+ * 	0058 LATIN CAPITAL LETTER X
+ * 	0049 LATIN CAPITAL LETTER I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 216C ROMAN NUMERAL FIFTY
+ * 	004C LATIN CAPITAL LETTER L
+ * 216D ROMAN NUMERAL ONE HUNDRED
+ * 	0043 LATIN CAPITAL LETTER C
+ * 216E ROMAN NUMERAL FIVE HUNDRED
+ * 	0044 LATIN CAPITAL LETTER D
+ * 216F ROMAN NUMERAL ONE THOUSAND
+ * 	004D LATIN CAPITAL LETTER M
+ * 2170 SMALL ROMAN NUMERAL ONE
+ * 	0069 LATIN SMALL LETTER I
+ * 2171 SMALL ROMAN NUMERAL TWO
+ * 	0069 LATIN SMALL LETTER I
+ * 	0069 LATIN SMALL LETTER I
+ * 2172 SMALL ROMAN NUMERAL THREE
+ * 	0069 LATIN SMALL LETTER I
+ * 	0069 LATIN SMALL LETTER I
+ * 	0069 LATIN SMALL LETTER I
+ * 2173 SMALL ROMAN NUMERAL FOUR
+ * 	0069 LATIN SMALL LETTER I
+ * 	0076 LATIN SMALL LETTER V
+ * 2174 SMALL ROMAN NUMERAL FIVE
+ * 	0076 LATIN SMALL LETTER V
+ * 2175 SMALL ROMAN NUMERAL SIX
+ * 	0076 LATIN SMALL LETTER V
+ * 	0069 LATIN SMALL LETTER I
+ * 2176 SMALL ROMAN NUMERAL SEVEN
+ * 	0076 LATIN SMALL LETTER V
+ * 	0069 LATIN SMALL LETTER I
+ * 	0069 LATIN SMALL LETTER I
+ * 2177 SMALL ROMAN NUMERAL EIGHT
+ * 	0076 LATIN SMALL LETTER V
+ * 	0069 LATIN SMALL LETTER I
+ * 	0069 LATIN SMALL LETTER I
+ * 	0069 LATIN SMALL LETTER I
+ * 2178 SMALL ROMAN NUMERAL NINE
+ * 	0069 LATIN SMALL LETTER I
+ * 	0078 LATIN SMALL LETTER X
+ * 2179 SMALL ROMAN NUMERAL TEN
+ * 	0078 LATIN SMALL LETTER X
+ * 217A SMALL ROMAN NUMERAL ELEVEN
+ * 	0078 LATIN SMALL LETTER X
+ * 	0069 LATIN SMALL LETTER I
+ * 217B SMALL ROMAN NUMERAL TWELVE
+ * 	0078 LATIN SMALL LETTER X
+ * 	0069 LATIN SMALL LETTER I
+ * 	0069 LATIN SMALL LETTER I
+ * 217C SMALL ROMAN NUMERAL FIFTY
+ * 	006C LATIN SMALL LETTER L
+ * 217D SMALL ROMAN NUMERAL ONE HUNDRED
+ * 	0063 LATIN SMALL LETTER C
+ * 217E SMALL ROMAN NUMERAL FIVE HUNDRED
+ * 	0064 LATIN SMALL LETTER D
+ * 217F SMALL ROMAN NUMERAL ONE THOUSAND
+ * 	006D LATIN SMALL LETTER M
+ * 219A LEFTWARDS ARROW WITH STROKE
+ * 	2190 LEFTWARDS ARROW
+ * 219B RIGHTWARDS ARROW WITH STROKE
+ * 	2192 RIGHTWARDS ARROW
+ * 21AE LEFT RIGHT ARROW WITH STROKE
+ * 	2194 LEFT RIGHT ARROW
+ * 21CD LEFTWARDS DOUBLE ARROW WITH STROKE
+ * 	21D0 LEFTWARDS DOUBLE ARROW
+ * 21CE LEFT RIGHT DOUBLE ARROW WITH STROKE
+ * 	21D4 LEFT RIGHT DOUBLE ARROW
+ * 21CF RIGHTWARDS DOUBLE ARROW WITH STROKE
+ * 	21D2 RIGHTWARDS DOUBLE ARROW
+ * 2204 THERE DOES NOT EXIST
+ * 	2203 THERE EXISTS
+ * 2209 NOT AN ELEMENT OF
+ * 	2208 ELEMENT OF
+ * 220C DOES NOT CONTAIN AS MEMBER
+ * 	220B CONTAINS AS MEMBER
+ * 2224 DOES NOT DIVIDE
+ * 	2223 DIVIDES
+ * 2226 NOT PARALLEL TO
+ * 	2225 PARALLEL TO
+ * 222C DOUBLE INTEGRAL
+ * 	222B INTEGRAL
+ * 	222B INTEGRAL
+ * 222D TRIPLE INTEGRAL
+ * 	222B INTEGRAL
+ * 	222B INTEGRAL
+ * 	222B INTEGRAL
+ * 222F SURFACE INTEGRAL
+ * 	222E CONTOUR INTEGRAL
+ * 	222E CONTOUR INTEGRAL
+ * 2230 VOLUME INTEGRAL
+ * 	222E CONTOUR INTEGRAL
+ * 	222E CONTOUR INTEGRAL
+ * 	222E CONTOUR INTEGRAL
+ * 2241 NOT TILDE
+ * 	223C TILDE OPERATOR
+ * 2244 NOT ASYMPTOTICALLY EQUAL TO
+ * 	2243 ASYMPTOTICALLY EQUAL TO
+ * 2247 NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
+ * 	2245 APPROXIMATELY EQUAL TO
+ * 2249 NOT ALMOST EQUAL TO
+ * 	2248 ALMOST EQUAL TO
+ * 2260 NOT EQUAL TO
+ * 	003D EQUALS SIGN
+ * 2262 NOT IDENTICAL TO
+ * 	2261 IDENTICAL TO
+ * 226D NOT EQUIVALENT TO
+ * 	224D EQUIVALENT TO
+ * 226E NOT LESS-THAN
+ * 	003C LESS-THAN SIGN
+ * 226F NOT GREATER-THAN
+ * 	003E GREATER-THAN SIGN
+ * 2270 NEITHER LESS-THAN NOR EQUAL TO
+ * 	2264 LESS-THAN OR EQUAL TO
+ * 2271 NEITHER GREATER-THAN NOR EQUAL TO
+ * 	2265 GREATER-THAN OR EQUAL TO
+ * 2274 NEITHER LESS-THAN NOR EQUIVALENT TO
+ * 	2272 LESS-THAN OR EQUIVALENT TO
+ * 2275 NEITHER GREATER-THAN NOR EQUIVALENT TO
+ * 	2273 GREATER-THAN OR EQUIVALENT TO
+ * 2278 NEITHER LESS-THAN NOR GREATER-THAN
+ * 	2276 LESS-THAN OR GREATER-THAN
+ * 2279 NEITHER GREATER-THAN NOR LESS-THAN
+ * 	2277 GREATER-THAN OR LESS-THAN
+ * 2280 DOES NOT PRECEDE
+ * 	227A PRECEDES
+ * 2281 DOES NOT SUCCEED
+ * 	227B SUCCEEDS
+ * 2284 NOT A SUBSET OF
+ * 	2282 SUBSET OF
+ * 2285 NOT A SUPERSET OF
+ * 	2283 SUPERSET OF
+ * 2288 NEITHER A SUBSET OF NOR EQUAL TO
+ * 	2286 SUBSET OF OR EQUAL TO
+ * 2289 NEITHER A SUPERSET OF NOR EQUAL TO
+ * 	2287 SUPERSET OF OR EQUAL TO
+ * 22AC DOES NOT PROVE
+ * 	22A2 RIGHT TACK
+ * 22AD NOT TRUE
+ * 	22A8 TRUE
+ * 22AE DOES NOT FORCE
+ * 	22A9 FORCES
+ * 22AF NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+ * 	22AB DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+ * 22E0 DOES NOT PRECEDE OR EQUAL
+ * 	227C PRECEDES OR EQUAL TO
+ * 22E1 DOES NOT SUCCEED OR EQUAL
+ * 	227D SUCCEEDS OR EQUAL TO
+ * 22E2 NOT SQUARE IMAGE OF OR EQUAL TO
+ * 	2291 SQUARE IMAGE OF OR EQUAL TO
+ * 22E3 NOT SQUARE ORIGINAL OF OR EQUAL TO
+ * 	2292 SQUARE ORIGINAL OF OR EQUAL TO
+ * 22EA NOT NORMAL SUBGROUP OF
+ * 	22B2 NORMAL SUBGROUP OF
+ * 22EB DOES NOT CONTAIN AS NORMAL SUBGROUP
+ * 	22B3 CONTAINS AS NORMAL SUBGROUP
+ * 22EC NOT NORMAL SUBGROUP OF OR EQUAL TO
+ * 	22B4 NORMAL SUBGROUP OF OR EQUAL TO
+ * 22ED DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+ * 	22B5 CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
+ * 2329 LEFT-POINTING ANGLE BRACKET
+ * 	3008 LEFT ANGLE BRACKET
+ * 232A RIGHT-POINTING ANGLE BRACKET
+ * 	3009 RIGHT ANGLE BRACKET
+ * 2460 CIRCLED DIGIT ONE
+ * 	0031 DIGIT ONE
+ * 2461 CIRCLED DIGIT TWO
+ * 	0032 DIGIT TWO
+ * 2462 CIRCLED DIGIT THREE
+ * 	0033 DIGIT THREE
+ * 2463 CIRCLED DIGIT FOUR
+ * 	0034 DIGIT FOUR
+ * 2464 CIRCLED DIGIT FIVE
+ * 	0035 DIGIT FIVE
+ * 2465 CIRCLED DIGIT SIX
+ * 	0036 DIGIT SIX
+ * 2466 CIRCLED DIGIT SEVEN
+ * 	0037 DIGIT SEVEN
+ * 2467 CIRCLED DIGIT EIGHT
+ * 	0038 DIGIT EIGHT
+ * 2468 CIRCLED DIGIT NINE
+ * 	0039 DIGIT NINE
+ * 2469 CIRCLED NUMBER TEN
+ * 	0031 DIGIT ONE
+ * 	0030 DIGIT ZERO
+ * 246A CIRCLED NUMBER ELEVEN
+ * 	0031 DIGIT ONE
+ * 	0031 DIGIT ONE
+ * 246B CIRCLED NUMBER TWELVE
+ * 	0031 DIGIT ONE
+ * 	0032 DIGIT TWO
+ * 246C CIRCLED NUMBER THIRTEEN
+ * 	0031 DIGIT ONE
+ * 	0033 DIGIT THREE
+ * 246D CIRCLED NUMBER FOURTEEN
+ * 	0031 DIGIT ONE
+ * 	0034 DIGIT FOUR
+ * 246E CIRCLED NUMBER FIFTEEN
+ * 	0031 DIGIT ONE
+ * 	0035 DIGIT FIVE
+ * 246F CIRCLED NUMBER SIXTEEN
+ * 	0031 DIGIT ONE
+ * 	0036 DIGIT SIX
+ * 2470 CIRCLED NUMBER SEVENTEEN
+ * 	0031 DIGIT ONE
+ * 	0037 DIGIT SEVEN
+ * 2471 CIRCLED NUMBER EIGHTEEN
+ * 	0031 DIGIT ONE
+ * 	0038 DIGIT EIGHT
+ * 2472 CIRCLED NUMBER NINETEEN
+ * 	0031 DIGIT ONE
+ * 	0039 DIGIT NINE
+ * 2473 CIRCLED NUMBER TWENTY
+ * 	0032 DIGIT TWO
+ * 	0030 DIGIT ZERO
+ * 2474 PARENTHESIZED DIGIT ONE
+ * 	0028 LEFT PARENTHESIS
+ * 	0031 DIGIT ONE
+ * 	0029 RIGHT PARENTHESIS
+ * 2475 PARENTHESIZED DIGIT TWO
+ * 	0028 LEFT PARENTHESIS
+ * 	0032 DIGIT TWO
+ * 	0029 RIGHT PARENTHESIS
+ * 2476 PARENTHESIZED DIGIT THREE
+ * 	0028 LEFT PARENTHESIS
+ * 	0033 DIGIT THREE
+ * 	0029 RIGHT PARENTHESIS
+ * 2477 PARENTHESIZED DIGIT FOUR
+ * 	0028 LEFT PARENTHESIS
+ * 	0034 DIGIT FOUR
+ * 	0029 RIGHT PARENTHESIS
+ * 2478 PARENTHESIZED DIGIT FIVE
+ * 	0028 LEFT PARENTHESIS
+ * 	0035 DIGIT FIVE
+ * 	0029 RIGHT PARENTHESIS
+ * 2479 PARENTHESIZED DIGIT SIX
+ * 	0028 LEFT PARENTHESIS
+ * 	0036 DIGIT SIX
+ * 	0029 RIGHT PARENTHESIS
+ * 247A PARENTHESIZED DIGIT SEVEN
+ * 	0028 LEFT PARENTHESIS
+ * 	0037 DIGIT SEVEN
+ * 	0029 RIGHT PARENTHESIS
+ * 247B PARENTHESIZED DIGIT EIGHT
+ * 	0028 LEFT PARENTHESIS
+ * 	0038 DIGIT EIGHT
+ * 	0029 RIGHT PARENTHESIS
+ * 247C PARENTHESIZED DIGIT NINE
+ * 	0028 LEFT PARENTHESIS
+ * 	0039 DIGIT NINE
+ * 	0029 RIGHT PARENTHESIS
+ * 247D PARENTHESIZED NUMBER TEN
+ * 	0028 LEFT PARENTHESIS
+ * 	0031 DIGIT ONE
+ * 	0030 DIGIT ZERO
+ * 	0029 RIGHT PARENTHESIS
+ * 247E PARENTHESIZED NUMBER ELEVEN
+ * 	0028 LEFT PARENTHESIS
+ * 	0031 DIGIT ONE
+ * 	0031 DIGIT ONE
+ * 	0029 RIGHT PARENTHESIS
+ * 247F PARENTHESIZED NUMBER TWELVE
+ * 	0028 LEFT PARENTHESIS
+ * 	0031 DIGIT ONE
+ * 	0032 DIGIT TWO
+ * 	0029 RIGHT PARENTHESIS
+ * 2480 PARENTHESIZED NUMBER THIRTEEN
+ * 	0028 LEFT PARENTHESIS
+ * 	0031 DIGIT ONE
+ * 	0033 DIGIT THREE
+ * 	0029 RIGHT PARENTHESIS
+ * 2481 PARENTHESIZED NUMBER FOURTEEN
+ * 	0028 LEFT PARENTHESIS
+ * 	0031 DIGIT ONE
+ * 	0034 DIGIT FOUR
+ * 	0029 RIGHT PARENTHESIS
+ * 2482 PARENTHESIZED NUMBER FIFTEEN
+ * 	0028 LEFT PARENTHESIS
+ * 	0031 DIGIT ONE
+ * 	0035 DIGIT FIVE
+ * 	0029 RIGHT PARENTHESIS
+ * 2483 PARENTHESIZED NUMBER SIXTEEN
+ * 	0028 LEFT PARENTHESIS
+ * 	0031 DIGIT ONE
+ * 	0036 DIGIT SIX
+ * 	0029 RIGHT PARENTHESIS
+ * 2484 PARENTHESIZED NUMBER SEVENTEEN
+ * 	0028 LEFT PARENTHESIS
+ * 	0031 DIGIT ONE
+ * 	0037 DIGIT SEVEN
+ * 	0029 RIGHT PARENTHESIS
+ * 2485 PARENTHESIZED NUMBER EIGHTEEN
+ * 	0028 LEFT PARENTHESIS
+ * 	0031 DIGIT ONE
+ * 	0038 DIGIT EIGHT
+ * 	0029 RIGHT PARENTHESIS
+ * 2486 PARENTHESIZED NUMBER NINETEEN
+ * 	0028 LEFT PARENTHESIS
+ * 	0031 DIGIT ONE
+ * 	0039 DIGIT NINE
+ * 	0029 RIGHT PARENTHESIS
+ * 2487 PARENTHESIZED NUMBER TWENTY
+ * 	0028 LEFT PARENTHESIS
+ * 	0032 DIGIT TWO
+ * 	0030 DIGIT ZERO
+ * 	0029 RIGHT PARENTHESIS
+ * 2488 DIGIT ONE FULL STOP
+ * 	0031 DIGIT ONE
+ * 	002E FULL STOP
+ * 2489 DIGIT TWO FULL STOP
+ * 	0032 DIGIT TWO
+ * 	002E FULL STOP
+ * 248A DIGIT THREE FULL STOP
+ * 	0033 DIGIT THREE
+ * 	002E FULL STOP
+ * 248B DIGIT FOUR FULL STOP
+ * 	0034 DIGIT FOUR
+ * 	002E FULL STOP
+ * 248C DIGIT FIVE FULL STOP
+ * 	0035 DIGIT FIVE
+ * 	002E FULL STOP
+ * 248D DIGIT SIX FULL STOP
+ * 	0036 DIGIT SIX
+ * 	002E FULL STOP
+ * 248E DIGIT SEVEN FULL STOP
+ * 	0037 DIGIT SEVEN
+ * 	002E FULL STOP
+ * 248F DIGIT EIGHT FULL STOP
+ * 	0038 DIGIT EIGHT
+ * 	002E FULL STOP
+ * 2490 DIGIT NINE FULL STOP
+ * 	0039 DIGIT NINE
+ * 	002E FULL STOP
+ * 2491 NUMBER TEN FULL STOP
+ * 	0031 DIGIT ONE
+ * 	0030 DIGIT ZERO
+ * 	002E FULL STOP
+ * 2492 NUMBER ELEVEN FULL STOP
+ * 	0031 DIGIT ONE
+ * 	0031 DIGIT ONE
+ * 	002E FULL STOP
+ * 2493 NUMBER TWELVE FULL STOP
+ * 	0031 DIGIT ONE
+ * 	0032 DIGIT TWO
+ * 	002E FULL STOP
+ * 2494 NUMBER THIRTEEN FULL STOP
+ * 	0031 DIGIT ONE
+ * 	0033 DIGIT THREE
+ * 	002E FULL STOP
+ * 2495 NUMBER FOURTEEN FULL STOP
+ * 	0031 DIGIT ONE
+ * 	0034 DIGIT FOUR
+ * 	002E FULL STOP
+ * 2496 NUMBER FIFTEEN FULL STOP
+ * 	0031 DIGIT ONE
+ * 	0035 DIGIT FIVE
+ * 	002E FULL STOP
+ * 2497 NUMBER SIXTEEN FULL STOP
+ * 	0031 DIGIT ONE
+ * 	0036 DIGIT SIX
+ * 	002E FULL STOP
+ * 2498 NUMBER SEVENTEEN FULL STOP
+ * 	0031 DIGIT ONE
+ * 	0037 DIGIT SEVEN
+ * 	002E FULL STOP
+ * 2499 NUMBER EIGHTEEN FULL STOP
+ * 	0031 DIGIT ONE
+ * 	0038 DIGIT EIGHT
+ * 	002E FULL STOP
+ * 249A NUMBER NINETEEN FULL STOP
+ * 	0031 DIGIT ONE
+ * 	0039 DIGIT NINE
+ * 	002E FULL STOP
+ * 249B NUMBER TWENTY FULL STOP
+ * 	0032 DIGIT TWO
+ * 	0030 DIGIT ZERO
+ * 	002E FULL STOP
+ * 249C PARENTHESIZED LATIN SMALL LETTER A
+ * 	0028 LEFT PARENTHESIS
+ * 	0061 LATIN SMALL LETTER A
+ * 	0029 RIGHT PARENTHESIS
+ * 249D PARENTHESIZED LATIN SMALL LETTER B
+ * 	0028 LEFT PARENTHESIS
+ * 	0062 LATIN SMALL LETTER B
+ * 	0029 RIGHT PARENTHESIS
+ * 249E PARENTHESIZED LATIN SMALL LETTER C
+ * 	0028 LEFT PARENTHESIS
+ * 	0063 LATIN SMALL LETTER C
+ * 	0029 RIGHT PARENTHESIS
+ * 249F PARENTHESIZED LATIN SMALL LETTER D
+ * 	0028 LEFT PARENTHESIS
+ * 	0064 LATIN SMALL LETTER D
+ * 	0029 RIGHT PARENTHESIS
+ * 24A0 PARENTHESIZED LATIN SMALL LETTER E
+ * 	0028 LEFT PARENTHESIS
+ * 	0065 LATIN SMALL LETTER E
+ * 	0029 RIGHT PARENTHESIS
+ * 24A1 PARENTHESIZED LATIN SMALL LETTER F
+ * 	0028 LEFT PARENTHESIS
+ * 	0066 LATIN SMALL LETTER F
+ * 	0029 RIGHT PARENTHESIS
+ * 24A2 PARENTHESIZED LATIN SMALL LETTER G
+ * 	0028 LEFT PARENTHESIS
+ * 	0067 LATIN SMALL LETTER G
+ * 	0029 RIGHT PARENTHESIS
+ * 24A3 PARENTHESIZED LATIN SMALL LETTER H
+ * 	0028 LEFT PARENTHESIS
+ * 	0068 LATIN SMALL LETTER H
+ * 	0029 RIGHT PARENTHESIS
+ * 24A4 PARENTHESIZED LATIN SMALL LETTER I
+ * 	0028 LEFT PARENTHESIS
+ * 	0069 LATIN SMALL LETTER I
+ * 	0029 RIGHT PARENTHESIS
+ * 24A5 PARENTHESIZED LATIN SMALL LETTER J
+ * 	0028 LEFT PARENTHESIS
+ * 	006A LATIN SMALL LETTER J
+ * 	0029 RIGHT PARENTHESIS
+ * 24A6 PARENTHESIZED LATIN SMALL LETTER K
+ * 	0028 LEFT PARENTHESIS
+ * 	006B LATIN SMALL LETTER K
+ * 	0029 RIGHT PARENTHESIS
+ * 24A7 PARENTHESIZED LATIN SMALL LETTER L
+ * 	0028 LEFT PARENTHESIS
+ * 	006C LATIN SMALL LETTER L
+ * 	0029 RIGHT PARENTHESIS
+ * 24A8 PARENTHESIZED LATIN SMALL LETTER M
+ * 	0028 LEFT PARENTHESIS
+ * 	006D LATIN SMALL LETTER M
+ * 	0029 RIGHT PARENTHESIS
+ * 24A9 PARENTHESIZED LATIN SMALL LETTER N
+ * 	0028 LEFT PARENTHESIS
+ * 	006E LATIN SMALL LETTER N
+ * 	0029 RIGHT PARENTHESIS
+ * 24AA PARENTHESIZED LATIN SMALL LETTER O
+ * 	0028 LEFT PARENTHESIS
+ * 	006F LATIN SMALL LETTER O
+ * 	0029 RIGHT PARENTHESIS
+ * 24AB PARENTHESIZED LATIN SMALL LETTER P
+ * 	0028 LEFT PARENTHESIS
+ * 	0070 LATIN SMALL LETTER P
+ * 	0029 RIGHT PARENTHESIS
+ * 24AC PARENTHESIZED LATIN SMALL LETTER Q
+ * 	0028 LEFT PARENTHESIS
+ * 	0071 LATIN SMALL LETTER Q
+ * 	0029 RIGHT PARENTHESIS
+ * 24AD PARENTHESIZED LATIN SMALL LETTER R
+ * 	0028 LEFT PARENTHESIS
+ * 	0072 LATIN SMALL LETTER R
+ * 	0029 RIGHT PARENTHESIS
+ * 24AE PARENTHESIZED LATIN SMALL LETTER S
+ * 	0028 LEFT PARENTHESIS
+ * 	0073 LATIN SMALL LETTER S
+ * 	0029 RIGHT PARENTHESIS
+ * 24AF PARENTHESIZED LATIN SMALL LETTER T
+ * 	0028 LEFT PARENTHESIS
+ * 	0074 LATIN SMALL LETTER T
+ * 	0029 RIGHT PARENTHESIS
+ * 24B0 PARENTHESIZED LATIN SMALL LETTER U
+ * 	0028 LEFT PARENTHESIS
+ * 	0075 LATIN SMALL LETTER U
+ * 	0029 RIGHT PARENTHESIS
+ * 24B1 PARENTHESIZED LATIN SMALL LETTER V
+ * 	0028 LEFT PARENTHESIS
+ * 	0076 LATIN SMALL LETTER V
+ * 	0029 RIGHT PARENTHESIS
+ * 24B2 PARENTHESIZED LATIN SMALL LETTER W
+ * 	0028 LEFT PARENTHESIS
+ * 	0077 LATIN SMALL LETTER W
+ * 	0029 RIGHT PARENTHESIS
+ * 24B3 PARENTHESIZED LATIN SMALL LETTER X
+ * 	0028 LEFT PARENTHESIS
+ * 	0078 LATIN SMALL LETTER X
+ * 	0029 RIGHT PARENTHESIS
+ * 24B4 PARENTHESIZED LATIN SMALL LETTER Y
+ * 	0028 LEFT PARENTHESIS
+ * 	0079 LATIN SMALL LETTER Y
+ * 	0029 RIGHT PARENTHESIS
+ * 24B5 PARENTHESIZED LATIN SMALL LETTER Z
+ * 	0028 LEFT PARENTHESIS
+ * 	007A LATIN SMALL LETTER Z
+ * 	0029 RIGHT PARENTHESIS
+ * 24B6 CIRCLED LATIN CAPITAL LETTER A
+ * 	0041 LATIN CAPITAL LETTER A
+ * 24B7 CIRCLED LATIN CAPITAL LETTER B
+ * 	0042 LATIN CAPITAL LETTER B
+ * 24B8 CIRCLED LATIN CAPITAL LETTER C
+ * 	0043 LATIN CAPITAL LETTER C
+ * 24B9 CIRCLED LATIN CAPITAL LETTER D
+ * 	0044 LATIN CAPITAL LETTER D
+ * 24BA CIRCLED LATIN CAPITAL LETTER E
+ * 	0045 LATIN CAPITAL LETTER E
+ * 24BB CIRCLED LATIN CAPITAL LETTER F
+ * 	0046 LATIN CAPITAL LETTER F
+ * 24BC CIRCLED LATIN CAPITAL LETTER G
+ * 	0047 LATIN CAPITAL LETTER G
+ * 24BD CIRCLED LATIN CAPITAL LETTER H
+ * 	0048 LATIN CAPITAL LETTER H
+ * 24BE CIRCLED LATIN CAPITAL LETTER I
+ * 	0049 LATIN CAPITAL LETTER I
+ * 24BF CIRCLED LATIN CAPITAL LETTER J
+ * 	004A LATIN CAPITAL LETTER J
+ * 24C0 CIRCLED LATIN CAPITAL LETTER K
+ * 	004B LATIN CAPITAL LETTER K
+ * 24C1 CIRCLED LATIN CAPITAL LETTER L
+ * 	004C LATIN CAPITAL LETTER L
+ * 24C2 CIRCLED LATIN CAPITAL LETTER M
+ * 	004D LATIN CAPITAL LETTER M
+ * 24C3 CIRCLED LATIN CAPITAL LETTER N
+ * 	004E LATIN CAPITAL LETTER N
+ * 24C4 CIRCLED LATIN CAPITAL LETTER O
+ * 	004F LATIN CAPITAL LETTER O
+ * 24C5 CIRCLED LATIN CAPITAL LETTER P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 24C6 CIRCLED LATIN CAPITAL LETTER Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * 24C7 CIRCLED LATIN CAPITAL LETTER R
+ * 	0052 LATIN CAPITAL LETTER R
+ * 24C8 CIRCLED LATIN CAPITAL LETTER S
+ * 	0053 LATIN CAPITAL LETTER S
+ * 24C9 CIRCLED LATIN CAPITAL LETTER T
+ * 	0054 LATIN CAPITAL LETTER T
+ * 24CA CIRCLED LATIN CAPITAL LETTER U
+ * 	0055 LATIN CAPITAL LETTER U
+ * 24CB CIRCLED LATIN CAPITAL LETTER V
+ * 	0056 LATIN CAPITAL LETTER V
+ * 24CC CIRCLED LATIN CAPITAL LETTER W
+ * 	0057 LATIN CAPITAL LETTER W
+ * 24CD CIRCLED LATIN CAPITAL LETTER X
+ * 	0058 LATIN CAPITAL LETTER X
+ * 24CE CIRCLED LATIN CAPITAL LETTER Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * 24CF CIRCLED LATIN CAPITAL LETTER Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * 24D0 CIRCLED LATIN SMALL LETTER A
+ * 	0061 LATIN SMALL LETTER A
+ * 24D1 CIRCLED LATIN SMALL LETTER B
+ * 	0062 LATIN SMALL LETTER B
+ * 24D2 CIRCLED LATIN SMALL LETTER C
+ * 	0063 LATIN SMALL LETTER C
+ * 24D3 CIRCLED LATIN SMALL LETTER D
+ * 	0064 LATIN SMALL LETTER D
+ * 24D4 CIRCLED LATIN SMALL LETTER E
+ * 	0065 LATIN SMALL LETTER E
+ * 24D5 CIRCLED LATIN SMALL LETTER F
+ * 	0066 LATIN SMALL LETTER F
+ * 24D6 CIRCLED LATIN SMALL LETTER G
+ * 	0067 LATIN SMALL LETTER G
+ * 24D7 CIRCLED LATIN SMALL LETTER H
+ * 	0068 LATIN SMALL LETTER H
+ * 24D8 CIRCLED LATIN SMALL LETTER I
+ * 	0069 LATIN SMALL LETTER I
+ * 24D9 CIRCLED LATIN SMALL LETTER J
+ * 	006A LATIN SMALL LETTER J
+ * 24DA CIRCLED LATIN SMALL LETTER K
+ * 	006B LATIN SMALL LETTER K
+ * 24DB CIRCLED LATIN SMALL LETTER L
+ * 	006C LATIN SMALL LETTER L
+ * 24DC CIRCLED LATIN SMALL LETTER M
+ * 	006D LATIN SMALL LETTER M
+ * 24DD CIRCLED LATIN SMALL LETTER N
+ * 	006E LATIN SMALL LETTER N
+ * 24DE CIRCLED LATIN SMALL LETTER O
+ * 	006F LATIN SMALL LETTER O
+ * 24DF CIRCLED LATIN SMALL LETTER P
+ * 	0070 LATIN SMALL LETTER P
+ * 24E0 CIRCLED LATIN SMALL LETTER Q
+ * 	0071 LATIN SMALL LETTER Q
+ * 24E1 CIRCLED LATIN SMALL LETTER R
+ * 	0072 LATIN SMALL LETTER R
+ * 24E2 CIRCLED LATIN SMALL LETTER S
+ * 	0073 LATIN SMALL LETTER S
+ * 24E3 CIRCLED LATIN SMALL LETTER T
+ * 	0074 LATIN SMALL LETTER T
+ * 24E4 CIRCLED LATIN SMALL LETTER U
+ * 	0075 LATIN SMALL LETTER U
+ * 24E5 CIRCLED LATIN SMALL LETTER V
+ * 	0076 LATIN SMALL LETTER V
+ * 24E6 CIRCLED LATIN SMALL LETTER W
+ * 	0077 LATIN SMALL LETTER W
+ * 24E7 CIRCLED LATIN SMALL LETTER X
+ * 	0078 LATIN SMALL LETTER X
+ * 24E8 CIRCLED LATIN SMALL LETTER Y
+ * 	0079 LATIN SMALL LETTER Y
+ * 24E9 CIRCLED LATIN SMALL LETTER Z
+ * 	007A LATIN SMALL LETTER Z
+ * 24EA CIRCLED DIGIT ZERO
+ * 	0030 DIGIT ZERO
+ * 2A0C QUADRUPLE INTEGRAL OPERATOR
+ * 	222B INTEGRAL
+ * 	222B INTEGRAL
+ * 	222B INTEGRAL
+ * 	222B INTEGRAL
+ * 2A74 DOUBLE COLON EQUAL
+ * 	003A COLON
+ * 	003A COLON
+ * 	003D EQUALS SIGN
+ * 2A75 TWO CONSECUTIVE EQUALS SIGNS
+ * 	003D EQUALS SIGN
+ * 	003D EQUALS SIGN
+ * 2A76 THREE CONSECUTIVE EQUALS SIGNS
+ * 	003D EQUALS SIGN
+ * 	003D EQUALS SIGN
+ * 	003D EQUALS SIGN
+ * 2ADC FORKING
+ * 	2ADD NONFORKING
+ * 2E9F CJK RADICAL MOTHER
+ * 	6BCD ??
+ * 2EF3 CJK RADICAL C-SIMPLIFIED TURTLE
+ * 	9F9F ??
+ * 2F00 KANGXI RADICAL ONE
+ * 	4E00 <CJK Ideograph, First>
+ * 2F01 KANGXI RADICAL LINE
+ * 	4E28 ??
+ * 2F02 KANGXI RADICAL DOT
+ * 	4E36 ??
+ * 2F03 KANGXI RADICAL SLASH
+ * 	4E3F ??
+ * 2F04 KANGXI RADICAL SECOND
+ * 	4E59 ??
+ * 2F05 KANGXI RADICAL HOOK
+ * 	4E85 ??
+ * 2F06 KANGXI RADICAL TWO
+ * 	4E8C ??
+ * 2F07 KANGXI RADICAL LID
+ * 	4EA0 ??
+ * 2F08 KANGXI RADICAL MAN
+ * 	4EBA ??
+ * 2F09 KANGXI RADICAL LEGS
+ * 	513F ??
+ * 2F0A KANGXI RADICAL ENTER
+ * 	5165 ??
+ * 2F0B KANGXI RADICAL EIGHT
+ * 	516B ??
+ * 2F0C KANGXI RADICAL DOWN BOX
+ * 	5182 ??
+ * 2F0D KANGXI RADICAL COVER
+ * 	5196 ??
+ * 2F0E KANGXI RADICAL ICE
+ * 	51AB ??
+ * 2F0F KANGXI RADICAL TABLE
+ * 	51E0 ??
+ * 2F10 KANGXI RADICAL OPEN BOX
+ * 	51F5 ??
+ * 2F11 KANGXI RADICAL KNIFE
+ * 	5200 ??
+ * 2F12 KANGXI RADICAL POWER
+ * 	529B ??
+ * 2F13 KANGXI RADICAL WRAP
+ * 	52F9 ??
+ * 2F14 KANGXI RADICAL SPOON
+ * 	5315 ??
+ * 2F15 KANGXI RADICAL RIGHT OPEN BOX
+ * 	531A ??
+ * 2F16 KANGXI RADICAL HIDING ENCLOSURE
+ * 	5338 ??
+ * 2F17 KANGXI RADICAL TEN
+ * 	5341 ??
+ * 2F18 KANGXI RADICAL DIVINATION
+ * 	535C ??
+ * 2F19 KANGXI RADICAL SEAL
+ * 	5369 ??
+ * 2F1A KANGXI RADICAL CLIFF
+ * 	5382 ??
+ * 2F1B KANGXI RADICAL PRIVATE
+ * 	53B6 ??
+ * 2F1C KANGXI RADICAL AGAIN
+ * 	53C8 ??
+ * 2F1D KANGXI RADICAL MOUTH
+ * 	53E3 ??
+ * 2F1E KANGXI RADICAL ENCLOSURE
+ * 	56D7 ??
+ * 2F1F KANGXI RADICAL EARTH
+ * 	571F ??
+ * 2F20 KANGXI RADICAL SCHOLAR
+ * 	58EB ??
+ * 2F21 KANGXI RADICAL GO
+ * 	5902 ??
+ * 2F22 KANGXI RADICAL GO SLOWLY
+ * 	590A ??
+ * 2F23 KANGXI RADICAL EVENING
+ * 	5915 ??
+ * 2F24 KANGXI RADICAL BIG
+ * 	5927 ??
+ * 2F25 KANGXI RADICAL WOMAN
+ * 	5973 ??
+ * 2F26 KANGXI RADICAL CHILD
+ * 	5B50 ??
+ * 2F27 KANGXI RADICAL ROOF
+ * 	5B80 ??
+ * 2F28 KANGXI RADICAL INCH
+ * 	5BF8 ??
+ * 2F29 KANGXI RADICAL SMALL
+ * 	5C0F ??
+ * 2F2A KANGXI RADICAL LAME
+ * 	5C22 ??
+ * 2F2B KANGXI RADICAL CORPSE
+ * 	5C38 ??
+ * 2F2C KANGXI RADICAL SPROUT
+ * 	5C6E ??
+ * 2F2D KANGXI RADICAL MOUNTAIN
+ * 	5C71 ??
+ * 2F2E KANGXI RADICAL RIVER
+ * 	5DDB ??
+ * 2F2F KANGXI RADICAL WORK
+ * 	5DE5 ??
+ * 2F30 KANGXI RADICAL ONESELF
+ * 	5DF1 ??
+ * 2F31 KANGXI RADICAL TURBAN
+ * 	5DFE ??
+ * 2F32 KANGXI RADICAL DRY
+ * 	5E72 ??
+ * 2F33 KANGXI RADICAL SHORT THREAD
+ * 	5E7A ??
+ * 2F34 KANGXI RADICAL DOTTED CLIFF
+ * 	5E7F ??
+ * 2F35 KANGXI RADICAL LONG STRIDE
+ * 	5EF4 ??
+ * 2F36 KANGXI RADICAL TWO HANDS
+ * 	5EFE ??
+ * 2F37 KANGXI RADICAL SHOOT
+ * 	5F0B ??
+ * 2F38 KANGXI RADICAL BOW
+ * 	5F13 ??
+ * 2F39 KANGXI RADICAL SNOUT
+ * 	5F50 ??
+ * 2F3A KANGXI RADICAL BRISTLE
+ * 	5F61 ??
+ * 2F3B KANGXI RADICAL STEP
+ * 	5F73 ??
+ * 2F3C KANGXI RADICAL HEART
+ * 	5FC3 ??
+ * 2F3D KANGXI RADICAL HALBERD
+ * 	6208 ??
+ * 2F3E KANGXI RADICAL DOOR
+ * 	6236 ??
+ * 2F3F KANGXI RADICAL HAND
+ * 	624B ??
+ * 2F40 KANGXI RADICAL BRANCH
+ * 	652F ??
+ * 2F41 KANGXI RADICAL RAP
+ * 	6534 ??
+ * 2F42 KANGXI RADICAL SCRIPT
+ * 	6587 ??
+ * 2F43 KANGXI RADICAL DIPPER
+ * 	6597 ??
+ * 2F44 KANGXI RADICAL AXE
+ * 	65A4 ??
+ * 2F45 KANGXI RADICAL SQUARE
+ * 	65B9 ??
+ * 2F46 KANGXI RADICAL NOT
+ * 	65E0 ??
+ * 2F47 KANGXI RADICAL SUN
+ * 	65E5 ??
+ * 2F48 KANGXI RADICAL SAY
+ * 	66F0 ??
+ * 2F49 KANGXI RADICAL MOON
+ * 	6708 ??
+ * 2F4A KANGXI RADICAL TREE
+ * 	6728 ??
+ * 2F4B KANGXI RADICAL LACK
+ * 	6B20 ??
+ * 2F4C KANGXI RADICAL STOP
+ * 	6B62 ??
+ * 2F4D KANGXI RADICAL DEATH
+ * 	6B79 ??
+ * 2F4E KANGXI RADICAL WEAPON
+ * 	6BB3 ??
+ * 2F4F KANGXI RADICAL DO NOT
+ * 	6BCB ??
+ * 2F50 KANGXI RADICAL COMPARE
+ * 	6BD4 ??
+ * 2F51 KANGXI RADICAL FUR
+ * 	6BDB ??
+ * 2F52 KANGXI RADICAL CLAN
+ * 	6C0F ??
+ * 2F53 KANGXI RADICAL STEAM
+ * 	6C14 ??
+ * 2F54 KANGXI RADICAL WATER
+ * 	6C34 ??
+ * 2F55 KANGXI RADICAL FIRE
+ * 	706B ??
+ * 2F56 KANGXI RADICAL CLAW
+ * 	722A ??
+ * 2F57 KANGXI RADICAL FATHER
+ * 	7236 ??
+ * 2F58 KANGXI RADICAL DOUBLE X
+ * 	723B ??
+ * 2F59 KANGXI RADICAL HALF TREE TRUNK
+ * 	723F ??
+ * 2F5A KANGXI RADICAL SLICE
+ * 	7247 ??
+ * 2F5B KANGXI RADICAL FANG
+ * 	7259 ??
+ * 2F5C KANGXI RADICAL COW
+ * 	725B ??
+ * 2F5D KANGXI RADICAL DOG
+ * 	72AC ??
+ * 2F5E KANGXI RADICAL PROFOUND
+ * 	7384 ??
+ * 2F5F KANGXI RADICAL JADE
+ * 	7389 ??
+ * 2F60 KANGXI RADICAL MELON
+ * 	74DC ??
+ * 2F61 KANGXI RADICAL TILE
+ * 	74E6 ??
+ * 2F62 KANGXI RADICAL SWEET
+ * 	7518 ??
+ * 2F63 KANGXI RADICAL LIFE
+ * 	751F ??
+ * 2F64 KANGXI RADICAL USE
+ * 	7528 ??
+ * 2F65 KANGXI RADICAL FIELD
+ * 	7530 ??
+ * 2F66 KANGXI RADICAL BOLT OF CLOTH
+ * 	758B ??
+ * 2F67 KANGXI RADICAL SICKNESS
+ * 	7592 ??
+ * 2F68 KANGXI RADICAL DOTTED TENT
+ * 	7676 ??
+ * 2F69 KANGXI RADICAL WHITE
+ * 	767D ??
+ * 2F6A KANGXI RADICAL SKIN
+ * 	76AE ??
+ * 2F6B KANGXI RADICAL DISH
+ * 	76BF ??
+ * 2F6C KANGXI RADICAL EYE
+ * 	76EE ??
+ * 2F6D KANGXI RADICAL SPEAR
+ * 	77DB ??
+ * 2F6E KANGXI RADICAL ARROW
+ * 	77E2 ??
+ * 2F6F KANGXI RADICAL STONE
+ * 	77F3 ??
+ * 2F70 KANGXI RADICAL SPIRIT
+ * 	793A ??
+ * 2F71 KANGXI RADICAL TRACK
+ * 	79B8 ??
+ * 2F72 KANGXI RADICAL GRAIN
+ * 	79BE ??
+ * 2F73 KANGXI RADICAL CAVE
+ * 	7A74 ??
+ * 2F74 KANGXI RADICAL STAND
+ * 	7ACB ??
+ * 2F75 KANGXI RADICAL BAMBOO
+ * 	7AF9 ??
+ * 2F76 KANGXI RADICAL RICE
+ * 	7C73 ??
+ * 2F77 KANGXI RADICAL SILK
+ * 	7CF8 ??
+ * 2F78 KANGXI RADICAL JAR
+ * 	7F36 ??
+ * 2F79 KANGXI RADICAL NET
+ * 	7F51 ??
+ * 2F7A KANGXI RADICAL SHEEP
+ * 	7F8A ??
+ * 2F7B KANGXI RADICAL FEATHER
+ * 	7FBD ??
+ * 2F7C KANGXI RADICAL OLD
+ * 	8001 ??
+ * 2F7D KANGXI RADICAL AND
+ * 	800C ??
+ * 2F7E KANGXI RADICAL PLOW
+ * 	8012 ??
+ * 2F7F KANGXI RADICAL EAR
+ * 	8033 ??
+ * 2F80 KANGXI RADICAL BRUSH
+ * 	807F ??
+ * 2F800 CJK COMPATIBILITY IDEOGRAPH-2F800
+ * 	4E3D ??
+ * 2F801 CJK COMPATIBILITY IDEOGRAPH-2F801
+ * 	4E38 ??
+ * 2F802 CJK COMPATIBILITY IDEOGRAPH-2F802
+ * 	4E41 ??
+ * 2F803 CJK COMPATIBILITY IDEOGRAPH-2F803
+ * 	20122 ??
+ * 2F804 CJK COMPATIBILITY IDEOGRAPH-2F804
+ * 	4F60 ??
+ * 2F805 CJK COMPATIBILITY IDEOGRAPH-2F805
+ * 	4FAE ??
+ * 2F806 CJK COMPATIBILITY IDEOGRAPH-2F806
+ * 	4FBB ??
+ * 2F807 CJK COMPATIBILITY IDEOGRAPH-2F807
+ * 	5002 ??
+ * 2F808 CJK COMPATIBILITY IDEOGRAPH-2F808
+ * 	507A ??
+ * 2F809 CJK COMPATIBILITY IDEOGRAPH-2F809
+ * 	5099 ??
+ * 2F80A CJK COMPATIBILITY IDEOGRAPH-2F80A
+ * 	50E7 ??
+ * 2F80B CJK COMPATIBILITY IDEOGRAPH-2F80B
+ * 	50CF ??
+ * 2F80C CJK COMPATIBILITY IDEOGRAPH-2F80C
+ * 	349E ??
+ * 2F80D CJK COMPATIBILITY IDEOGRAPH-2F80D
+ * 	2063A ??
+ * 2F80E CJK COMPATIBILITY IDEOGRAPH-2F80E
+ * 	514D ??
+ * 2F80F CJK COMPATIBILITY IDEOGRAPH-2F80F
+ * 	5154 ??
+ * 2F81 KANGXI RADICAL MEAT
+ * 	8089 ??
+ * 2F810 CJK COMPATIBILITY IDEOGRAPH-2F810
+ * 	5164 ??
+ * 2F811 CJK COMPATIBILITY IDEOGRAPH-2F811
+ * 	5177 ??
+ * 2F812 CJK COMPATIBILITY IDEOGRAPH-2F812
+ * 	2051C ??
+ * 2F813 CJK COMPATIBILITY IDEOGRAPH-2F813
+ * 	34B9 ??
+ * 2F814 CJK COMPATIBILITY IDEOGRAPH-2F814
+ * 	5167 ??
+ * 2F815 CJK COMPATIBILITY IDEOGRAPH-2F815
+ * 	518D ??
+ * 2F816 CJK COMPATIBILITY IDEOGRAPH-2F816
+ * 	2054B ??
+ * 2F817 CJK COMPATIBILITY IDEOGRAPH-2F817
+ * 	5197 ??
+ * 2F818 CJK COMPATIBILITY IDEOGRAPH-2F818
+ * 	51A4 ??
+ * 2F819 CJK COMPATIBILITY IDEOGRAPH-2F819
+ * 	4ECC ??
+ * 2F81A CJK COMPATIBILITY IDEOGRAPH-2F81A
+ * 	51AC ??
+ * 2F81B CJK COMPATIBILITY IDEOGRAPH-2F81B
+ * 	51B5 ??
+ * 2F81C CJK COMPATIBILITY IDEOGRAPH-2F81C
+ * 	291DF ??
+ * 2F81D CJK COMPATIBILITY IDEOGRAPH-2F81D
+ * 	51F5 ??
+ * 2F81E CJK COMPATIBILITY IDEOGRAPH-2F81E
+ * 	5203 ??
+ * 2F81F CJK COMPATIBILITY IDEOGRAPH-2F81F
+ * 	34DF ??
+ * 2F82 KANGXI RADICAL MINISTER
+ * 	81E3 ??
+ * 2F820 CJK COMPATIBILITY IDEOGRAPH-2F820
+ * 	523B ??
+ * 2F821 CJK COMPATIBILITY IDEOGRAPH-2F821
+ * 	5246 ??
+ * 2F822 CJK COMPATIBILITY IDEOGRAPH-2F822
+ * 	5272 ??
+ * 2F823 CJK COMPATIBILITY IDEOGRAPH-2F823
+ * 	5277 ??
+ * 2F824 CJK COMPATIBILITY IDEOGRAPH-2F824
+ * 	3515 ??
+ * 2F825 CJK COMPATIBILITY IDEOGRAPH-2F825
+ * 	52C7 ??
+ * 2F826 CJK COMPATIBILITY IDEOGRAPH-2F826
+ * 	52C9 ??
+ * 2F827 CJK COMPATIBILITY IDEOGRAPH-2F827
+ * 	52E4 ??
+ * 2F828 CJK COMPATIBILITY IDEOGRAPH-2F828
+ * 	52FA ??
+ * 2F829 CJK COMPATIBILITY IDEOGRAPH-2F829
+ * 	5305 ??
+ * 2F82A CJK COMPATIBILITY IDEOGRAPH-2F82A
+ * 	5306 ??
+ * 2F82B CJK COMPATIBILITY IDEOGRAPH-2F82B
+ * 	5317 ??
+ * 2F82C CJK COMPATIBILITY IDEOGRAPH-2F82C
+ * 	5349 ??
+ * 2F82D CJK COMPATIBILITY IDEOGRAPH-2F82D
+ * 	5351 ??
+ * 2F82E CJK COMPATIBILITY IDEOGRAPH-2F82E
+ * 	535A ??
+ * 2F82F CJK COMPATIBILITY IDEOGRAPH-2F82F
+ * 	5373 ??
+ * 2F83 KANGXI RADICAL SELF
+ * 	81EA ??
+ * 2F830 CJK COMPATIBILITY IDEOGRAPH-2F830
+ * 	537D ??
+ * 2F831 CJK COMPATIBILITY IDEOGRAPH-2F831
+ * 	537F ??
+ * 2F832 CJK COMPATIBILITY IDEOGRAPH-2F832
+ * 	537F ??
+ * 2F833 CJK COMPATIBILITY IDEOGRAPH-2F833
+ * 	537F ??
+ * 2F834 CJK COMPATIBILITY IDEOGRAPH-2F834
+ * 	20A2C ??
+ * 2F835 CJK COMPATIBILITY IDEOGRAPH-2F835
+ * 	7070 ??
+ * 2F836 CJK COMPATIBILITY IDEOGRAPH-2F836
+ * 	53CA ??
+ * 2F837 CJK COMPATIBILITY IDEOGRAPH-2F837
+ * 	53DF ??
+ * 2F838 CJK COMPATIBILITY IDEOGRAPH-2F838
+ * 	20B63 ??
+ * 2F839 CJK COMPATIBILITY IDEOGRAPH-2F839
+ * 	53EB ??
+ * 2F83A CJK COMPATIBILITY IDEOGRAPH-2F83A
+ * 	53F1 ??
+ * 2F83B CJK COMPATIBILITY IDEOGRAPH-2F83B
+ * 	5406 ??
+ * 2F83C CJK COMPATIBILITY IDEOGRAPH-2F83C
+ * 	549E ??
+ * 2F83D CJK COMPATIBILITY IDEOGRAPH-2F83D
+ * 	5438 ??
+ * 2F83E CJK COMPATIBILITY IDEOGRAPH-2F83E
+ * 	5448 ??
+ * 2F83F CJK COMPATIBILITY IDEOGRAPH-2F83F
+ * 	5468 ??
+ * 2F84 KANGXI RADICAL ARRIVE
+ * 	81F3 ??
+ * 2F840 CJK COMPATIBILITY IDEOGRAPH-2F840
+ * 	54A2 ??
+ * 2F841 CJK COMPATIBILITY IDEOGRAPH-2F841
+ * 	54F6 ??
+ * 2F842 CJK COMPATIBILITY IDEOGRAPH-2F842
+ * 	5510 ??
+ * 2F843 CJK COMPATIBILITY IDEOGRAPH-2F843
+ * 	5553 ??
+ * 2F844 CJK COMPATIBILITY IDEOGRAPH-2F844
+ * 	5563 ??
+ * 2F845 CJK COMPATIBILITY IDEOGRAPH-2F845
+ * 	5584 ??
+ * 2F846 CJK COMPATIBILITY IDEOGRAPH-2F846
+ * 	5584 ??
+ * 2F847 CJK COMPATIBILITY IDEOGRAPH-2F847
+ * 	5599 ??
+ * 2F848 CJK COMPATIBILITY IDEOGRAPH-2F848
+ * 	55AB ??
+ * 2F849 CJK COMPATIBILITY IDEOGRAPH-2F849
+ * 	55B3 ??
+ * 2F84A CJK COMPATIBILITY IDEOGRAPH-2F84A
+ * 	55C2 ??
+ * 2F84B CJK COMPATIBILITY IDEOGRAPH-2F84B
+ * 	5716 ??
+ * 2F84C CJK COMPATIBILITY IDEOGRAPH-2F84C
+ * 	5606 ??
+ * 2F84D CJK COMPATIBILITY IDEOGRAPH-2F84D
+ * 	5717 ??
+ * 2F84E CJK COMPATIBILITY IDEOGRAPH-2F84E
+ * 	5651 ??
+ * 2F84F CJK COMPATIBILITY IDEOGRAPH-2F84F
+ * 	5674 ??
+ * 2F85 KANGXI RADICAL MORTAR
+ * 	81FC ??
+ * 2F850 CJK COMPATIBILITY IDEOGRAPH-2F850
+ * 	5207 ??
+ * 2F851 CJK COMPATIBILITY IDEOGRAPH-2F851
+ * 	58EE ??
+ * 2F852 CJK COMPATIBILITY IDEOGRAPH-2F852
+ * 	57CE ??
+ * 2F853 CJK COMPATIBILITY IDEOGRAPH-2F853
+ * 	57F4 ??
+ * 2F854 CJK COMPATIBILITY IDEOGRAPH-2F854
+ * 	580D ??
+ * 2F855 CJK COMPATIBILITY IDEOGRAPH-2F855
+ * 	578B ??
+ * 2F856 CJK COMPATIBILITY IDEOGRAPH-2F856
+ * 	5832 ??
+ * 2F857 CJK COMPATIBILITY IDEOGRAPH-2F857
+ * 	5831 ??
+ * 2F858 CJK COMPATIBILITY IDEOGRAPH-2F858
+ * 	58AC ??
+ * 2F859 CJK COMPATIBILITY IDEOGRAPH-2F859
+ * 	214E4 ??
+ * 2F85A CJK COMPATIBILITY IDEOGRAPH-2F85A
+ * 	58F2 ??
+ * 2F85B CJK COMPATIBILITY IDEOGRAPH-2F85B
+ * 	58F7 ??
+ * 2F85C CJK COMPATIBILITY IDEOGRAPH-2F85C
+ * 	5906 ??
+ * 2F85D CJK COMPATIBILITY IDEOGRAPH-2F85D
+ * 	591A ??
+ * 2F85E CJK COMPATIBILITY IDEOGRAPH-2F85E
+ * 	5922 ??
+ * 2F85F CJK COMPATIBILITY IDEOGRAPH-2F85F
+ * 	5962 ??
+ * 2F86 KANGXI RADICAL TONGUE
+ * 	820C ??
+ * 2F860 CJK COMPATIBILITY IDEOGRAPH-2F860
+ * 	216A8 ??
+ * 2F861 CJK COMPATIBILITY IDEOGRAPH-2F861
+ * 	216EA ??
+ * 2F862 CJK COMPATIBILITY IDEOGRAPH-2F862
+ * 	59EC ??
+ * 2F863 CJK COMPATIBILITY IDEOGRAPH-2F863
+ * 	5A1B ??
+ * 2F864 CJK COMPATIBILITY IDEOGRAPH-2F864
+ * 	5A27 ??
+ * 2F865 CJK COMPATIBILITY IDEOGRAPH-2F865
+ * 	59D8 ??
+ * 2F866 CJK COMPATIBILITY IDEOGRAPH-2F866
+ * 	5A66 ??
+ * 2F867 CJK COMPATIBILITY IDEOGRAPH-2F867
+ * 	36EE ??
+ * 2F868 CJK COMPATIBILITY IDEOGRAPH-2F868
+ * 	2136A ??
+ * 2F869 CJK COMPATIBILITY IDEOGRAPH-2F869
+ * 	5B08 ??
+ * 2F86A CJK COMPATIBILITY IDEOGRAPH-2F86A
+ * 	5B3E ??
+ * 2F86B CJK COMPATIBILITY IDEOGRAPH-2F86B
+ * 	5B3E ??
+ * 2F86C CJK COMPATIBILITY IDEOGRAPH-2F86C
+ * 	219C8 ??
+ * 2F86D CJK COMPATIBILITY IDEOGRAPH-2F86D
+ * 	5BC3 ??
+ * 2F86E CJK COMPATIBILITY IDEOGRAPH-2F86E
+ * 	5BD8 ??
+ * 2F86F CJK COMPATIBILITY IDEOGRAPH-2F86F
+ * 	5BE7 ??
+ * 2F87 KANGXI RADICAL OPPOSE
+ * 	821B ??
+ * 2F870 CJK COMPATIBILITY IDEOGRAPH-2F870
+ * 	5BF3 ??
+ * 2F871 CJK COMPATIBILITY IDEOGRAPH-2F871
+ * 	21B18 ??
+ * 2F872 CJK COMPATIBILITY IDEOGRAPH-2F872
+ * 	5BFF ??
+ * 2F873 CJK COMPATIBILITY IDEOGRAPH-2F873
+ * 	5C06 ??
+ * 2F874 CJK COMPATIBILITY IDEOGRAPH-2F874
+ * 	5F33 ??
+ * 2F875 CJK COMPATIBILITY IDEOGRAPH-2F875
+ * 	5C22 ??
+ * 2F876 CJK COMPATIBILITY IDEOGRAPH-2F876
+ * 	3781 ??
+ * 2F877 CJK COMPATIBILITY IDEOGRAPH-2F877
+ * 	5C60 ??
+ * 2F878 CJK COMPATIBILITY IDEOGRAPH-2F878
+ * 	5C6E ??
+ * 2F879 CJK COMPATIBILITY IDEOGRAPH-2F879
+ * 	5CC0 ??
+ * 2F87A CJK COMPATIBILITY IDEOGRAPH-2F87A
+ * 	5C8D ??
+ * 2F87B CJK COMPATIBILITY IDEOGRAPH-2F87B
+ * 	21DE4 ??
+ * 2F87C CJK COMPATIBILITY IDEOGRAPH-2F87C
+ * 	5D43 ??
+ * 2F87D CJK COMPATIBILITY IDEOGRAPH-2F87D
+ * 	21DE6 ??
+ * 2F87E CJK COMPATIBILITY IDEOGRAPH-2F87E
+ * 	5D6E ??
+ * 2F87F CJK COMPATIBILITY IDEOGRAPH-2F87F
+ * 	5D6B ??
+ * 2F88 KANGXI RADICAL BOAT
+ * 	821F ??
+ * 2F880 CJK COMPATIBILITY IDEOGRAPH-2F880
+ * 	5D7C ??
+ * 2F881 CJK COMPATIBILITY IDEOGRAPH-2F881
+ * 	5DE1 ??
+ * 2F882 CJK COMPATIBILITY IDEOGRAPH-2F882
+ * 	5DE2 ??
+ * 2F883 CJK COMPATIBILITY IDEOGRAPH-2F883
+ * 	382F ??
+ * 2F884 CJK COMPATIBILITY IDEOGRAPH-2F884
+ * 	5DFD ??
+ * 2F885 CJK COMPATIBILITY IDEOGRAPH-2F885
+ * 	5E28 ??
+ * 2F886 CJK COMPATIBILITY IDEOGRAPH-2F886
+ * 	5E3D ??
+ * 2F887 CJK COMPATIBILITY IDEOGRAPH-2F887
+ * 	5E69 ??
+ * 2F888 CJK COMPATIBILITY IDEOGRAPH-2F888
+ * 	3862 ??
+ * 2F889 CJK COMPATIBILITY IDEOGRAPH-2F889
+ * 	22183 ??
+ * 2F88A CJK COMPATIBILITY IDEOGRAPH-2F88A
+ * 	387C ??
+ * 2F88B CJK COMPATIBILITY IDEOGRAPH-2F88B
+ * 	5EB0 ??
+ * 2F88C CJK COMPATIBILITY IDEOGRAPH-2F88C
+ * 	5EB3 ??
+ * 2F88D CJK COMPATIBILITY IDEOGRAPH-2F88D
+ * 	5EB6 ??
+ * 2F88E CJK COMPATIBILITY IDEOGRAPH-2F88E
+ * 	5ECA ??
+ * 2F88F CJK COMPATIBILITY IDEOGRAPH-2F88F
+ * 	2A392 ??
+ * 2F89 KANGXI RADICAL STOPPING
+ * 	826E ??
+ * 2F890 CJK COMPATIBILITY IDEOGRAPH-2F890
+ * 	5EFE ??
+ * 2F891 CJK COMPATIBILITY IDEOGRAPH-2F891
+ * 	22331 ??
+ * 2F892 CJK COMPATIBILITY IDEOGRAPH-2F892
+ * 	22331 ??
+ * 2F893 CJK COMPATIBILITY IDEOGRAPH-2F893
+ * 	8201 ??
+ * 2F894 CJK COMPATIBILITY IDEOGRAPH-2F894
+ * 	5F22 ??
+ * 2F895 CJK COMPATIBILITY IDEOGRAPH-2F895
+ * 	5F22 ??
+ * 2F896 CJK COMPATIBILITY IDEOGRAPH-2F896
+ * 	38C7 ??
+ * 2F897 CJK COMPATIBILITY IDEOGRAPH-2F897
+ * 	232B8 ??
+ * 2F898 CJK COMPATIBILITY IDEOGRAPH-2F898
+ * 	261DA ??
+ * 2F899 CJK COMPATIBILITY IDEOGRAPH-2F899
+ * 	5F62 ??
+ * 2F89A CJK COMPATIBILITY IDEOGRAPH-2F89A
+ * 	5F6B ??
+ * 2F89B CJK COMPATIBILITY IDEOGRAPH-2F89B
+ * 	38E3 ??
+ * 2F89C CJK COMPATIBILITY IDEOGRAPH-2F89C
+ * 	5F9A ??
+ * 2F89D CJK COMPATIBILITY IDEOGRAPH-2F89D
+ * 	5FCD ??
+ * 2F89E CJK COMPATIBILITY IDEOGRAPH-2F89E
+ * 	5FD7 ??
+ * 2F89F CJK COMPATIBILITY IDEOGRAPH-2F89F
+ * 	5FF9 ??
+ * 2F8A KANGXI RADICAL COLOR
+ * 	8272 ??
+ * 2F8A0 CJK COMPATIBILITY IDEOGRAPH-2F8A0
+ * 	6081 ??
+ * 2F8A1 CJK COMPATIBILITY IDEOGRAPH-2F8A1
+ * 	393A ??
+ * 2F8A2 CJK COMPATIBILITY IDEOGRAPH-2F8A2
+ * 	391C ??
+ * 2F8A3 CJK COMPATIBILITY IDEOGRAPH-2F8A3
+ * 	6094 ??
+ * 2F8A4 CJK COMPATIBILITY IDEOGRAPH-2F8A4
+ * 	226D4 ??
+ * 2F8A5 CJK COMPATIBILITY IDEOGRAPH-2F8A5
+ * 	60C7 ??
+ * 2F8A6 CJK COMPATIBILITY IDEOGRAPH-2F8A6
+ * 	6148 ??
+ * 2F8A7 CJK COMPATIBILITY IDEOGRAPH-2F8A7
+ * 	614C ??
+ * 2F8A8 CJK COMPATIBILITY IDEOGRAPH-2F8A8
+ * 	614E ??
+ * 2F8A9 CJK COMPATIBILITY IDEOGRAPH-2F8A9
+ * 	614C ??
+ * 2F8AA CJK COMPATIBILITY IDEOGRAPH-2F8AA
+ * 	617A ??
+ * 2F8AB CJK COMPATIBILITY IDEOGRAPH-2F8AB
+ * 	618E ??
+ * 2F8AC CJK COMPATIBILITY IDEOGRAPH-2F8AC
+ * 	61B2 ??
+ * 2F8AD CJK COMPATIBILITY IDEOGRAPH-2F8AD
+ * 	61A4 ??
+ * 2F8AE CJK COMPATIBILITY IDEOGRAPH-2F8AE
+ * 	61AF ??
+ * 2F8AF CJK COMPATIBILITY IDEOGRAPH-2F8AF
+ * 	61DE ??
+ * 2F8B KANGXI RADICAL GRASS
+ * 	8278 ??
+ * 2F8B0 CJK COMPATIBILITY IDEOGRAPH-2F8B0
+ * 	61F2 ??
+ * 2F8B1 CJK COMPATIBILITY IDEOGRAPH-2F8B1
+ * 	61F6 ??
+ * 2F8B2 CJK COMPATIBILITY IDEOGRAPH-2F8B2
+ * 	6210 ??
+ * 2F8B3 CJK COMPATIBILITY IDEOGRAPH-2F8B3
+ * 	621B ??
+ * 2F8B4 CJK COMPATIBILITY IDEOGRAPH-2F8B4
+ * 	625D ??
+ * 2F8B5 CJK COMPATIBILITY IDEOGRAPH-2F8B5
+ * 	62B1 ??
+ * 2F8B6 CJK COMPATIBILITY IDEOGRAPH-2F8B6
+ * 	62D4 ??
+ * 2F8B7 CJK COMPATIBILITY IDEOGRAPH-2F8B7
+ * 	6350 ??
+ * 2F8B8 CJK COMPATIBILITY IDEOGRAPH-2F8B8
+ * 	22B0C ??
+ * 2F8B9 CJK COMPATIBILITY IDEOGRAPH-2F8B9
+ * 	633D ??
+ * 2F8BA CJK COMPATIBILITY IDEOGRAPH-2F8BA
+ * 	62FC ??
+ * 2F8BB CJK COMPATIBILITY IDEOGRAPH-2F8BB
+ * 	6368 ??
+ * 2F8BC CJK COMPATIBILITY IDEOGRAPH-2F8BC
+ * 	6383 ??
+ * 2F8BD CJK COMPATIBILITY IDEOGRAPH-2F8BD
+ * 	63E4 ??
+ * 2F8BE CJK COMPATIBILITY IDEOGRAPH-2F8BE
+ * 	22BF1 ??
+ * 2F8BF CJK COMPATIBILITY IDEOGRAPH-2F8BF
+ * 	6422 ??
+ * 2F8C KANGXI RADICAL TIGER
+ * 	864D ??
+ * 2F8C0 CJK COMPATIBILITY IDEOGRAPH-2F8C0
+ * 	63C5 ??
+ * 2F8C1 CJK COMPATIBILITY IDEOGRAPH-2F8C1
+ * 	63A9 ??
+ * 2F8C2 CJK COMPATIBILITY IDEOGRAPH-2F8C2
+ * 	3A2E ??
+ * 2F8C3 CJK COMPATIBILITY IDEOGRAPH-2F8C3
+ * 	6469 ??
+ * 2F8C4 CJK COMPATIBILITY IDEOGRAPH-2F8C4
+ * 	647E ??
+ * 2F8C5 CJK COMPATIBILITY IDEOGRAPH-2F8C5
+ * 	649D ??
+ * 2F8C6 CJK COMPATIBILITY IDEOGRAPH-2F8C6
+ * 	6477 ??
+ * 2F8C7 CJK COMPATIBILITY IDEOGRAPH-2F8C7
+ * 	3A6C ??
+ * 2F8C8 CJK COMPATIBILITY IDEOGRAPH-2F8C8
+ * 	654F ??
+ * 2F8C9 CJK COMPATIBILITY IDEOGRAPH-2F8C9
+ * 	656C ??
+ * 2F8CA CJK COMPATIBILITY IDEOGRAPH-2F8CA
+ * 	2300A ??
+ * 2F8CB CJK COMPATIBILITY IDEOGRAPH-2F8CB
+ * 	65E3 ??
+ * 2F8CC CJK COMPATIBILITY IDEOGRAPH-2F8CC
+ * 	66F8 ??
+ * 2F8CD CJK COMPATIBILITY IDEOGRAPH-2F8CD
+ * 	6649 ??
+ * 2F8CE CJK COMPATIBILITY IDEOGRAPH-2F8CE
+ * 	3B19 ??
+ * 2F8CF CJK COMPATIBILITY IDEOGRAPH-2F8CF
+ * 	6691 ??
+ * 2F8D KANGXI RADICAL INSECT
+ * 	866B ??
+ * 2F8D0 CJK COMPATIBILITY IDEOGRAPH-2F8D0
+ * 	3B08 ??
+ * 2F8D1 CJK COMPATIBILITY IDEOGRAPH-2F8D1
+ * 	3AE4 ??
+ * 2F8D2 CJK COMPATIBILITY IDEOGRAPH-2F8D2
+ * 	5192 ??
+ * 2F8D3 CJK COMPATIBILITY IDEOGRAPH-2F8D3
+ * 	5195 ??
+ * 2F8D4 CJK COMPATIBILITY IDEOGRAPH-2F8D4
+ * 	6700 ??
+ * 2F8D5 CJK COMPATIBILITY IDEOGRAPH-2F8D5
+ * 	669C ??
+ * 2F8D6 CJK COMPATIBILITY IDEOGRAPH-2F8D6
+ * 	80AD ??
+ * 2F8D7 CJK COMPATIBILITY IDEOGRAPH-2F8D7
+ * 	43D9 ??
+ * 2F8D8 CJK COMPATIBILITY IDEOGRAPH-2F8D8
+ * 	6717 ??
+ * 2F8D9 CJK COMPATIBILITY IDEOGRAPH-2F8D9
+ * 	671B ??
+ * 2F8DA CJK COMPATIBILITY IDEOGRAPH-2F8DA
+ * 	6721 ??
+ * 2F8DB CJK COMPATIBILITY IDEOGRAPH-2F8DB
+ * 	675E ??
+ * 2F8DC CJK COMPATIBILITY IDEOGRAPH-2F8DC
+ * 	6753 ??
+ * 2F8DD CJK COMPATIBILITY IDEOGRAPH-2F8DD
+ * 	233C3 ??
+ * 2F8DE CJK COMPATIBILITY IDEOGRAPH-2F8DE
+ * 	3B49 ??
+ * 2F8DF CJK COMPATIBILITY IDEOGRAPH-2F8DF
+ * 	67FA ??
+ * 2F8E KANGXI RADICAL BLOOD
+ * 	8840 ??
+ * 2F8E0 CJK COMPATIBILITY IDEOGRAPH-2F8E0
+ * 	6785 ??
+ * 2F8E1 CJK COMPATIBILITY IDEOGRAPH-2F8E1
+ * 	6852 ??
+ * 2F8E2 CJK COMPATIBILITY IDEOGRAPH-2F8E2
+ * 	6885 ??
+ * 2F8E3 CJK COMPATIBILITY IDEOGRAPH-2F8E3
+ * 	2346D ??
+ * 2F8E4 CJK COMPATIBILITY IDEOGRAPH-2F8E4
+ * 	688E ??
+ * 2F8E5 CJK COMPATIBILITY IDEOGRAPH-2F8E5
+ * 	681F ??
+ * 2F8E6 CJK COMPATIBILITY IDEOGRAPH-2F8E6
+ * 	6914 ??
+ * 2F8E7 CJK COMPATIBILITY IDEOGRAPH-2F8E7
+ * 	3B9D ??
+ * 2F8E8 CJK COMPATIBILITY IDEOGRAPH-2F8E8
+ * 	6942 ??
+ * 2F8E9 CJK COMPATIBILITY IDEOGRAPH-2F8E9
+ * 	69A3 ??
+ * 2F8EA CJK COMPATIBILITY IDEOGRAPH-2F8EA
+ * 	69EA ??
+ * 2F8EB CJK COMPATIBILITY IDEOGRAPH-2F8EB
+ * 	6AA8 ??
+ * 2F8EC CJK COMPATIBILITY IDEOGRAPH-2F8EC
+ * 	236A3 ??
+ * 2F8ED CJK COMPATIBILITY IDEOGRAPH-2F8ED
+ * 	6ADB ??
+ * 2F8EE CJK COMPATIBILITY IDEOGRAPH-2F8EE
+ * 	3C18 ??
+ * 2F8EF CJK COMPATIBILITY IDEOGRAPH-2F8EF
+ * 	6B21 ??
+ * 2F8F KANGXI RADICAL WALK ENCLOSURE
+ * 	884C ??
+ * 2F8F0 CJK COMPATIBILITY IDEOGRAPH-2F8F0
+ * 	238A7 ??
+ * 2F8F1 CJK COMPATIBILITY IDEOGRAPH-2F8F1
+ * 	6B54 ??
+ * 2F8F2 CJK COMPATIBILITY IDEOGRAPH-2F8F2
+ * 	3C4E ??
+ * 2F8F3 CJK COMPATIBILITY IDEOGRAPH-2F8F3
+ * 	6B72 ??
+ * 2F8F4 CJK COMPATIBILITY IDEOGRAPH-2F8F4
+ * 	6B9F ??
+ * 2F8F5 CJK COMPATIBILITY IDEOGRAPH-2F8F5
+ * 	6BBA ??
+ * 2F8F6 CJK COMPATIBILITY IDEOGRAPH-2F8F6
+ * 	6BBB ??
+ * 2F8F7 CJK COMPATIBILITY IDEOGRAPH-2F8F7
+ * 	23A8D ??
+ * 2F8F8 CJK COMPATIBILITY IDEOGRAPH-2F8F8
+ * 	21D0B ??
+ * 2F8F9 CJK COMPATIBILITY IDEOGRAPH-2F8F9
+ * 	23AFA ??
+ * 2F8FA CJK COMPATIBILITY IDEOGRAPH-2F8FA
+ * 	6C4E ??
+ * 2F8FB CJK COMPATIBILITY IDEOGRAPH-2F8FB
+ * 	23CBC ??
+ * 2F8FC CJK COMPATIBILITY IDEOGRAPH-2F8FC
+ * 	6CBF ??
+ * 2F8FD CJK COMPATIBILITY IDEOGRAPH-2F8FD
+ * 	6CCD ??
+ * 2F8FE CJK COMPATIBILITY IDEOGRAPH-2F8FE
+ * 	6C67 ??
+ * 2F8FF CJK COMPATIBILITY IDEOGRAPH-2F8FF
+ * 	6D16 ??
+ * 2F90 KANGXI RADICAL CLOTHES
+ * 	8863 ??
+ * 2F900 CJK COMPATIBILITY IDEOGRAPH-2F900
+ * 	6D3E ??
+ * 2F901 CJK COMPATIBILITY IDEOGRAPH-2F901
+ * 	6D77 ??
+ * 2F902 CJK COMPATIBILITY IDEOGRAPH-2F902
+ * 	6D41 ??
+ * 2F903 CJK COMPATIBILITY IDEOGRAPH-2F903
+ * 	6D69 ??
+ * 2F904 CJK COMPATIBILITY IDEOGRAPH-2F904
+ * 	6D78 ??
+ * 2F905 CJK COMPATIBILITY IDEOGRAPH-2F905
+ * 	6D85 ??
+ * 2F906 CJK COMPATIBILITY IDEOGRAPH-2F906
+ * 	23D1E ??
+ * 2F907 CJK COMPATIBILITY IDEOGRAPH-2F907
+ * 	6D34 ??
+ * 2F908 CJK COMPATIBILITY IDEOGRAPH-2F908
+ * 	6E2F ??
+ * 2F909 CJK COMPATIBILITY IDEOGRAPH-2F909
+ * 	6E6E ??
+ * 2F90A CJK COMPATIBILITY IDEOGRAPH-2F90A
+ * 	3D33 ??
+ * 2F90B CJK COMPATIBILITY IDEOGRAPH-2F90B
+ * 	6ECB ??
+ * 2F90C CJK COMPATIBILITY IDEOGRAPH-2F90C
+ * 	6EC7 ??
+ * 2F90D CJK COMPATIBILITY IDEOGRAPH-2F90D
+ * 	23ED1 ??
+ * 2F90E CJK COMPATIBILITY IDEOGRAPH-2F90E
+ * 	6DF9 ??
+ * 2F90F CJK COMPATIBILITY IDEOGRAPH-2F90F
+ * 	6F6E ??
+ * 2F91 KANGXI RADICAL WEST
+ * 	897E ??
+ * 2F910 CJK COMPATIBILITY IDEOGRAPH-2F910
+ * 	23F5E ??
+ * 2F911 CJK COMPATIBILITY IDEOGRAPH-2F911
+ * 	23F8E ??
+ * 2F912 CJK COMPATIBILITY IDEOGRAPH-2F912
+ * 	6FC6 ??
+ * 2F913 CJK COMPATIBILITY IDEOGRAPH-2F913
+ * 	7039 ??
+ * 2F914 CJK COMPATIBILITY IDEOGRAPH-2F914
+ * 	701E ??
+ * 2F915 CJK COMPATIBILITY IDEOGRAPH-2F915
+ * 	701B ??
+ * 2F916 CJK COMPATIBILITY IDEOGRAPH-2F916
+ * 	3D96 ??
+ * 2F917 CJK COMPATIBILITY IDEOGRAPH-2F917
+ * 	704A ??
+ * 2F918 CJK COMPATIBILITY IDEOGRAPH-2F918
+ * 	707D ??
+ * 2F919 CJK COMPATIBILITY IDEOGRAPH-2F919
+ * 	7077 ??
+ * 2F91A CJK COMPATIBILITY IDEOGRAPH-2F91A
+ * 	70AD ??
+ * 2F91B CJK COMPATIBILITY IDEOGRAPH-2F91B
+ * 	20525 ??
+ * 2F91C CJK COMPATIBILITY IDEOGRAPH-2F91C
+ * 	7145 ??
+ * 2F91D CJK COMPATIBILITY IDEOGRAPH-2F91D
+ * 	24263 ??
+ * 2F91E CJK COMPATIBILITY IDEOGRAPH-2F91E
+ * 	719C ??
+ * 2F91F CJK COMPATIBILITY IDEOGRAPH-2F91F
+ * 	43AB ??
+ * 2F92 KANGXI RADICAL SEE
+ * 	898B ??
+ * 2F920 CJK COMPATIBILITY IDEOGRAPH-2F920
+ * 	7228 ??
+ * 2F921 CJK COMPATIBILITY IDEOGRAPH-2F921
+ * 	7235 ??
+ * 2F922 CJK COMPATIBILITY IDEOGRAPH-2F922
+ * 	7250 ??
+ * 2F923 CJK COMPATIBILITY IDEOGRAPH-2F923
+ * 	24608 ??
+ * 2F924 CJK COMPATIBILITY IDEOGRAPH-2F924
+ * 	7280 ??
+ * 2F925 CJK COMPATIBILITY IDEOGRAPH-2F925
+ * 	7295 ??
+ * 2F926 CJK COMPATIBILITY IDEOGRAPH-2F926
+ * 	24735 ??
+ * 2F927 CJK COMPATIBILITY IDEOGRAPH-2F927
+ * 	24814 ??
+ * 2F928 CJK COMPATIBILITY IDEOGRAPH-2F928
+ * 	737A ??
+ * 2F929 CJK COMPATIBILITY IDEOGRAPH-2F929
+ * 	738B ??
+ * 2F92A CJK COMPATIBILITY IDEOGRAPH-2F92A
+ * 	3EAC ??
+ * 2F92B CJK COMPATIBILITY IDEOGRAPH-2F92B
+ * 	73A5 ??
+ * 2F92C CJK COMPATIBILITY IDEOGRAPH-2F92C
+ * 	3EB8 ??
+ * 2F92D CJK COMPATIBILITY IDEOGRAPH-2F92D
+ * 	3EB8 ??
+ * 2F92E CJK COMPATIBILITY IDEOGRAPH-2F92E
+ * 	7447 ??
+ * 2F92F CJK COMPATIBILITY IDEOGRAPH-2F92F
+ * 	745C ??
+ * 2F93 KANGXI RADICAL HORN
+ * 	89D2 ??
+ * 2F930 CJK COMPATIBILITY IDEOGRAPH-2F930
+ * 	7471 ??
+ * 2F931 CJK COMPATIBILITY IDEOGRAPH-2F931
+ * 	7485 ??
+ * 2F932 CJK COMPATIBILITY IDEOGRAPH-2F932
+ * 	74CA ??
+ * 2F933 CJK COMPATIBILITY IDEOGRAPH-2F933
+ * 	3F1B ??
+ * 2F934 CJK COMPATIBILITY IDEOGRAPH-2F934
+ * 	7524 ??
+ * 2F935 CJK COMPATIBILITY IDEOGRAPH-2F935
+ * 	24C36 ??
+ * 2F936 CJK COMPATIBILITY IDEOGRAPH-2F936
+ * 	753E ??
+ * 2F937 CJK COMPATIBILITY IDEOGRAPH-2F937
+ * 	24C92 ??
+ * 2F938 CJK COMPATIBILITY IDEOGRAPH-2F938
+ * 	7570 ??
+ * 2F939 CJK COMPATIBILITY IDEOGRAPH-2F939
+ * 	2219F ??
+ * 2F93A CJK COMPATIBILITY IDEOGRAPH-2F93A
+ * 	7610 ??
+ * 2F93B CJK COMPATIBILITY IDEOGRAPH-2F93B
+ * 	24FA1 ??
+ * 2F93C CJK COMPATIBILITY IDEOGRAPH-2F93C
+ * 	24FB8 ??
+ * 2F93D CJK COMPATIBILITY IDEOGRAPH-2F93D
+ * 	25044 ??
+ * 2F93E CJK COMPATIBILITY IDEOGRAPH-2F93E
+ * 	3FFC ??
+ * 2F93F CJK COMPATIBILITY IDEOGRAPH-2F93F
+ * 	4008 ??
+ * 2F94 KANGXI RADICAL SPEECH
+ * 	8A00 ??
+ * 2F940 CJK COMPATIBILITY IDEOGRAPH-2F940
+ * 	76F4 ??
+ * 2F941 CJK COMPATIBILITY IDEOGRAPH-2F941
+ * 	250F3 ??
+ * 2F942 CJK COMPATIBILITY IDEOGRAPH-2F942
+ * 	250F2 ??
+ * 2F943 CJK COMPATIBILITY IDEOGRAPH-2F943
+ * 	25119 ??
+ * 2F944 CJK COMPATIBILITY IDEOGRAPH-2F944
+ * 	25133 ??
+ * 2F945 CJK COMPATIBILITY IDEOGRAPH-2F945
+ * 	771E ??
+ * 2F946 CJK COMPATIBILITY IDEOGRAPH-2F946
+ * 	771F ??
+ * 2F947 CJK COMPATIBILITY IDEOGRAPH-2F947
+ * 	771F ??
+ * 2F948 CJK COMPATIBILITY IDEOGRAPH-2F948
+ * 	774A ??
+ * 2F949 CJK COMPATIBILITY IDEOGRAPH-2F949
+ * 	4039 ??
+ * 2F94A CJK COMPATIBILITY IDEOGRAPH-2F94A
+ * 	778B ??
+ * 2F94B CJK COMPATIBILITY IDEOGRAPH-2F94B
+ * 	4046 ??
+ * 2F94C CJK COMPATIBILITY IDEOGRAPH-2F94C
+ * 	4096 ??
+ * 2F94D CJK COMPATIBILITY IDEOGRAPH-2F94D
+ * 	2541D ??
+ * 2F94E CJK COMPATIBILITY IDEOGRAPH-2F94E
+ * 	784E ??
+ * 2F94F CJK COMPATIBILITY IDEOGRAPH-2F94F
+ * 	788C ??
+ * 2F95 KANGXI RADICAL VALLEY
+ * 	8C37 ??
+ * 2F950 CJK COMPATIBILITY IDEOGRAPH-2F950
+ * 	78CC ??
+ * 2F951 CJK COMPATIBILITY IDEOGRAPH-2F951
+ * 	40E3 ??
+ * 2F952 CJK COMPATIBILITY IDEOGRAPH-2F952
+ * 	25626 ??
+ * 2F953 CJK COMPATIBILITY IDEOGRAPH-2F953
+ * 	7956 ??
+ * 2F954 CJK COMPATIBILITY IDEOGRAPH-2F954
+ * 	2569A ??
+ * 2F955 CJK COMPATIBILITY IDEOGRAPH-2F955
+ * 	256C5 ??
+ * 2F956 CJK COMPATIBILITY IDEOGRAPH-2F956
+ * 	798F ??
+ * 2F957 CJK COMPATIBILITY IDEOGRAPH-2F957
+ * 	79EB ??
+ * 2F958 CJK COMPATIBILITY IDEOGRAPH-2F958
+ * 	412F ??
+ * 2F959 CJK COMPATIBILITY IDEOGRAPH-2F959
+ * 	7A40 ??
+ * 2F95A CJK COMPATIBILITY IDEOGRAPH-2F95A
+ * 	7A4A ??
+ * 2F95B CJK COMPATIBILITY IDEOGRAPH-2F95B
+ * 	7A4F ??
+ * 2F95C CJK COMPATIBILITY IDEOGRAPH-2F95C
+ * 	2597C ??
+ * 2F95D CJK COMPATIBILITY IDEOGRAPH-2F95D
+ * 	25AA7 ??
+ * 2F95E CJK COMPATIBILITY IDEOGRAPH-2F95E
+ * 	25AA7 ??
+ * 2F95F CJK COMPATIBILITY IDEOGRAPH-2F95F
+ * 	7AAE ??
+ * 2F96 KANGXI RADICAL BEAN
+ * 	8C46 ??
+ * 2F960 CJK COMPATIBILITY IDEOGRAPH-2F960
+ * 	4202 ??
+ * 2F961 CJK COMPATIBILITY IDEOGRAPH-2F961
+ * 	25BAB ??
+ * 2F962 CJK COMPATIBILITY IDEOGRAPH-2F962
+ * 	7BC6 ??
+ * 2F963 CJK COMPATIBILITY IDEOGRAPH-2F963
+ * 	7BC9 ??
+ * 2F964 CJK COMPATIBILITY IDEOGRAPH-2F964
+ * 	4227 ??
+ * 2F965 CJK COMPATIBILITY IDEOGRAPH-2F965
+ * 	25C80 ??
+ * 2F966 CJK COMPATIBILITY IDEOGRAPH-2F966
+ * 	7CD2 ??
+ * 2F967 CJK COMPATIBILITY IDEOGRAPH-2F967
+ * 	42A0 ??
+ * 2F968 CJK COMPATIBILITY IDEOGRAPH-2F968
+ * 	7CE8 ??
+ * 2F969 CJK COMPATIBILITY IDEOGRAPH-2F969
+ * 	7CE3 ??
+ * 2F96A CJK COMPATIBILITY IDEOGRAPH-2F96A
+ * 	7D00 ??
+ * 2F96B CJK COMPATIBILITY IDEOGRAPH-2F96B
+ * 	25F86 ??
+ * 2F96C CJK COMPATIBILITY IDEOGRAPH-2F96C
+ * 	7D63 ??
+ * 2F96D CJK COMPATIBILITY IDEOGRAPH-2F96D
+ * 	4301 ??
+ * 2F96E CJK COMPATIBILITY IDEOGRAPH-2F96E
+ * 	7DC7 ??
+ * 2F96F CJK COMPATIBILITY IDEOGRAPH-2F96F
+ * 	7E02 ??
+ * 2F97 KANGXI RADICAL PIG
+ * 	8C55 ??
+ * 2F970 CJK COMPATIBILITY IDEOGRAPH-2F970
+ * 	7E45 ??
+ * 2F971 CJK COMPATIBILITY IDEOGRAPH-2F971
+ * 	4334 ??
+ * 2F972 CJK COMPATIBILITY IDEOGRAPH-2F972
+ * 	26228 ??
+ * 2F973 CJK COMPATIBILITY IDEOGRAPH-2F973
+ * 	26247 ??
+ * 2F974 CJK COMPATIBILITY IDEOGRAPH-2F974
+ * 	4359 ??
+ * 2F975 CJK COMPATIBILITY IDEOGRAPH-2F975
+ * 	262D9 ??
+ * 2F976 CJK COMPATIBILITY IDEOGRAPH-2F976
+ * 	7F7A ??
+ * 2F977 CJK COMPATIBILITY IDEOGRAPH-2F977
+ * 	2633E ??
+ * 2F978 CJK COMPATIBILITY IDEOGRAPH-2F978
+ * 	7F95 ??
+ * 2F979 CJK COMPATIBILITY IDEOGRAPH-2F979
+ * 	7FFA ??
+ * 2F97A CJK COMPATIBILITY IDEOGRAPH-2F97A
+ * 	8005 ??
+ * 2F97B CJK COMPATIBILITY IDEOGRAPH-2F97B
+ * 	264DA ??
+ * 2F97C CJK COMPATIBILITY IDEOGRAPH-2F97C
+ * 	26523 ??
+ * 2F97D CJK COMPATIBILITY IDEOGRAPH-2F97D
+ * 	8060 ??
+ * 2F97E CJK COMPATIBILITY IDEOGRAPH-2F97E
+ * 	265A8 ??
+ * 2F97F CJK COMPATIBILITY IDEOGRAPH-2F97F
+ * 	8070 ??
+ * 2F98 KANGXI RADICAL BADGER
+ * 	8C78 ??
+ * 2F980 CJK COMPATIBILITY IDEOGRAPH-2F980
+ * 	2335F ??
+ * 2F981 CJK COMPATIBILITY IDEOGRAPH-2F981
+ * 	43D5 ??
+ * 2F982 CJK COMPATIBILITY IDEOGRAPH-2F982
+ * 	80B2 ??
+ * 2F983 CJK COMPATIBILITY IDEOGRAPH-2F983
+ * 	8103 ??
+ * 2F984 CJK COMPATIBILITY IDEOGRAPH-2F984
+ * 	440B ??
+ * 2F985 CJK COMPATIBILITY IDEOGRAPH-2F985
+ * 	813E ??
+ * 2F986 CJK COMPATIBILITY IDEOGRAPH-2F986
+ * 	5AB5 ??
+ * 2F987 CJK COMPATIBILITY IDEOGRAPH-2F987
+ * 	267A7 ??
+ * 2F988 CJK COMPATIBILITY IDEOGRAPH-2F988
+ * 	267B5 ??
+ * 2F989 CJK COMPATIBILITY IDEOGRAPH-2F989
+ * 	23393 ??
+ * 2F98A CJK COMPATIBILITY IDEOGRAPH-2F98A
+ * 	2339C ??
+ * 2F98B CJK COMPATIBILITY IDEOGRAPH-2F98B
+ * 	8201 ??
+ * 2F98C CJK COMPATIBILITY IDEOGRAPH-2F98C
+ * 	8204 ??
+ * 2F98D CJK COMPATIBILITY IDEOGRAPH-2F98D
+ * 	8F9E ??
+ * 2F98E CJK COMPATIBILITY IDEOGRAPH-2F98E
+ * 	446B ??
+ * 2F98F CJK COMPATIBILITY IDEOGRAPH-2F98F
+ * 	8291 ??
+ * 2F99 KANGXI RADICAL SHELL
+ * 	8C9D ??
+ * 2F990 CJK COMPATIBILITY IDEOGRAPH-2F990
+ * 	828B ??
+ * 2F991 CJK COMPATIBILITY IDEOGRAPH-2F991
+ * 	829D ??
+ * 2F992 CJK COMPATIBILITY IDEOGRAPH-2F992
+ * 	52B3 ??
+ * 2F993 CJK COMPATIBILITY IDEOGRAPH-2F993
+ * 	82B1 ??
+ * 2F994 CJK COMPATIBILITY IDEOGRAPH-2F994
+ * 	82B3 ??
+ * 2F995 CJK COMPATIBILITY IDEOGRAPH-2F995
+ * 	82BD ??
+ * 2F996 CJK COMPATIBILITY IDEOGRAPH-2F996
+ * 	82E6 ??
+ * 2F997 CJK COMPATIBILITY IDEOGRAPH-2F997
+ * 	26B3C ??
+ * 2F998 CJK COMPATIBILITY IDEOGRAPH-2F998
+ * 	82E5 ??
+ * 2F999 CJK COMPATIBILITY IDEOGRAPH-2F999
+ * 	831D ??
+ * 2F99A CJK COMPATIBILITY IDEOGRAPH-2F99A
+ * 	8363 ??
+ * 2F99B CJK COMPATIBILITY IDEOGRAPH-2F99B
+ * 	83AD ??
+ * 2F99C CJK COMPATIBILITY IDEOGRAPH-2F99C
+ * 	8323 ??
+ * 2F99D CJK COMPATIBILITY IDEOGRAPH-2F99D
+ * 	83BD ??
+ * 2F99E CJK COMPATIBILITY IDEOGRAPH-2F99E
+ * 	83E7 ??
+ * 2F99F CJK COMPATIBILITY IDEOGRAPH-2F99F
+ * 	8457 ??
+ * 2F9A KANGXI RADICAL RED
+ * 	8D64 ??
+ * 2F9A0 CJK COMPATIBILITY IDEOGRAPH-2F9A0
+ * 	8353 ??
+ * 2F9A1 CJK COMPATIBILITY IDEOGRAPH-2F9A1
+ * 	83CA ??
+ * 2F9A2 CJK COMPATIBILITY IDEOGRAPH-2F9A2
+ * 	83CC ??
+ * 2F9A3 CJK COMPATIBILITY IDEOGRAPH-2F9A3
+ * 	83DC ??
+ * 2F9A4 CJK COMPATIBILITY IDEOGRAPH-2F9A4
+ * 	26C36 ??
+ * 2F9A5 CJK COMPATIBILITY IDEOGRAPH-2F9A5
+ * 	26D6B ??
+ * 2F9A6 CJK COMPATIBILITY IDEOGRAPH-2F9A6
+ * 	26CD5 ??
+ * 2F9A7 CJK COMPATIBILITY IDEOGRAPH-2F9A7
+ * 	452B ??
+ * 2F9A8 CJK COMPATIBILITY IDEOGRAPH-2F9A8
+ * 	84F1 ??
+ * 2F9A9 CJK COMPATIBILITY IDEOGRAPH-2F9A9
+ * 	84F3 ??
+ * 2F9AA CJK COMPATIBILITY IDEOGRAPH-2F9AA
+ * 	8516 ??
+ * 2F9AB CJK COMPATIBILITY IDEOGRAPH-2F9AB
+ * 	273CA ??
+ * 2F9AC CJK COMPATIBILITY IDEOGRAPH-2F9AC
+ * 	8564 ??
+ * 2F9AD CJK COMPATIBILITY IDEOGRAPH-2F9AD
+ * 	26F2C ??
+ * 2F9AE CJK COMPATIBILITY IDEOGRAPH-2F9AE
+ * 	455D ??
+ * 2F9AF CJK COMPATIBILITY IDEOGRAPH-2F9AF
+ * 	4561 ??
+ * 2F9B KANGXI RADICAL RUN
+ * 	8D70 ??
+ * 2F9B0 CJK COMPATIBILITY IDEOGRAPH-2F9B0
+ * 	26FB1 ??
+ * 2F9B1 CJK COMPATIBILITY IDEOGRAPH-2F9B1
+ * 	270D2 ??
+ * 2F9B2 CJK COMPATIBILITY IDEOGRAPH-2F9B2
+ * 	456B ??
+ * 2F9B3 CJK COMPATIBILITY IDEOGRAPH-2F9B3
+ * 	8650 ??
+ * 2F9B4 CJK COMPATIBILITY IDEOGRAPH-2F9B4
+ * 	865C ??
+ * 2F9B5 CJK COMPATIBILITY IDEOGRAPH-2F9B5
+ * 	8667 ??
+ * 2F9B6 CJK COMPATIBILITY IDEOGRAPH-2F9B6
+ * 	8669 ??
+ * 2F9B7 CJK COMPATIBILITY IDEOGRAPH-2F9B7
+ * 	86A9 ??
+ * 2F9B8 CJK COMPATIBILITY IDEOGRAPH-2F9B8
+ * 	8688 ??
+ * 2F9B9 CJK COMPATIBILITY IDEOGRAPH-2F9B9
+ * 	870E ??
+ * 2F9BA CJK COMPATIBILITY IDEOGRAPH-2F9BA
+ * 	86E2 ??
+ * 2F9BB CJK COMPATIBILITY IDEOGRAPH-2F9BB
+ * 	8779 ??
+ * 2F9BC CJK COMPATIBILITY IDEOGRAPH-2F9BC
+ * 	8728 ??
+ * 2F9BD CJK COMPATIBILITY IDEOGRAPH-2F9BD
+ * 	876B ??
+ * 2F9BE CJK COMPATIBILITY IDEOGRAPH-2F9BE
+ * 	8786 ??
+ * 2F9BF CJK COMPATIBILITY IDEOGRAPH-2F9BF
+ * 	4D57 ??
+ * 2F9C KANGXI RADICAL FOOT
+ * 	8DB3 ??
+ * 2F9C0 CJK COMPATIBILITY IDEOGRAPH-2F9C0
+ * 	87E1 ??
+ * 2F9C1 CJK COMPATIBILITY IDEOGRAPH-2F9C1
+ * 	8801 ??
+ * 2F9C2 CJK COMPATIBILITY IDEOGRAPH-2F9C2
+ * 	45F9 ??
+ * 2F9C3 CJK COMPATIBILITY IDEOGRAPH-2F9C3
+ * 	8860 ??
+ * 2F9C4 CJK COMPATIBILITY IDEOGRAPH-2F9C4
+ * 	8863 ??
+ * 2F9C5 CJK COMPATIBILITY IDEOGRAPH-2F9C5
+ * 	27667 ??
+ * 2F9C6 CJK COMPATIBILITY IDEOGRAPH-2F9C6
+ * 	88D7 ??
+ * 2F9C7 CJK COMPATIBILITY IDEOGRAPH-2F9C7
+ * 	88DE ??
+ * 2F9C8 CJK COMPATIBILITY IDEOGRAPH-2F9C8
+ * 	4635 ??
+ * 2F9C9 CJK COMPATIBILITY IDEOGRAPH-2F9C9
+ * 	88FA ??
+ * 2F9CA CJK COMPATIBILITY IDEOGRAPH-2F9CA
+ * 	34BB ??
+ * 2F9CB CJK COMPATIBILITY IDEOGRAPH-2F9CB
+ * 	278AE ??
+ * 2F9CC CJK COMPATIBILITY IDEOGRAPH-2F9CC
+ * 	27966 ??
+ * 2F9CD CJK COMPATIBILITY IDEOGRAPH-2F9CD
+ * 	46BE ??
+ * 2F9CE CJK COMPATIBILITY IDEOGRAPH-2F9CE
+ * 	46C7 ??
+ * 2F9CF CJK COMPATIBILITY IDEOGRAPH-2F9CF
+ * 	8AA0 ??
+ * 2F9D KANGXI RADICAL BODY
+ * 	8EAB ??
+ * 2F9D0 CJK COMPATIBILITY IDEOGRAPH-2F9D0
+ * 	8AED ??
+ * 2F9D1 CJK COMPATIBILITY IDEOGRAPH-2F9D1
+ * 	8B8A ??
+ * 2F9D2 CJK COMPATIBILITY IDEOGRAPH-2F9D2
+ * 	8C55 ??
+ * 2F9D3 CJK COMPATIBILITY IDEOGRAPH-2F9D3
+ * 	27CA8 ??
+ * 2F9D4 CJK COMPATIBILITY IDEOGRAPH-2F9D4
+ * 	8CAB ??
+ * 2F9D5 CJK COMPATIBILITY IDEOGRAPH-2F9D5
+ * 	8CC1 ??
+ * 2F9D6 CJK COMPATIBILITY IDEOGRAPH-2F9D6
+ * 	8D1B ??
+ * 2F9D7 CJK COMPATIBILITY IDEOGRAPH-2F9D7
+ * 	8D77 ??
+ * 2F9D8 CJK COMPATIBILITY IDEOGRAPH-2F9D8
+ * 	27F2F ??
+ * 2F9D9 CJK COMPATIBILITY IDEOGRAPH-2F9D9
+ * 	20804 ??
+ * 2F9DA CJK COMPATIBILITY IDEOGRAPH-2F9DA
+ * 	8DCB ??
+ * 2F9DB CJK COMPATIBILITY IDEOGRAPH-2F9DB
+ * 	8DBC ??
+ * 2F9DC CJK COMPATIBILITY IDEOGRAPH-2F9DC
+ * 	8DF0 ??
+ * 2F9DD CJK COMPATIBILITY IDEOGRAPH-2F9DD
+ * 	208DE ??
+ * 2F9DE CJK COMPATIBILITY IDEOGRAPH-2F9DE
+ * 	8ED4 ??
+ * 2F9DF CJK COMPATIBILITY IDEOGRAPH-2F9DF
+ * 	8F38 ??
+ * 2F9E KANGXI RADICAL CART
+ * 	8ECA ??
+ * 2F9E0 CJK COMPATIBILITY IDEOGRAPH-2F9E0
+ * 	285D2 ??
+ * 2F9E1 CJK COMPATIBILITY IDEOGRAPH-2F9E1
+ * 	285ED ??
+ * 2F9E2 CJK COMPATIBILITY IDEOGRAPH-2F9E2
+ * 	9094 ??
+ * 2F9E3 CJK COMPATIBILITY IDEOGRAPH-2F9E3
+ * 	90F1 ??
+ * 2F9E4 CJK COMPATIBILITY IDEOGRAPH-2F9E4
+ * 	9111 ??
+ * 2F9E5 CJK COMPATIBILITY IDEOGRAPH-2F9E5
+ * 	2872E ??
+ * 2F9E6 CJK COMPATIBILITY IDEOGRAPH-2F9E6
+ * 	911B ??
+ * 2F9E7 CJK COMPATIBILITY IDEOGRAPH-2F9E7
+ * 	9238 ??
+ * 2F9E8 CJK COMPATIBILITY IDEOGRAPH-2F9E8
+ * 	92D7 ??
+ * 2F9E9 CJK COMPATIBILITY IDEOGRAPH-2F9E9
+ * 	92D8 ??
+ * 2F9EA CJK COMPATIBILITY IDEOGRAPH-2F9EA
+ * 	927C ??
+ * 2F9EB CJK COMPATIBILITY IDEOGRAPH-2F9EB
+ * 	93F9 ??
+ * 2F9EC CJK COMPATIBILITY IDEOGRAPH-2F9EC
+ * 	9415 ??
+ * 2F9ED CJK COMPATIBILITY IDEOGRAPH-2F9ED
+ * 	28BFA ??
+ * 2F9EE CJK COMPATIBILITY IDEOGRAPH-2F9EE
+ * 	958B ??
+ * 2F9EF CJK COMPATIBILITY IDEOGRAPH-2F9EF
+ * 	4995 ??
+ * 2F9F KANGXI RADICAL BITTER
+ * 	8F9B ??
+ * 2F9F0 CJK COMPATIBILITY IDEOGRAPH-2F9F0
+ * 	95B7 ??
+ * 2F9F1 CJK COMPATIBILITY IDEOGRAPH-2F9F1
+ * 	28D77 ??
+ * 2F9F2 CJK COMPATIBILITY IDEOGRAPH-2F9F2
+ * 	49E6 ??
+ * 2F9F3 CJK COMPATIBILITY IDEOGRAPH-2F9F3
+ * 	96C3 ??
+ * 2F9F4 CJK COMPATIBILITY IDEOGRAPH-2F9F4
+ * 	5DB2 ??
+ * 2F9F5 CJK COMPATIBILITY IDEOGRAPH-2F9F5
+ * 	9723 ??
+ * 2F9F6 CJK COMPATIBILITY IDEOGRAPH-2F9F6
+ * 	29145 ??
+ * 2F9F7 CJK COMPATIBILITY IDEOGRAPH-2F9F7
+ * 	2921A ??
+ * 2F9F8 CJK COMPATIBILITY IDEOGRAPH-2F9F8
+ * 	4A6E ??
+ * 2F9F9 CJK COMPATIBILITY IDEOGRAPH-2F9F9
+ * 	4A76 ??
+ * 2F9FA CJK COMPATIBILITY IDEOGRAPH-2F9FA
+ * 	97E0 ??
+ * 2F9FB CJK COMPATIBILITY IDEOGRAPH-2F9FB
+ * 	2940A ??
+ * 2F9FC CJK COMPATIBILITY IDEOGRAPH-2F9FC
+ * 	4AB2 ??
+ * 2F9FD CJK COMPATIBILITY IDEOGRAPH-2F9FD
+ * 	29496 ??
+ * 2F9FE CJK COMPATIBILITY IDEOGRAPH-2F9FE
+ * 	980B ??
+ * 2F9FF CJK COMPATIBILITY IDEOGRAPH-2F9FF
+ * 	980B ??
+ * 2FA0 KANGXI RADICAL MORNING
+ * 	8FB0 ??
+ * 2FA00 CJK COMPATIBILITY IDEOGRAPH-2FA00
+ * 	9829 ??
+ * 2FA01 CJK COMPATIBILITY IDEOGRAPH-2FA01
+ * 	295B6 ??
+ * 2FA02 CJK COMPATIBILITY IDEOGRAPH-2FA02
+ * 	98E2 ??
+ * 2FA03 CJK COMPATIBILITY IDEOGRAPH-2FA03
+ * 	4B33 ??
+ * 2FA04 CJK COMPATIBILITY IDEOGRAPH-2FA04
+ * 	9929 ??
+ * 2FA05 CJK COMPATIBILITY IDEOGRAPH-2FA05
+ * 	99A7 ??
+ * 2FA06 CJK COMPATIBILITY IDEOGRAPH-2FA06
+ * 	99C2 ??
+ * 2FA07 CJK COMPATIBILITY IDEOGRAPH-2FA07
+ * 	99FE ??
+ * 2FA08 CJK COMPATIBILITY IDEOGRAPH-2FA08
+ * 	4BCE ??
+ * 2FA09 CJK COMPATIBILITY IDEOGRAPH-2FA09
+ * 	29B30 ??
+ * 2FA0A CJK COMPATIBILITY IDEOGRAPH-2FA0A
+ * 	9B12 ??
+ * 2FA0B CJK COMPATIBILITY IDEOGRAPH-2FA0B
+ * 	9C40 ??
+ * 2FA0C CJK COMPATIBILITY IDEOGRAPH-2FA0C
+ * 	9CFD ??
+ * 2FA0D CJK COMPATIBILITY IDEOGRAPH-2FA0D
+ * 	4CCE ??
+ * 2FA0E CJK COMPATIBILITY IDEOGRAPH-2FA0E
+ * 	4CED ??
+ * 2FA0F CJK COMPATIBILITY IDEOGRAPH-2FA0F
+ * 	9D67 ??
+ * 2FA1 KANGXI RADICAL WALK
+ * 	8FB5 ??
+ * 2FA10 CJK COMPATIBILITY IDEOGRAPH-2FA10
+ * 	2A0CE ??
+ * 2FA11 CJK COMPATIBILITY IDEOGRAPH-2FA11
+ * 	4CF8 ??
+ * 2FA12 CJK COMPATIBILITY IDEOGRAPH-2FA12
+ * 	2A105 ??
+ * 2FA13 CJK COMPATIBILITY IDEOGRAPH-2FA13
+ * 	2A20E ??
+ * 2FA14 CJK COMPATIBILITY IDEOGRAPH-2FA14
+ * 	2A291 ??
+ * 2FA15 CJK COMPATIBILITY IDEOGRAPH-2FA15
+ * 	9EBB ??
+ * 2FA16 CJK COMPATIBILITY IDEOGRAPH-2FA16
+ * 	4D56 ??
+ * 2FA17 CJK COMPATIBILITY IDEOGRAPH-2FA17
+ * 	9EF9 ??
+ * 2FA18 CJK COMPATIBILITY IDEOGRAPH-2FA18
+ * 	9EFE ??
+ * 2FA19 CJK COMPATIBILITY IDEOGRAPH-2FA19
+ * 	9F05 ??
+ * 2FA1A CJK COMPATIBILITY IDEOGRAPH-2FA1A
+ * 	9F0F ??
+ * 2FA1B CJK COMPATIBILITY IDEOGRAPH-2FA1B
+ * 	9F16 ??
+ * 2FA1C CJK COMPATIBILITY IDEOGRAPH-2FA1C
+ * 	9F3B ??
+ * 2FA1D CJK COMPATIBILITY IDEOGRAPH-2FA1D
+ * 	2A600 ??
+ * 2FA2 KANGXI RADICAL CITY
+ * 	9091 ??
+ * 2FA3 KANGXI RADICAL WINE
+ * 	9149 ??
+ * 2FA4 KANGXI RADICAL DISTINGUISH
+ * 	91C6 ??
+ * 2FA5 KANGXI RADICAL VILLAGE
+ * 	91CC ??
+ * 2FA6 KANGXI RADICAL GOLD
+ * 	91D1 ??
+ * 2FA7 KANGXI RADICAL LONG
+ * 	9577 ??
+ * 2FA8 KANGXI RADICAL GATE
+ * 	9580 ??
+ * 2FA9 KANGXI RADICAL MOUND
+ * 	961C ??
+ * 2FAA KANGXI RADICAL SLAVE
+ * 	96B6 ??
+ * 2FAB KANGXI RADICAL SHORT TAILED BIRD
+ * 	96B9 ??
+ * 2FAC KANGXI RADICAL RAIN
+ * 	96E8 ??
+ * 2FAD KANGXI RADICAL BLUE
+ * 	9751 ??
+ * 2FAE KANGXI RADICAL WRONG
+ * 	975E ??
+ * 2FAF KANGXI RADICAL FACE
+ * 	9762 ??
+ * 2FB0 KANGXI RADICAL LEATHER
+ * 	9769 ??
+ * 2FB1 KANGXI RADICAL TANNED LEATHER
+ * 	97CB ??
+ * 2FB2 KANGXI RADICAL LEEK
+ * 	97ED ??
+ * 2FB3 KANGXI RADICAL SOUND
+ * 	97F3 ??
+ * 2FB4 KANGXI RADICAL LEAF
+ * 	9801 ??
+ * 2FB5 KANGXI RADICAL WIND
+ * 	98A8 ??
+ * 2FB6 KANGXI RADICAL FLY
+ * 	98DB ??
+ * 2FB7 KANGXI RADICAL EAT
+ * 	98DF ??
+ * 2FB8 KANGXI RADICAL HEAD
+ * 	9996 ??
+ * 2FB9 KANGXI RADICAL FRAGRANT
+ * 	9999 ??
+ * 2FBA KANGXI RADICAL HORSE
+ * 	99AC ??
+ * 2FBB KANGXI RADICAL BONE
+ * 	9AA8 ??
+ * 2FBC KANGXI RADICAL TALL
+ * 	9AD8 ??
+ * 2FBD KANGXI RADICAL HAIR
+ * 	9ADF ??
+ * 2FBE KANGXI RADICAL FIGHT
+ * 	9B25 ??
+ * 2FBF KANGXI RADICAL SACRIFICIAL WINE
+ * 	9B2F ??
+ * 2FC0 KANGXI RADICAL CAULDRON
+ * 	9B32 ??
+ * 2FC1 KANGXI RADICAL GHOST
+ * 	9B3C ??
+ * 2FC2 KANGXI RADICAL FISH
+ * 	9B5A ??
+ * 2FC3 KANGXI RADICAL BIRD
+ * 	9CE5 ??
+ * 2FC4 KANGXI RADICAL SALT
+ * 	9E75 ??
+ * 2FC5 KANGXI RADICAL DEER
+ * 	9E7F ??
+ * 2FC6 KANGXI RADICAL WHEAT
+ * 	9EA5 ??
+ * 2FC7 KANGXI RADICAL HEMP
+ * 	9EBB ??
+ * 2FC8 KANGXI RADICAL YELLOW
+ * 	9EC3 ??
+ * 2FC9 KANGXI RADICAL MILLET
+ * 	9ECD ??
+ * 2FCA KANGXI RADICAL BLACK
+ * 	9ED1 ??
+ * 2FCB KANGXI RADICAL EMBROIDERY
+ * 	9EF9 ??
+ * 2FCC KANGXI RADICAL FROG
+ * 	9EFD ??
+ * 2FCD KANGXI RADICAL TRIPOD
+ * 	9F0E ??
+ * 2FCE KANGXI RADICAL DRUM
+ * 	9F13 ??
+ * 2FCF KANGXI RADICAL RAT
+ * 	9F20 ??
+ * 2FD0 KANGXI RADICAL NOSE
+ * 	9F3B ??
+ * 2FD1 KANGXI RADICAL EVEN
+ * 	9F4A ??
+ * 2FD2 KANGXI RADICAL TOOTH
+ * 	9F52 ??
+ * 2FD3 KANGXI RADICAL DRAGON
+ * 	9F8D ??
+ * 2FD4 KANGXI RADICAL TURTLE
+ * 	9F9C ??
+ * 2FD5 KANGXI RADICAL FLUTE
+ * 	9FA0 ??
+ * 3000 IDEOGRAPHIC SPACE
+ * 	0020 SPACE
+ * 3036 CIRCLED POSTAL MARK
+ * 	3012 POSTAL MARK
+ * 3038 HANGZHOU NUMERAL TEN
+ * 	5341 ??
+ * 3039 HANGZHOU NUMERAL TWENTY
+ * 	5344 ??
+ * 303A HANGZHOU NUMERAL THIRTY
+ * 	5345 ??
+ * 304C HIRAGANA LETTER GA
+ * 	304B HIRAGANA LETTER KA
+ * 304E HIRAGANA LETTER GI
+ * 	304D HIRAGANA LETTER KI
+ * 3050 HIRAGANA LETTER GU
+ * 	304F HIRAGANA LETTER KU
+ * 3052 HIRAGANA LETTER GE
+ * 	3051 HIRAGANA LETTER KE
+ * 3054 HIRAGANA LETTER GO
+ * 	3053 HIRAGANA LETTER KO
+ * 3056 HIRAGANA LETTER ZA
+ * 	3055 HIRAGANA LETTER SA
+ * 3058 HIRAGANA LETTER ZI
+ * 	3057 HIRAGANA LETTER SI
+ * 305A HIRAGANA LETTER ZU
+ * 	3059 HIRAGANA LETTER SU
+ * 305C HIRAGANA LETTER ZE
+ * 	305B HIRAGANA LETTER SE
+ * 305E HIRAGANA LETTER ZO
+ * 	305D HIRAGANA LETTER SO
+ * 3060 HIRAGANA LETTER DA
+ * 	305F HIRAGANA LETTER TA
+ * 3062 HIRAGANA LETTER DI
+ * 	3061 HIRAGANA LETTER TI
+ * 3065 HIRAGANA LETTER DU
+ * 	3064 HIRAGANA LETTER TU
+ * 3067 HIRAGANA LETTER DE
+ * 	3066 HIRAGANA LETTER TE
+ * 3069 HIRAGANA LETTER DO
+ * 	3068 HIRAGANA LETTER TO
+ * 3070 HIRAGANA LETTER BA
+ * 	306F HIRAGANA LETTER HA
+ * 3071 HIRAGANA LETTER PA
+ * 	306F HIRAGANA LETTER HA
+ * 3073 HIRAGANA LETTER BI
+ * 	3072 HIRAGANA LETTER HI
+ * 3074 HIRAGANA LETTER PI
+ * 	3072 HIRAGANA LETTER HI
+ * 3076 HIRAGANA LETTER BU
+ * 	3075 HIRAGANA LETTER HU
+ * 3077 HIRAGANA LETTER PU
+ * 	3075 HIRAGANA LETTER HU
+ * 3079 HIRAGANA LETTER BE
+ * 	3078 HIRAGANA LETTER HE
+ * 307A HIRAGANA LETTER PE
+ * 	3078 HIRAGANA LETTER HE
+ * 307C HIRAGANA LETTER BO
+ * 	307B HIRAGANA LETTER HO
+ * 307D HIRAGANA LETTER PO
+ * 	307B HIRAGANA LETTER HO
+ * 3094 HIRAGANA LETTER VU
+ * 	3046 HIRAGANA LETTER U
+ * 309B KATAKANA-HIRAGANA VOICED SOUND MARK
+ * 	0020 SPACE
+ * 309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+ * 	0020 SPACE
+ * 309E HIRAGANA VOICED ITERATION MARK
+ * 	309D HIRAGANA ITERATION MARK
+ * 309F HIRAGANA DIGRAPH YORI
+ * 	3088 HIRAGANA LETTER YO
+ * 	308A HIRAGANA LETTER RI
+ * 30AC KATAKANA LETTER GA
+ * 	30AB KATAKANA LETTER KA
+ * 30AE KATAKANA LETTER GI
+ * 	30AD KATAKANA LETTER KI
+ * 30B0 KATAKANA LETTER GU
+ * 	30AF KATAKANA LETTER KU
+ * 30B2 KATAKANA LETTER GE
+ * 	30B1 KATAKANA LETTER KE
+ * 30B4 KATAKANA LETTER GO
+ * 	30B3 KATAKANA LETTER KO
+ * 30B6 KATAKANA LETTER ZA
+ * 	30B5 KATAKANA LETTER SA
+ * 30B8 KATAKANA LETTER ZI
+ * 	30B7 KATAKANA LETTER SI
+ * 30BA KATAKANA LETTER ZU
+ * 	30B9 KATAKANA LETTER SU
+ * 30BC KATAKANA LETTER ZE
+ * 	30BB KATAKANA LETTER SE
+ * 30BE KATAKANA LETTER ZO
+ * 	30BD KATAKANA LETTER SO
+ * 30C0 KATAKANA LETTER DA
+ * 	30BF KATAKANA LETTER TA
+ * 30C2 KATAKANA LETTER DI
+ * 	30C1 KATAKANA LETTER TI
+ * 30C5 KATAKANA LETTER DU
+ * 	30C4 KATAKANA LETTER TU
+ * 30C7 KATAKANA LETTER DE
+ * 	30C6 KATAKANA LETTER TE
+ * 30C9 KATAKANA LETTER DO
+ * 	30C8 KATAKANA LETTER TO
+ * 30D0 KATAKANA LETTER BA
+ * 	30CF KATAKANA LETTER HA
+ * 30D1 KATAKANA LETTER PA
+ * 	30CF KATAKANA LETTER HA
+ * 30D3 KATAKANA LETTER BI
+ * 	30D2 KATAKANA LETTER HI
+ * 30D4 KATAKANA LETTER PI
+ * 	30D2 KATAKANA LETTER HI
+ * 30D6 KATAKANA LETTER BU
+ * 	30D5 KATAKANA LETTER HU
+ * 30D7 KATAKANA LETTER PU
+ * 	30D5 KATAKANA LETTER HU
+ * 30D9 KATAKANA LETTER BE
+ * 	30D8 KATAKANA LETTER HE
+ * 30DA KATAKANA LETTER PE
+ * 	30D8 KATAKANA LETTER HE
+ * 30DC KATAKANA LETTER BO
+ * 	30DB KATAKANA LETTER HO
+ * 30DD KATAKANA LETTER PO
+ * 	30DB KATAKANA LETTER HO
+ * 30F4 KATAKANA LETTER VU
+ * 	30A6 KATAKANA LETTER U
+ * 30F7 KATAKANA LETTER VA
+ * 	30EF KATAKANA LETTER WA
+ * 30F8 KATAKANA LETTER VI
+ * 	30F0 KATAKANA LETTER WI
+ * 30F9 KATAKANA LETTER VE
+ * 	30F1 KATAKANA LETTER WE
+ * 30FA KATAKANA LETTER VO
+ * 	30F2 KATAKANA LETTER WO
+ * 30FE KATAKANA VOICED ITERATION MARK
+ * 	30FD KATAKANA ITERATION MARK
+ * 30FF KATAKANA DIGRAPH KOTO
+ * 	30B3 KATAKANA LETTER KO
+ * 	30C8 KATAKANA LETTER TO
+ * 3131 HANGUL LETTER KIYEOK
+ * 	1100 HANGUL CHOSEONG KIYEOK
+ * 3132 HANGUL LETTER SSANGKIYEOK
+ * 	1101 HANGUL CHOSEONG SSANGKIYEOK
+ * 3133 HANGUL LETTER KIYEOK-SIOS
+ * 	11AA HANGUL JONGSEONG KIYEOK-SIOS
+ * 3134 HANGUL LETTER NIEUN
+ * 	1102 HANGUL CHOSEONG NIEUN
+ * 3135 HANGUL LETTER NIEUN-CIEUC
+ * 	11AC HANGUL JONGSEONG NIEUN-CIEUC
+ * 3136 HANGUL LETTER NIEUN-HIEUH
+ * 	11AD HANGUL JONGSEONG NIEUN-HIEUH
+ * 3137 HANGUL LETTER TIKEUT
+ * 	1103 HANGUL CHOSEONG TIKEUT
+ * 3138 HANGUL LETTER SSANGTIKEUT
+ * 	1104 HANGUL CHOSEONG SSANGTIKEUT
+ * 3139 HANGUL LETTER RIEUL
+ * 	1105 HANGUL CHOSEONG RIEUL
+ * 313A HANGUL LETTER RIEUL-KIYEOK
+ * 	11B0 HANGUL JONGSEONG RIEUL-KIYEOK
+ * 313B HANGUL LETTER RIEUL-MIEUM
+ * 	11B1 HANGUL JONGSEONG RIEUL-MIEUM
+ * 313C HANGUL LETTER RIEUL-PIEUP
+ * 	11B2 HANGUL JONGSEONG RIEUL-PIEUP
+ * 313D HANGUL LETTER RIEUL-SIOS
+ * 	11B3 HANGUL JONGSEONG RIEUL-SIOS
+ * 313E HANGUL LETTER RIEUL-THIEUTH
+ * 	11B4 HANGUL JONGSEONG RIEUL-THIEUTH
+ * 313F HANGUL LETTER RIEUL-PHIEUPH
+ * 	11B5 HANGUL JONGSEONG RIEUL-PHIEUPH
+ * 3140 HANGUL LETTER RIEUL-HIEUH
+ * 	111A HANGUL CHOSEONG RIEUL-HIEUH
+ * 3141 HANGUL LETTER MIEUM
+ * 	1106 HANGUL CHOSEONG MIEUM
+ * 3142 HANGUL LETTER PIEUP
+ * 	1107 HANGUL CHOSEONG PIEUP
+ * 3143 HANGUL LETTER SSANGPIEUP
+ * 	1108 HANGUL CHOSEONG SSANGPIEUP
+ * 3144 HANGUL LETTER PIEUP-SIOS
+ * 	1121 HANGUL CHOSEONG PIEUP-SIOS
+ * 3145 HANGUL LETTER SIOS
+ * 	1109 HANGUL CHOSEONG SIOS
+ * 3146 HANGUL LETTER SSANGSIOS
+ * 	110A HANGUL CHOSEONG SSANGSIOS
+ * 3147 HANGUL LETTER IEUNG
+ * 	110B HANGUL CHOSEONG IEUNG
+ * 3148 HANGUL LETTER CIEUC
+ * 	110C HANGUL CHOSEONG CIEUC
+ * 3149 HANGUL LETTER SSANGCIEUC
+ * 	110D HANGUL CHOSEONG SSANGCIEUC
+ * 314A HANGUL LETTER CHIEUCH
+ * 	110E HANGUL CHOSEONG CHIEUCH
+ * 314B HANGUL LETTER KHIEUKH
+ * 	110F HANGUL CHOSEONG KHIEUKH
+ * 314C HANGUL LETTER THIEUTH
+ * 	1110 HANGUL CHOSEONG THIEUTH
+ * 314D HANGUL LETTER PHIEUPH
+ * 	1111 HANGUL CHOSEONG PHIEUPH
+ * 314E HANGUL LETTER HIEUH
+ * 	1112 HANGUL CHOSEONG HIEUH
+ * 314F HANGUL LETTER A
+ * 	1161 HANGUL JUNGSEONG A
+ * 3150 HANGUL LETTER AE
+ * 	1162 HANGUL JUNGSEONG AE
+ * 3151 HANGUL LETTER YA
+ * 	1163 HANGUL JUNGSEONG YA
+ * 3152 HANGUL LETTER YAE
+ * 	1164 HANGUL JUNGSEONG YAE
+ * 3153 HANGUL LETTER EO
+ * 	1165 HANGUL JUNGSEONG EO
+ * 3154 HANGUL LETTER E
+ * 	1166 HANGUL JUNGSEONG E
+ * 3155 HANGUL LETTER YEO
+ * 	1167 HANGUL JUNGSEONG YEO
+ * 3156 HANGUL LETTER YE
+ * 	1168 HANGUL JUNGSEONG YE
+ * 3157 HANGUL LETTER O
+ * 	1169 HANGUL JUNGSEONG O
+ * 3158 HANGUL LETTER WA
+ * 	116A HANGUL JUNGSEONG WA
+ * 3159 HANGUL LETTER WAE
+ * 	116B HANGUL JUNGSEONG WAE
+ * 315A HANGUL LETTER OE
+ * 	116C HANGUL JUNGSEONG OE
+ * 315B HANGUL LETTER YO
+ * 	116D HANGUL JUNGSEONG YO
+ * 315C HANGUL LETTER U
+ * 	116E HANGUL JUNGSEONG U
+ * 315D HANGUL LETTER WEO
+ * 	116F HANGUL JUNGSEONG WEO
+ * 315E HANGUL LETTER WE
+ * 	1170 HANGUL JUNGSEONG WE
+ * 315F HANGUL LETTER WI
+ * 	1171 HANGUL JUNGSEONG WI
+ * 3160 HANGUL LETTER YU
+ * 	1172 HANGUL JUNGSEONG YU
+ * 3161 HANGUL LETTER EU
+ * 	1173 HANGUL JUNGSEONG EU
+ * 3162 HANGUL LETTER YI
+ * 	1174 HANGUL JUNGSEONG YI
+ * 3163 HANGUL LETTER I
+ * 	1175 HANGUL JUNGSEONG I
+ * 3164 HANGUL FILLER
+ * 	1160 HANGUL JUNGSEONG FILLER
+ * 3165 HANGUL LETTER SSANGNIEUN
+ * 	1114 HANGUL CHOSEONG SSANGNIEUN
+ * 3166 HANGUL LETTER NIEUN-TIKEUT
+ * 	1115 HANGUL CHOSEONG NIEUN-TIKEUT
+ * 3167 HANGUL LETTER NIEUN-SIOS
+ * 	11C7 HANGUL JONGSEONG NIEUN-SIOS
+ * 3168 HANGUL LETTER NIEUN-PANSIOS
+ * 	11C8 HANGUL JONGSEONG NIEUN-PANSIOS
+ * 3169 HANGUL LETTER RIEUL-KIYEOK-SIOS
+ * 	11CC HANGUL JONGSEONG RIEUL-KIYEOK-SIOS
+ * 316A HANGUL LETTER RIEUL-TIKEUT
+ * 	11CE HANGUL JONGSEONG RIEUL-TIKEUT
+ * 316B HANGUL LETTER RIEUL-PIEUP-SIOS
+ * 	11D3 HANGUL JONGSEONG RIEUL-PIEUP-SIOS
+ * 316C HANGUL LETTER RIEUL-PANSIOS
+ * 	11D7 HANGUL JONGSEONG RIEUL-PANSIOS
+ * 316D HANGUL LETTER RIEUL-YEORINHIEUH
+ * 	11D9 HANGUL JONGSEONG RIEUL-YEORINHIEUH
+ * 316E HANGUL LETTER MIEUM-PIEUP
+ * 	111C HANGUL CHOSEONG MIEUM-PIEUP
+ * 316F HANGUL LETTER MIEUM-SIOS
+ * 	11DD HANGUL JONGSEONG MIEUM-SIOS
+ * 3170 HANGUL LETTER MIEUM-PANSIOS
+ * 	11DF HANGUL JONGSEONG MIEUM-PANSIOS
+ * 3171 HANGUL LETTER KAPYEOUNMIEUM
+ * 	111D HANGUL CHOSEONG KAPYEOUNMIEUM
+ * 3172 HANGUL LETTER PIEUP-KIYEOK
+ * 	111E HANGUL CHOSEONG PIEUP-KIYEOK
+ * 3173 HANGUL LETTER PIEUP-TIKEUT
+ * 	1120 HANGUL CHOSEONG PIEUP-TIKEUT
+ * 3174 HANGUL LETTER PIEUP-SIOS-KIYEOK
+ * 	1122 HANGUL CHOSEONG PIEUP-SIOS-KIYEOK
+ * 3175 HANGUL LETTER PIEUP-SIOS-TIKEUT
+ * 	1123 HANGUL CHOSEONG PIEUP-SIOS-TIKEUT
+ * 3176 HANGUL LETTER PIEUP-CIEUC
+ * 	1127 HANGUL CHOSEONG PIEUP-CIEUC
+ * 3177 HANGUL LETTER PIEUP-THIEUTH
+ * 	1129 HANGUL CHOSEONG PIEUP-THIEUTH
+ * 3178 HANGUL LETTER KAPYEOUNPIEUP
+ * 	112B HANGUL CHOSEONG KAPYEOUNPIEUP
+ * 3179 HANGUL LETTER KAPYEOUNSSANGPIEUP
+ * 	112C HANGUL CHOSEONG KAPYEOUNSSANGPIEUP
+ * 317A HANGUL LETTER SIOS-KIYEOK
+ * 	112D HANGUL CHOSEONG SIOS-KIYEOK
+ * 317B HANGUL LETTER SIOS-NIEUN
+ * 	112E HANGUL CHOSEONG SIOS-NIEUN
+ * 317C HANGUL LETTER SIOS-TIKEUT
+ * 	112F HANGUL CHOSEONG SIOS-TIKEUT
+ * 317D HANGUL LETTER SIOS-PIEUP
+ * 	1132 HANGUL CHOSEONG SIOS-PIEUP
+ * 317E HANGUL LETTER SIOS-CIEUC
+ * 	1136 HANGUL CHOSEONG SIOS-CIEUC
+ * 317F HANGUL LETTER PANSIOS
+ * 	1140 HANGUL CHOSEONG PANSIOS
+ * 3180 HANGUL LETTER SSANGIEUNG
+ * 	1147 HANGUL CHOSEONG SSANGIEUNG
+ * 3181 HANGUL LETTER YESIEUNG
+ * 	114C HANGUL CHOSEONG YESIEUNG
+ * 3182 HANGUL LETTER YESIEUNG-SIOS
+ * 	11F1 HANGUL JONGSEONG YESIEUNG-SIOS
+ * 3183 HANGUL LETTER YESIEUNG-PANSIOS
+ * 	11F2 HANGUL JONGSEONG YESIEUNG-PANSIOS
+ * 3184 HANGUL LETTER KAPYEOUNPHIEUPH
+ * 	1157 HANGUL CHOSEONG KAPYEOUNPHIEUPH
+ * 3185 HANGUL LETTER SSANGHIEUH
+ * 	1158 HANGUL CHOSEONG SSANGHIEUH
+ * 3186 HANGUL LETTER YEORINHIEUH
+ * 	1159 HANGUL CHOSEONG YEORINHIEUH
+ * 3187 HANGUL LETTER YO-YA
+ * 	1184 HANGUL JUNGSEONG YO-YA
+ * 3188 HANGUL LETTER YO-YAE
+ * 	1185 HANGUL JUNGSEONG YO-YAE
+ * 3189 HANGUL LETTER YO-I
+ * 	1188 HANGUL JUNGSEONG YO-I
+ * 318A HANGUL LETTER YU-YEO
+ * 	1191 HANGUL JUNGSEONG YU-YEO
+ * 318B HANGUL LETTER YU-YE
+ * 	1192 HANGUL JUNGSEONG YU-YE
+ * 318C HANGUL LETTER YU-I
+ * 	1194 HANGUL JUNGSEONG YU-I
+ * 318D HANGUL LETTER ARAEA
+ * 	119E HANGUL JUNGSEONG ARAEA
+ * 318E HANGUL LETTER ARAEAE
+ * 	11A1 HANGUL JUNGSEONG ARAEA-I
+ * 3192 IDEOGRAPHIC ANNOTATION ONE MARK
+ * 	4E00 <CJK Ideograph, First>
+ * 3193 IDEOGRAPHIC ANNOTATION TWO MARK
+ * 	4E8C ??
+ * 3194 IDEOGRAPHIC ANNOTATION THREE MARK
+ * 	4E09 ??
+ * 3195 IDEOGRAPHIC ANNOTATION FOUR MARK
+ * 	56DB ??
+ * 3196 IDEOGRAPHIC ANNOTATION TOP MARK
+ * 	4E0A ??
+ * 3197 IDEOGRAPHIC ANNOTATION MIDDLE MARK
+ * 	4E2D ??
+ * 3198 IDEOGRAPHIC ANNOTATION BOTTOM MARK
+ * 	4E0B ??
+ * 3199 IDEOGRAPHIC ANNOTATION FIRST MARK
+ * 	7532 ??
+ * 319A IDEOGRAPHIC ANNOTATION SECOND MARK
+ * 	4E59 ??
+ * 319B IDEOGRAPHIC ANNOTATION THIRD MARK
+ * 	4E19 ??
+ * 319C IDEOGRAPHIC ANNOTATION FOURTH MARK
+ * 	4E01 ??
+ * 319D IDEOGRAPHIC ANNOTATION HEAVEN MARK
+ * 	5929 ??
+ * 319E IDEOGRAPHIC ANNOTATION EARTH MARK
+ * 	5730 ??
+ * 319F IDEOGRAPHIC ANNOTATION MAN MARK
+ * 	4EBA ??
+ * 3200 PARENTHESIZED HANGUL KIYEOK
+ * 	0028 LEFT PARENTHESIS
+ * 	1100 HANGUL CHOSEONG KIYEOK
+ * 	0029 RIGHT PARENTHESIS
+ * 3201 PARENTHESIZED HANGUL NIEUN
+ * 	0028 LEFT PARENTHESIS
+ * 	1102 HANGUL CHOSEONG NIEUN
+ * 	0029 RIGHT PARENTHESIS
+ * 3202 PARENTHESIZED HANGUL TIKEUT
+ * 	0028 LEFT PARENTHESIS
+ * 	1103 HANGUL CHOSEONG TIKEUT
+ * 	0029 RIGHT PARENTHESIS
+ * 3203 PARENTHESIZED HANGUL RIEUL
+ * 	0028 LEFT PARENTHESIS
+ * 	1105 HANGUL CHOSEONG RIEUL
+ * 	0029 RIGHT PARENTHESIS
+ * 3204 PARENTHESIZED HANGUL MIEUM
+ * 	0028 LEFT PARENTHESIS
+ * 	1106 HANGUL CHOSEONG MIEUM
+ * 	0029 RIGHT PARENTHESIS
+ * 3205 PARENTHESIZED HANGUL PIEUP
+ * 	0028 LEFT PARENTHESIS
+ * 	1107 HANGUL CHOSEONG PIEUP
+ * 	0029 RIGHT PARENTHESIS
+ * 3206 PARENTHESIZED HANGUL SIOS
+ * 	0028 LEFT PARENTHESIS
+ * 	1109 HANGUL CHOSEONG SIOS
+ * 	0029 RIGHT PARENTHESIS
+ * 3207 PARENTHESIZED HANGUL IEUNG
+ * 	0028 LEFT PARENTHESIS
+ * 	110B HANGUL CHOSEONG IEUNG
+ * 	0029 RIGHT PARENTHESIS
+ * 3208 PARENTHESIZED HANGUL CIEUC
+ * 	0028 LEFT PARENTHESIS
+ * 	110C HANGUL CHOSEONG CIEUC
+ * 	0029 RIGHT PARENTHESIS
+ * 3209 PARENTHESIZED HANGUL CHIEUCH
+ * 	0028 LEFT PARENTHESIS
+ * 	110E HANGUL CHOSEONG CHIEUCH
+ * 	0029 RIGHT PARENTHESIS
+ * 320A PARENTHESIZED HANGUL KHIEUKH
+ * 	0028 LEFT PARENTHESIS
+ * 	110F HANGUL CHOSEONG KHIEUKH
+ * 	0029 RIGHT PARENTHESIS
+ * 320B PARENTHESIZED HANGUL THIEUTH
+ * 	0028 LEFT PARENTHESIS
+ * 	1110 HANGUL CHOSEONG THIEUTH
+ * 	0029 RIGHT PARENTHESIS
+ * 320C PARENTHESIZED HANGUL PHIEUPH
+ * 	0028 LEFT PARENTHESIS
+ * 	1111 HANGUL CHOSEONG PHIEUPH
+ * 	0029 RIGHT PARENTHESIS
+ * 320D PARENTHESIZED HANGUL HIEUH
+ * 	0028 LEFT PARENTHESIS
+ * 	1112 HANGUL CHOSEONG HIEUH
+ * 	0029 RIGHT PARENTHESIS
+ * 320E PARENTHESIZED HANGUL KIYEOK A
+ * 	0028 LEFT PARENTHESIS
+ * 	1100 HANGUL CHOSEONG KIYEOK
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 320F PARENTHESIZED HANGUL NIEUN A
+ * 	0028 LEFT PARENTHESIS
+ * 	1102 HANGUL CHOSEONG NIEUN
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 3210 PARENTHESIZED HANGUL TIKEUT A
+ * 	0028 LEFT PARENTHESIS
+ * 	1103 HANGUL CHOSEONG TIKEUT
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 3211 PARENTHESIZED HANGUL RIEUL A
+ * 	0028 LEFT PARENTHESIS
+ * 	1105 HANGUL CHOSEONG RIEUL
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 3212 PARENTHESIZED HANGUL MIEUM A
+ * 	0028 LEFT PARENTHESIS
+ * 	1106 HANGUL CHOSEONG MIEUM
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 3213 PARENTHESIZED HANGUL PIEUP A
+ * 	0028 LEFT PARENTHESIS
+ * 	1107 HANGUL CHOSEONG PIEUP
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 3214 PARENTHESIZED HANGUL SIOS A
+ * 	0028 LEFT PARENTHESIS
+ * 	1109 HANGUL CHOSEONG SIOS
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 3215 PARENTHESIZED HANGUL IEUNG A
+ * 	0028 LEFT PARENTHESIS
+ * 	110B HANGUL CHOSEONG IEUNG
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 3216 PARENTHESIZED HANGUL CIEUC A
+ * 	0028 LEFT PARENTHESIS
+ * 	110C HANGUL CHOSEONG CIEUC
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 3217 PARENTHESIZED HANGUL CHIEUCH A
+ * 	0028 LEFT PARENTHESIS
+ * 	110E HANGUL CHOSEONG CHIEUCH
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 3218 PARENTHESIZED HANGUL KHIEUKH A
+ * 	0028 LEFT PARENTHESIS
+ * 	110F HANGUL CHOSEONG KHIEUKH
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 3219 PARENTHESIZED HANGUL THIEUTH A
+ * 	0028 LEFT PARENTHESIS
+ * 	1110 HANGUL CHOSEONG THIEUTH
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 321A PARENTHESIZED HANGUL PHIEUPH A
+ * 	0028 LEFT PARENTHESIS
+ * 	1111 HANGUL CHOSEONG PHIEUPH
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 321B PARENTHESIZED HANGUL HIEUH A
+ * 	0028 LEFT PARENTHESIS
+ * 	1112 HANGUL CHOSEONG HIEUH
+ * 	1161 HANGUL JUNGSEONG A
+ * 	0029 RIGHT PARENTHESIS
+ * 321C PARENTHESIZED HANGUL CIEUC U
+ * 	0028 LEFT PARENTHESIS
+ * 	110C HANGUL CHOSEONG CIEUC
+ * 	116E HANGUL JUNGSEONG U
+ * 	0029 RIGHT PARENTHESIS
+ * 3220 PARENTHESIZED IDEOGRAPH ONE
+ * 	0028 LEFT PARENTHESIS
+ * 	4E00 <CJK Ideograph, First>
+ * 	0029 RIGHT PARENTHESIS
+ * 3221 PARENTHESIZED IDEOGRAPH TWO
+ * 	0028 LEFT PARENTHESIS
+ * 	4E8C ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3222 PARENTHESIZED IDEOGRAPH THREE
+ * 	0028 LEFT PARENTHESIS
+ * 	4E09 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3223 PARENTHESIZED IDEOGRAPH FOUR
+ * 	0028 LEFT PARENTHESIS
+ * 	56DB ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3224 PARENTHESIZED IDEOGRAPH FIVE
+ * 	0028 LEFT PARENTHESIS
+ * 	4E94 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3225 PARENTHESIZED IDEOGRAPH SIX
+ * 	0028 LEFT PARENTHESIS
+ * 	516D ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3226 PARENTHESIZED IDEOGRAPH SEVEN
+ * 	0028 LEFT PARENTHESIS
+ * 	4E03 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3227 PARENTHESIZED IDEOGRAPH EIGHT
+ * 	0028 LEFT PARENTHESIS
+ * 	516B ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3228 PARENTHESIZED IDEOGRAPH NINE
+ * 	0028 LEFT PARENTHESIS
+ * 	4E5D ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3229 PARENTHESIZED IDEOGRAPH TEN
+ * 	0028 LEFT PARENTHESIS
+ * 	5341 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 322A PARENTHESIZED IDEOGRAPH MOON
+ * 	0028 LEFT PARENTHESIS
+ * 	6708 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 322B PARENTHESIZED IDEOGRAPH FIRE
+ * 	0028 LEFT PARENTHESIS
+ * 	706B ??
+ * 	0029 RIGHT PARENTHESIS
+ * 322C PARENTHESIZED IDEOGRAPH WATER
+ * 	0028 LEFT PARENTHESIS
+ * 	6C34 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 322D PARENTHESIZED IDEOGRAPH WOOD
+ * 	0028 LEFT PARENTHESIS
+ * 	6728 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 322E PARENTHESIZED IDEOGRAPH METAL
+ * 	0028 LEFT PARENTHESIS
+ * 	91D1 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 322F PARENTHESIZED IDEOGRAPH EARTH
+ * 	0028 LEFT PARENTHESIS
+ * 	571F ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3230 PARENTHESIZED IDEOGRAPH SUN
+ * 	0028 LEFT PARENTHESIS
+ * 	65E5 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3231 PARENTHESIZED IDEOGRAPH STOCK
+ * 	0028 LEFT PARENTHESIS
+ * 	682A ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3232 PARENTHESIZED IDEOGRAPH HAVE
+ * 	0028 LEFT PARENTHESIS
+ * 	6709 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3233 PARENTHESIZED IDEOGRAPH SOCIETY
+ * 	0028 LEFT PARENTHESIS
+ * 	793E ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3234 PARENTHESIZED IDEOGRAPH NAME
+ * 	0028 LEFT PARENTHESIS
+ * 	540D ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3235 PARENTHESIZED IDEOGRAPH SPECIAL
+ * 	0028 LEFT PARENTHESIS
+ * 	7279 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3236 PARENTHESIZED IDEOGRAPH FINANCIAL
+ * 	0028 LEFT PARENTHESIS
+ * 	8CA1 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3237 PARENTHESIZED IDEOGRAPH CONGRATULATION
+ * 	0028 LEFT PARENTHESIS
+ * 	795D ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3238 PARENTHESIZED IDEOGRAPH LABOR
+ * 	0028 LEFT PARENTHESIS
+ * 	52B4 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3239 PARENTHESIZED IDEOGRAPH REPRESENT
+ * 	0028 LEFT PARENTHESIS
+ * 	4EE3 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 323A PARENTHESIZED IDEOGRAPH CALL
+ * 	0028 LEFT PARENTHESIS
+ * 	547C ??
+ * 	0029 RIGHT PARENTHESIS
+ * 323B PARENTHESIZED IDEOGRAPH STUDY
+ * 	0028 LEFT PARENTHESIS
+ * 	5B66 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 323C PARENTHESIZED IDEOGRAPH SUPERVISE
+ * 	0028 LEFT PARENTHESIS
+ * 	76E3 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 323D PARENTHESIZED IDEOGRAPH ENTERPRISE
+ * 	0028 LEFT PARENTHESIS
+ * 	4F01 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 323E PARENTHESIZED IDEOGRAPH RESOURCE
+ * 	0028 LEFT PARENTHESIS
+ * 	8CC7 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 323F PARENTHESIZED IDEOGRAPH ALLIANCE
+ * 	0028 LEFT PARENTHESIS
+ * 	5354 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3240 PARENTHESIZED IDEOGRAPH FESTIVAL
+ * 	0028 LEFT PARENTHESIS
+ * 	796D ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3241 PARENTHESIZED IDEOGRAPH REST
+ * 	0028 LEFT PARENTHESIS
+ * 	4F11 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3242 PARENTHESIZED IDEOGRAPH SELF
+ * 	0028 LEFT PARENTHESIS
+ * 	81EA ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3243 PARENTHESIZED IDEOGRAPH REACH
+ * 	0028 LEFT PARENTHESIS
+ * 	81F3 ??
+ * 	0029 RIGHT PARENTHESIS
+ * 3251 CIRCLED NUMBER TWENTY ONE
+ * 	0032 DIGIT TWO
+ * 	0031 DIGIT ONE
+ * 3252 CIRCLED NUMBER TWENTY TWO
+ * 	0032 DIGIT TWO
+ * 	0032 DIGIT TWO
+ * 3253 CIRCLED NUMBER TWENTY THREE
+ * 	0032 DIGIT TWO
+ * 	0033 DIGIT THREE
+ * 3254 CIRCLED NUMBER TWENTY FOUR
+ * 	0032 DIGIT TWO
+ * 	0034 DIGIT FOUR
+ * 3255 CIRCLED NUMBER TWENTY FIVE
+ * 	0032 DIGIT TWO
+ * 	0035 DIGIT FIVE
+ * 3256 CIRCLED NUMBER TWENTY SIX
+ * 	0032 DIGIT TWO
+ * 	0036 DIGIT SIX
+ * 3257 CIRCLED NUMBER TWENTY SEVEN
+ * 	0032 DIGIT TWO
+ * 	0037 DIGIT SEVEN
+ * 3258 CIRCLED NUMBER TWENTY EIGHT
+ * 	0032 DIGIT TWO
+ * 	0038 DIGIT EIGHT
+ * 3259 CIRCLED NUMBER TWENTY NINE
+ * 	0032 DIGIT TWO
+ * 	0039 DIGIT NINE
+ * 325A CIRCLED NUMBER THIRTY
+ * 	0033 DIGIT THREE
+ * 	0030 DIGIT ZERO
+ * 325B CIRCLED NUMBER THIRTY ONE
+ * 	0033 DIGIT THREE
+ * 	0031 DIGIT ONE
+ * 325C CIRCLED NUMBER THIRTY TWO
+ * 	0033 DIGIT THREE
+ * 	0032 DIGIT TWO
+ * 325D CIRCLED NUMBER THIRTY THREE
+ * 	0033 DIGIT THREE
+ * 	0033 DIGIT THREE
+ * 325E CIRCLED NUMBER THIRTY FOUR
+ * 	0033 DIGIT THREE
+ * 	0034 DIGIT FOUR
+ * 325F CIRCLED NUMBER THIRTY FIVE
+ * 	0033 DIGIT THREE
+ * 	0035 DIGIT FIVE
+ * 3260 CIRCLED HANGUL KIYEOK
+ * 	1100 HANGUL CHOSEONG KIYEOK
+ * 3261 CIRCLED HANGUL NIEUN
+ * 	1102 HANGUL CHOSEONG NIEUN
+ * 3262 CIRCLED HANGUL TIKEUT
+ * 	1103 HANGUL CHOSEONG TIKEUT
+ * 3263 CIRCLED HANGUL RIEUL
+ * 	1105 HANGUL CHOSEONG RIEUL
+ * 3264 CIRCLED HANGUL MIEUM
+ * 	1106 HANGUL CHOSEONG MIEUM
+ * 3265 CIRCLED HANGUL PIEUP
+ * 	1107 HANGUL CHOSEONG PIEUP
+ * 3266 CIRCLED HANGUL SIOS
+ * 	1109 HANGUL CHOSEONG SIOS
+ * 3267 CIRCLED HANGUL IEUNG
+ * 	110B HANGUL CHOSEONG IEUNG
+ * 3268 CIRCLED HANGUL CIEUC
+ * 	110C HANGUL CHOSEONG CIEUC
+ * 3269 CIRCLED HANGUL CHIEUCH
+ * 	110E HANGUL CHOSEONG CHIEUCH
+ * 326A CIRCLED HANGUL KHIEUKH
+ * 	110F HANGUL CHOSEONG KHIEUKH
+ * 326B CIRCLED HANGUL THIEUTH
+ * 	1110 HANGUL CHOSEONG THIEUTH
+ * 326C CIRCLED HANGUL PHIEUPH
+ * 	1111 HANGUL CHOSEONG PHIEUPH
+ * 326D CIRCLED HANGUL HIEUH
+ * 	1112 HANGUL CHOSEONG HIEUH
+ * 326E CIRCLED HANGUL KIYEOK A
+ * 	1100 HANGUL CHOSEONG KIYEOK
+ * 	1161 HANGUL JUNGSEONG A
+ * 326F CIRCLED HANGUL NIEUN A
+ * 	1102 HANGUL CHOSEONG NIEUN
+ * 	1161 HANGUL JUNGSEONG A
+ * 3270 CIRCLED HANGUL TIKEUT A
+ * 	1103 HANGUL CHOSEONG TIKEUT
+ * 	1161 HANGUL JUNGSEONG A
+ * 3271 CIRCLED HANGUL RIEUL A
+ * 	1105 HANGUL CHOSEONG RIEUL
+ * 	1161 HANGUL JUNGSEONG A
+ * 3272 CIRCLED HANGUL MIEUM A
+ * 	1106 HANGUL CHOSEONG MIEUM
+ * 	1161 HANGUL JUNGSEONG A
+ * 3273 CIRCLED HANGUL PIEUP A
+ * 	1107 HANGUL CHOSEONG PIEUP
+ * 	1161 HANGUL JUNGSEONG A
+ * 3274 CIRCLED HANGUL SIOS A
+ * 	1109 HANGUL CHOSEONG SIOS
+ * 	1161 HANGUL JUNGSEONG A
+ * 3275 CIRCLED HANGUL IEUNG A
+ * 	110B HANGUL CHOSEONG IEUNG
+ * 	1161 HANGUL JUNGSEONG A
+ * 3276 CIRCLED HANGUL CIEUC A
+ * 	110C HANGUL CHOSEONG CIEUC
+ * 	1161 HANGUL JUNGSEONG A
+ * 3277 CIRCLED HANGUL CHIEUCH A
+ * 	110E HANGUL CHOSEONG CHIEUCH
+ * 	1161 HANGUL JUNGSEONG A
+ * 3278 CIRCLED HANGUL KHIEUKH A
+ * 	110F HANGUL CHOSEONG KHIEUKH
+ * 	1161 HANGUL JUNGSEONG A
+ * 3279 CIRCLED HANGUL THIEUTH A
+ * 	1110 HANGUL CHOSEONG THIEUTH
+ * 	1161 HANGUL JUNGSEONG A
+ * 327A CIRCLED HANGUL PHIEUPH A
+ * 	1111 HANGUL CHOSEONG PHIEUPH
+ * 	1161 HANGUL JUNGSEONG A
+ * 327B CIRCLED HANGUL HIEUH A
+ * 	1112 HANGUL CHOSEONG HIEUH
+ * 	1161 HANGUL JUNGSEONG A
+ * 3280 CIRCLED IDEOGRAPH ONE
+ * 	4E00 <CJK Ideograph, First>
+ * 3281 CIRCLED IDEOGRAPH TWO
+ * 	4E8C ??
+ * 3282 CIRCLED IDEOGRAPH THREE
+ * 	4E09 ??
+ * 3283 CIRCLED IDEOGRAPH FOUR
+ * 	56DB ??
+ * 3284 CIRCLED IDEOGRAPH FIVE
+ * 	4E94 ??
+ * 3285 CIRCLED IDEOGRAPH SIX
+ * 	516D ??
+ * 3286 CIRCLED IDEOGRAPH SEVEN
+ * 	4E03 ??
+ * 3287 CIRCLED IDEOGRAPH EIGHT
+ * 	516B ??
+ * 3288 CIRCLED IDEOGRAPH NINE
+ * 	4E5D ??
+ * 3289 CIRCLED IDEOGRAPH TEN
+ * 	5341 ??
+ * 328A CIRCLED IDEOGRAPH MOON
+ * 	6708 ??
+ * 328B CIRCLED IDEOGRAPH FIRE
+ * 	706B ??
+ * 328C CIRCLED IDEOGRAPH WATER
+ * 	6C34 ??
+ * 328D CIRCLED IDEOGRAPH WOOD
+ * 	6728 ??
+ * 328E CIRCLED IDEOGRAPH METAL
+ * 	91D1 ??
+ * 328F CIRCLED IDEOGRAPH EARTH
+ * 	571F ??
+ * 3290 CIRCLED IDEOGRAPH SUN
+ * 	65E5 ??
+ * 3291 CIRCLED IDEOGRAPH STOCK
+ * 	682A ??
+ * 3292 CIRCLED IDEOGRAPH HAVE
+ * 	6709 ??
+ * 3293 CIRCLED IDEOGRAPH SOCIETY
+ * 	793E ??
+ * 3294 CIRCLED IDEOGRAPH NAME
+ * 	540D ??
+ * 3295 CIRCLED IDEOGRAPH SPECIAL
+ * 	7279 ??
+ * 3296 CIRCLED IDEOGRAPH FINANCIAL
+ * 	8CA1 ??
+ * 3297 CIRCLED IDEOGRAPH CONGRATULATION
+ * 	795D ??
+ * 3298 CIRCLED IDEOGRAPH LABOR
+ * 	52B4 ??
+ * 3299 CIRCLED IDEOGRAPH SECRET
+ * 	79D8 ??
+ * 329A CIRCLED IDEOGRAPH MALE
+ * 	7537 ??
+ * 329B CIRCLED IDEOGRAPH FEMALE
+ * 	5973 ??
+ * 329C CIRCLED IDEOGRAPH SUITABLE
+ * 	9069 ??
+ * 329D CIRCLED IDEOGRAPH EXCELLENT
+ * 	512A ??
+ * 329E CIRCLED IDEOGRAPH PRINT
+ * 	5370 ??
+ * 329F CIRCLED IDEOGRAPH ATTENTION
+ * 	6CE8 ??
+ * 32A0 CIRCLED IDEOGRAPH ITEM
+ * 	9805 ??
+ * 32A1 CIRCLED IDEOGRAPH REST
+ * 	4F11 ??
+ * 32A2 CIRCLED IDEOGRAPH COPY
+ * 	5199 ??
+ * 32A3 CIRCLED IDEOGRAPH CORRECT
+ * 	6B63 ??
+ * 32A4 CIRCLED IDEOGRAPH HIGH
+ * 	4E0A ??
+ * 32A5 CIRCLED IDEOGRAPH CENTRE
+ * 	4E2D ??
+ * 32A6 CIRCLED IDEOGRAPH LOW
+ * 	4E0B ??
+ * 32A7 CIRCLED IDEOGRAPH LEFT
+ * 	5DE6 ??
+ * 32A8 CIRCLED IDEOGRAPH RIGHT
+ * 	53F3 ??
+ * 32A9 CIRCLED IDEOGRAPH MEDICINE
+ * 	533B ??
+ * 32AA CIRCLED IDEOGRAPH RELIGION
+ * 	5B97 ??
+ * 32AB CIRCLED IDEOGRAPH STUDY
+ * 	5B66 ??
+ * 32AC CIRCLED IDEOGRAPH SUPERVISE
+ * 	76E3 ??
+ * 32AD CIRCLED IDEOGRAPH ENTERPRISE
+ * 	4F01 ??
+ * 32AE CIRCLED IDEOGRAPH RESOURCE
+ * 	8CC7 ??
+ * 32AF CIRCLED IDEOGRAPH ALLIANCE
+ * 	5354 ??
+ * 32B0 CIRCLED IDEOGRAPH NIGHT
+ * 	591C ??
+ * 32B1 CIRCLED NUMBER THIRTY SIX
+ * 	0033 DIGIT THREE
+ * 	0036 DIGIT SIX
+ * 32B2 CIRCLED NUMBER THIRTY SEVEN
+ * 	0033 DIGIT THREE
+ * 	0037 DIGIT SEVEN
+ * 32B3 CIRCLED NUMBER THIRTY EIGHT
+ * 	0033 DIGIT THREE
+ * 	0038 DIGIT EIGHT
+ * 32B4 CIRCLED NUMBER THIRTY NINE
+ * 	0033 DIGIT THREE
+ * 	0039 DIGIT NINE
+ * 32B5 CIRCLED NUMBER FORTY
+ * 	0034 DIGIT FOUR
+ * 	0030 DIGIT ZERO
+ * 32B6 CIRCLED NUMBER FORTY ONE
+ * 	0034 DIGIT FOUR
+ * 	0031 DIGIT ONE
+ * 32B7 CIRCLED NUMBER FORTY TWO
+ * 	0034 DIGIT FOUR
+ * 	0032 DIGIT TWO
+ * 32B8 CIRCLED NUMBER FORTY THREE
+ * 	0034 DIGIT FOUR
+ * 	0033 DIGIT THREE
+ * 32B9 CIRCLED NUMBER FORTY FOUR
+ * 	0034 DIGIT FOUR
+ * 	0034 DIGIT FOUR
+ * 32BA CIRCLED NUMBER FORTY FIVE
+ * 	0034 DIGIT FOUR
+ * 	0035 DIGIT FIVE
+ * 32BB CIRCLED NUMBER FORTY SIX
+ * 	0034 DIGIT FOUR
+ * 	0036 DIGIT SIX
+ * 32BC CIRCLED NUMBER FORTY SEVEN
+ * 	0034 DIGIT FOUR
+ * 	0037 DIGIT SEVEN
+ * 32BD CIRCLED NUMBER FORTY EIGHT
+ * 	0034 DIGIT FOUR
+ * 	0038 DIGIT EIGHT
+ * 32BE CIRCLED NUMBER FORTY NINE
+ * 	0034 DIGIT FOUR
+ * 	0039 DIGIT NINE
+ * 32BF CIRCLED NUMBER FIFTY
+ * 	0035 DIGIT FIVE
+ * 	0030 DIGIT ZERO
+ * 32C0 IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY
+ * 	0031 DIGIT ONE
+ * 	6708 ??
+ * 32C1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY
+ * 	0032 DIGIT TWO
+ * 	6708 ??
+ * 32C2 IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH
+ * 	0033 DIGIT THREE
+ * 	6708 ??
+ * 32C3 IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL
+ * 	0034 DIGIT FOUR
+ * 	6708 ??
+ * 32C4 IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY
+ * 	0035 DIGIT FIVE
+ * 	6708 ??
+ * 32C5 IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE
+ * 	0036 DIGIT SIX
+ * 	6708 ??
+ * 32C6 IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY
+ * 	0037 DIGIT SEVEN
+ * 	6708 ??
+ * 32C7 IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST
+ * 	0038 DIGIT EIGHT
+ * 	6708 ??
+ * 32C8 IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER
+ * 	0039 DIGIT NINE
+ * 	6708 ??
+ * 32C9 IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER
+ * 	0031 DIGIT ONE
+ * 	0030 DIGIT ZERO
+ * 	6708 ??
+ * 32CA IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER
+ * 	0031 DIGIT ONE
+ * 	0031 DIGIT ONE
+ * 	6708 ??
+ * 32CB IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER
+ * 	0031 DIGIT ONE
+ * 	0032 DIGIT TWO
+ * 	6708 ??
+ * 32D0 CIRCLED KATAKANA A
+ * 	30A2 KATAKANA LETTER A
+ * 32D1 CIRCLED KATAKANA I
+ * 	30A4 KATAKANA LETTER I
+ * 32D2 CIRCLED KATAKANA U
+ * 	30A6 KATAKANA LETTER U
+ * 32D3 CIRCLED KATAKANA E
+ * 	30A8 KATAKANA LETTER E
+ * 32D4 CIRCLED KATAKANA O
+ * 	30AA KATAKANA LETTER O
+ * 32D5 CIRCLED KATAKANA KA
+ * 	30AB KATAKANA LETTER KA
+ * 32D6 CIRCLED KATAKANA KI
+ * 	30AD KATAKANA LETTER KI
+ * 32D7 CIRCLED KATAKANA KU
+ * 	30AF KATAKANA LETTER KU
+ * 32D8 CIRCLED KATAKANA KE
+ * 	30B1 KATAKANA LETTER KE
+ * 32D9 CIRCLED KATAKANA KO
+ * 	30B3 KATAKANA LETTER KO
+ * 32DA CIRCLED KATAKANA SA
+ * 	30B5 KATAKANA LETTER SA
+ * 32DB CIRCLED KATAKANA SI
+ * 	30B7 KATAKANA LETTER SI
+ * 32DC CIRCLED KATAKANA SU
+ * 	30B9 KATAKANA LETTER SU
+ * 32DD CIRCLED KATAKANA SE
+ * 	30BB KATAKANA LETTER SE
+ * 32DE CIRCLED KATAKANA SO
+ * 	30BD KATAKANA LETTER SO
+ * 32DF CIRCLED KATAKANA TA
+ * 	30BF KATAKANA LETTER TA
+ * 32E0 CIRCLED KATAKANA TI
+ * 	30C1 KATAKANA LETTER TI
+ * 32E1 CIRCLED KATAKANA TU
+ * 	30C4 KATAKANA LETTER TU
+ * 32E2 CIRCLED KATAKANA TE
+ * 	30C6 KATAKANA LETTER TE
+ * 32E3 CIRCLED KATAKANA TO
+ * 	30C8 KATAKANA LETTER TO
+ * 32E4 CIRCLED KATAKANA NA
+ * 	30CA KATAKANA LETTER NA
+ * 32E5 CIRCLED KATAKANA NI
+ * 	30CB KATAKANA LETTER NI
+ * 32E6 CIRCLED KATAKANA NU
+ * 	30CC KATAKANA LETTER NU
+ * 32E7 CIRCLED KATAKANA NE
+ * 	30CD KATAKANA LETTER NE
+ * 32E8 CIRCLED KATAKANA NO
+ * 	30CE KATAKANA LETTER NO
+ * 32E9 CIRCLED KATAKANA HA
+ * 	30CF KATAKANA LETTER HA
+ * 32EA CIRCLED KATAKANA HI
+ * 	30D2 KATAKANA LETTER HI
+ * 32EB CIRCLED KATAKANA HU
+ * 	30D5 KATAKANA LETTER HU
+ * 32EC CIRCLED KATAKANA HE
+ * 	30D8 KATAKANA LETTER HE
+ * 32ED CIRCLED KATAKANA HO
+ * 	30DB KATAKANA LETTER HO
+ * 32EE CIRCLED KATAKANA MA
+ * 	30DE KATAKANA LETTER MA
+ * 32EF CIRCLED KATAKANA MI
+ * 	30DF KATAKANA LETTER MI
+ * 32F0 CIRCLED KATAKANA MU
+ * 	30E0 KATAKANA LETTER MU
+ * 32F1 CIRCLED KATAKANA ME
+ * 	30E1 KATAKANA LETTER ME
+ * 32F2 CIRCLED KATAKANA MO
+ * 	30E2 KATAKANA LETTER MO
+ * 32F3 CIRCLED KATAKANA YA
+ * 	30E4 KATAKANA LETTER YA
+ * 32F4 CIRCLED KATAKANA YU
+ * 	30E6 KATAKANA LETTER YU
+ * 32F5 CIRCLED KATAKANA YO
+ * 	30E8 KATAKANA LETTER YO
+ * 32F6 CIRCLED KATAKANA RA
+ * 	30E9 KATAKANA LETTER RA
+ * 32F7 CIRCLED KATAKANA RI
+ * 	30EA KATAKANA LETTER RI
+ * 32F8 CIRCLED KATAKANA RU
+ * 	30EB KATAKANA LETTER RU
+ * 32F9 CIRCLED KATAKANA RE
+ * 	30EC KATAKANA LETTER RE
+ * 32FA CIRCLED KATAKANA RO
+ * 	30ED KATAKANA LETTER RO
+ * 32FB CIRCLED KATAKANA WA
+ * 	30EF KATAKANA LETTER WA
+ * 32FC CIRCLED KATAKANA WI
+ * 	30F0 KATAKANA LETTER WI
+ * 32FD CIRCLED KATAKANA WE
+ * 	30F1 KATAKANA LETTER WE
+ * 32FE CIRCLED KATAKANA WO
+ * 	30F2 KATAKANA LETTER WO
+ * 3300 SQUARE APAATO
+ * 	30A2 KATAKANA LETTER A
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30C8 KATAKANA LETTER TO
+ * 	30CF KATAKANA LETTER HA
+ * 3301 SQUARE ARUHUA
+ * 	30A2 KATAKANA LETTER A
+ * 	30EB KATAKANA LETTER RU
+ * 	30D5 KATAKANA LETTER HU
+ * 	30A1 KATAKANA LETTER SMALL A
+ * 3302 SQUARE ANPEA
+ * 	30A2 KATAKANA LETTER A
+ * 	30F3 KATAKANA LETTER N
+ * 	30A2 KATAKANA LETTER A
+ * 	30D8 KATAKANA LETTER HE
+ * 3303 SQUARE AARU
+ * 	30A2 KATAKANA LETTER A
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30EB KATAKANA LETTER RU
+ * 3304 SQUARE ININGU
+ * 	30A4 KATAKANA LETTER I
+ * 	30CB KATAKANA LETTER NI
+ * 	30F3 KATAKANA LETTER N
+ * 	30AF KATAKANA LETTER KU
+ * 3305 SQUARE INTI
+ * 	30A4 KATAKANA LETTER I
+ * 	30F3 KATAKANA LETTER N
+ * 	30C1 KATAKANA LETTER TI
+ * 3306 SQUARE UON
+ * 	30A6 KATAKANA LETTER U
+ * 	30A9 KATAKANA LETTER SMALL O
+ * 	30F3 KATAKANA LETTER N
+ * 3307 SQUARE ESUKUUDO
+ * 	30A8 KATAKANA LETTER E
+ * 	30B9 KATAKANA LETTER SU
+ * 	30AF KATAKANA LETTER KU
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30C8 KATAKANA LETTER TO
+ * 3308 SQUARE EEKAA
+ * 	30A8 KATAKANA LETTER E
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30AB KATAKANA LETTER KA
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 3309 SQUARE ONSU
+ * 	30AA KATAKANA LETTER O
+ * 	30F3 KATAKANA LETTER N
+ * 	30B9 KATAKANA LETTER SU
+ * 330A SQUARE OOMU
+ * 	30AA KATAKANA LETTER O
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30E0 KATAKANA LETTER MU
+ * 330B SQUARE KAIRI
+ * 	30AB KATAKANA LETTER KA
+ * 	30A4 KATAKANA LETTER I
+ * 	30EA KATAKANA LETTER RI
+ * 330C SQUARE KARATTO
+ * 	30AB KATAKANA LETTER KA
+ * 	30E9 KATAKANA LETTER RA
+ * 	30C3 KATAKANA LETTER SMALL TU
+ * 	30C8 KATAKANA LETTER TO
+ * 330D SQUARE KARORII
+ * 	30AB KATAKANA LETTER KA
+ * 	30ED KATAKANA LETTER RO
+ * 	30EA KATAKANA LETTER RI
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 330E SQUARE GARON
+ * 	30ED KATAKANA LETTER RO
+ * 	30F3 KATAKANA LETTER N
+ * 	30AB KATAKANA LETTER KA
+ * 330F SQUARE GANMA
+ * 	30F3 KATAKANA LETTER N
+ * 	30DE KATAKANA LETTER MA
+ * 	30AB KATAKANA LETTER KA
+ * 3310 SQUARE GIGA
+ * 	30AD KATAKANA LETTER KI
+ * 	30AB KATAKANA LETTER KA
+ * 3311 SQUARE GINII
+ * 	30CB KATAKANA LETTER NI
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30AD KATAKANA LETTER KI
+ * 3312 SQUARE KYURII
+ * 	30AD KATAKANA LETTER KI
+ * 	30E5 KATAKANA LETTER SMALL YU
+ * 	30EA KATAKANA LETTER RI
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 3313 SQUARE GIRUDAA
+ * 	30EB KATAKANA LETTER RU
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30AD KATAKANA LETTER KI
+ * 	30BF KATAKANA LETTER TA
+ * 3314 SQUARE KIRO
+ * 	30AD KATAKANA LETTER KI
+ * 	30ED KATAKANA LETTER RO
+ * 3315 SQUARE KIROGURAMU
+ * 	30AD KATAKANA LETTER KI
+ * 	30ED KATAKANA LETTER RO
+ * 	30E9 KATAKANA LETTER RA
+ * 	30E0 KATAKANA LETTER MU
+ * 	30AF KATAKANA LETTER KU
+ * 3316 SQUARE KIROMEETORU
+ * 	30AD KATAKANA LETTER KI
+ * 	30ED KATAKANA LETTER RO
+ * 	30E1 KATAKANA LETTER ME
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30C8 KATAKANA LETTER TO
+ * 	30EB KATAKANA LETTER RU
+ * 3317 SQUARE KIROWATTO
+ * 	30AD KATAKANA LETTER KI
+ * 	30ED KATAKANA LETTER RO
+ * 	30EF KATAKANA LETTER WA
+ * 	30C3 KATAKANA LETTER SMALL TU
+ * 	30C8 KATAKANA LETTER TO
+ * 3318 SQUARE GURAMU
+ * 	30E9 KATAKANA LETTER RA
+ * 	30E0 KATAKANA LETTER MU
+ * 	30AF KATAKANA LETTER KU
+ * 3319 SQUARE GURAMUTON
+ * 	30E9 KATAKANA LETTER RA
+ * 	30E0 KATAKANA LETTER MU
+ * 	30C8 KATAKANA LETTER TO
+ * 	30F3 KATAKANA LETTER N
+ * 	30AF KATAKANA LETTER KU
+ * 331A SQUARE KURUZEIRO
+ * 	30AF KATAKANA LETTER KU
+ * 	30EB KATAKANA LETTER RU
+ * 	30A4 KATAKANA LETTER I
+ * 	30ED KATAKANA LETTER RO
+ * 	30BB KATAKANA LETTER SE
+ * 331B SQUARE KUROONE
+ * 	30AF KATAKANA LETTER KU
+ * 	30ED KATAKANA LETTER RO
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30CD KATAKANA LETTER NE
+ * 331C SQUARE KEESU
+ * 	30B1 KATAKANA LETTER KE
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30B9 KATAKANA LETTER SU
+ * 331D SQUARE KORUNA
+ * 	30B3 KATAKANA LETTER KO
+ * 	30EB KATAKANA LETTER RU
+ * 	30CA KATAKANA LETTER NA
+ * 331E SQUARE KOOPO
+ * 	30B3 KATAKANA LETTER KO
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30DB KATAKANA LETTER HO
+ * 331F SQUARE SAIKURU
+ * 	30B5 KATAKANA LETTER SA
+ * 	30A4 KATAKANA LETTER I
+ * 	30AF KATAKANA LETTER KU
+ * 	30EB KATAKANA LETTER RU
+ * 3320 SQUARE SANTIIMU
+ * 	30B5 KATAKANA LETTER SA
+ * 	30F3 KATAKANA LETTER N
+ * 	30C1 KATAKANA LETTER TI
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30E0 KATAKANA LETTER MU
+ * 3321 SQUARE SIRINGU
+ * 	30B7 KATAKANA LETTER SI
+ * 	30EA KATAKANA LETTER RI
+ * 	30F3 KATAKANA LETTER N
+ * 	30AF KATAKANA LETTER KU
+ * 3322 SQUARE SENTI
+ * 	30BB KATAKANA LETTER SE
+ * 	30F3 KATAKANA LETTER N
+ * 	30C1 KATAKANA LETTER TI
+ * 3323 SQUARE SENTO
+ * 	30BB KATAKANA LETTER SE
+ * 	30F3 KATAKANA LETTER N
+ * 	30C8 KATAKANA LETTER TO
+ * 3324 SQUARE DAASU
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30B9 KATAKANA LETTER SU
+ * 	30BF KATAKANA LETTER TA
+ * 3325 SQUARE DESI
+ * 	30B7 KATAKANA LETTER SI
+ * 	30C6 KATAKANA LETTER TE
+ * 3326 SQUARE DORU
+ * 	30EB KATAKANA LETTER RU
+ * 	30C8 KATAKANA LETTER TO
+ * 3327 SQUARE TON
+ * 	30C8 KATAKANA LETTER TO
+ * 	30F3 KATAKANA LETTER N
+ * 3328 SQUARE NANO
+ * 	30CA KATAKANA LETTER NA
+ * 	30CE KATAKANA LETTER NO
+ * 3329 SQUARE NOTTO
+ * 	30CE KATAKANA LETTER NO
+ * 	30C3 KATAKANA LETTER SMALL TU
+ * 	30C8 KATAKANA LETTER TO
+ * 332A SQUARE HAITU
+ * 	30CF KATAKANA LETTER HA
+ * 	30A4 KATAKANA LETTER I
+ * 	30C4 KATAKANA LETTER TU
+ * 332B SQUARE PAASENTO
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30BB KATAKANA LETTER SE
+ * 	30F3 KATAKANA LETTER N
+ * 	30C8 KATAKANA LETTER TO
+ * 	30CF KATAKANA LETTER HA
+ * 332C SQUARE PAATU
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30C4 KATAKANA LETTER TU
+ * 	30CF KATAKANA LETTER HA
+ * 332D SQUARE BAARERU
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30EC KATAKANA LETTER RE
+ * 	30EB KATAKANA LETTER RU
+ * 	30CF KATAKANA LETTER HA
+ * 332E SQUARE PIASUTORU
+ * 	30A2 KATAKANA LETTER A
+ * 	30B9 KATAKANA LETTER SU
+ * 	30C8 KATAKANA LETTER TO
+ * 	30EB KATAKANA LETTER RU
+ * 	30D2 KATAKANA LETTER HI
+ * 332F SQUARE PIKURU
+ * 	30AF KATAKANA LETTER KU
+ * 	30EB KATAKANA LETTER RU
+ * 	30D2 KATAKANA LETTER HI
+ * 3330 SQUARE PIKO
+ * 	30B3 KATAKANA LETTER KO
+ * 	30D2 KATAKANA LETTER HI
+ * 3331 SQUARE BIRU
+ * 	30EB KATAKANA LETTER RU
+ * 	30D2 KATAKANA LETTER HI
+ * 3332 SQUARE HUARADDO
+ * 	30D5 KATAKANA LETTER HU
+ * 	30A1 KATAKANA LETTER SMALL A
+ * 	30E9 KATAKANA LETTER RA
+ * 	30C3 KATAKANA LETTER SMALL TU
+ * 	30C8 KATAKANA LETTER TO
+ * 3333 SQUARE HUIITO
+ * 	30D5 KATAKANA LETTER HU
+ * 	30A3 KATAKANA LETTER SMALL I
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30C8 KATAKANA LETTER TO
+ * 3334 SQUARE BUSSYERU
+ * 	30C3 KATAKANA LETTER SMALL TU
+ * 	30B7 KATAKANA LETTER SI
+ * 	30A7 KATAKANA LETTER SMALL E
+ * 	30EB KATAKANA LETTER RU
+ * 	30D5 KATAKANA LETTER HU
+ * 3335 SQUARE HURAN
+ * 	30D5 KATAKANA LETTER HU
+ * 	30E9 KATAKANA LETTER RA
+ * 	30F3 KATAKANA LETTER N
+ * 3336 SQUARE HEKUTAARU
+ * 	30D8 KATAKANA LETTER HE
+ * 	30AF KATAKANA LETTER KU
+ * 	30BF KATAKANA LETTER TA
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30EB KATAKANA LETTER RU
+ * 3337 SQUARE PESO
+ * 	30BD KATAKANA LETTER SO
+ * 	30D8 KATAKANA LETTER HE
+ * 3338 SQUARE PENIHI
+ * 	30CB KATAKANA LETTER NI
+ * 	30D2 KATAKANA LETTER HI
+ * 	30D8 KATAKANA LETTER HE
+ * 3339 SQUARE HERUTU
+ * 	30D8 KATAKANA LETTER HE
+ * 	30EB KATAKANA LETTER RU
+ * 	30C4 KATAKANA LETTER TU
+ * 333A SQUARE PENSU
+ * 	30F3 KATAKANA LETTER N
+ * 	30B9 KATAKANA LETTER SU
+ * 	30D8 KATAKANA LETTER HE
+ * 333B SQUARE PEEZI
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30D8 KATAKANA LETTER HE
+ * 	30B7 KATAKANA LETTER SI
+ * 333C SQUARE BEETA
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30BF KATAKANA LETTER TA
+ * 	30D8 KATAKANA LETTER HE
+ * 333D SQUARE POINTO
+ * 	30A4 KATAKANA LETTER I
+ * 	30F3 KATAKANA LETTER N
+ * 	30C8 KATAKANA LETTER TO
+ * 	30DB KATAKANA LETTER HO
+ * 333E SQUARE BORUTO
+ * 	30EB KATAKANA LETTER RU
+ * 	30C8 KATAKANA LETTER TO
+ * 	30DB KATAKANA LETTER HO
+ * 333F SQUARE HON
+ * 	30DB KATAKANA LETTER HO
+ * 	30F3 KATAKANA LETTER N
+ * 3340 SQUARE PONDO
+ * 	30F3 KATAKANA LETTER N
+ * 	30DB KATAKANA LETTER HO
+ * 	30C8 KATAKANA LETTER TO
+ * 3341 SQUARE HOORU
+ * 	30DB KATAKANA LETTER HO
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30EB KATAKANA LETTER RU
+ * 3342 SQUARE HOON
+ * 	30DB KATAKANA LETTER HO
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30F3 KATAKANA LETTER N
+ * 3343 SQUARE MAIKURO
+ * 	30DE KATAKANA LETTER MA
+ * 	30A4 KATAKANA LETTER I
+ * 	30AF KATAKANA LETTER KU
+ * 	30ED KATAKANA LETTER RO
+ * 3344 SQUARE MAIRU
+ * 	30DE KATAKANA LETTER MA
+ * 	30A4 KATAKANA LETTER I
+ * 	30EB KATAKANA LETTER RU
+ * 3345 SQUARE MAHHA
+ * 	30DE KATAKANA LETTER MA
+ * 	30C3 KATAKANA LETTER SMALL TU
+ * 	30CF KATAKANA LETTER HA
+ * 3346 SQUARE MARUKU
+ * 	30DE KATAKANA LETTER MA
+ * 	30EB KATAKANA LETTER RU
+ * 	30AF KATAKANA LETTER KU
+ * 3347 SQUARE MANSYON
+ * 	30DE KATAKANA LETTER MA
+ * 	30F3 KATAKANA LETTER N
+ * 	30B7 KATAKANA LETTER SI
+ * 	30E7 KATAKANA LETTER SMALL YO
+ * 	30F3 KATAKANA LETTER N
+ * 3348 SQUARE MIKURON
+ * 	30DF KATAKANA LETTER MI
+ * 	30AF KATAKANA LETTER KU
+ * 	30ED KATAKANA LETTER RO
+ * 	30F3 KATAKANA LETTER N
+ * 3349 SQUARE MIRI
+ * 	30DF KATAKANA LETTER MI
+ * 	30EA KATAKANA LETTER RI
+ * 334A SQUARE MIRIBAARU
+ * 	30DF KATAKANA LETTER MI
+ * 	30EA KATAKANA LETTER RI
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30EB KATAKANA LETTER RU
+ * 	30CF KATAKANA LETTER HA
+ * 334B SQUARE MEGA
+ * 	30E1 KATAKANA LETTER ME
+ * 	30AB KATAKANA LETTER KA
+ * 334C SQUARE MEGATON
+ * 	30E1 KATAKANA LETTER ME
+ * 	30C8 KATAKANA LETTER TO
+ * 	30F3 KATAKANA LETTER N
+ * 	30AB KATAKANA LETTER KA
+ * 334D SQUARE MEETORU
+ * 	30E1 KATAKANA LETTER ME
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30C8 KATAKANA LETTER TO
+ * 	30EB KATAKANA LETTER RU
+ * 334E SQUARE YAADO
+ * 	30E4 KATAKANA LETTER YA
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30C8 KATAKANA LETTER TO
+ * 334F SQUARE YAARU
+ * 	30E4 KATAKANA LETTER YA
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30EB KATAKANA LETTER RU
+ * 3350 SQUARE YUAN
+ * 	30E6 KATAKANA LETTER YU
+ * 	30A2 KATAKANA LETTER A
+ * 	30F3 KATAKANA LETTER N
+ * 3351 SQUARE RITTORU
+ * 	30EA KATAKANA LETTER RI
+ * 	30C3 KATAKANA LETTER SMALL TU
+ * 	30C8 KATAKANA LETTER TO
+ * 	30EB KATAKANA LETTER RU
+ * 3352 SQUARE RIRA
+ * 	30EA KATAKANA LETTER RI
+ * 	30E9 KATAKANA LETTER RA
+ * 3353 SQUARE RUPII
+ * 	30EB KATAKANA LETTER RU
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30D2 KATAKANA LETTER HI
+ * 3354 SQUARE RUUBURU
+ * 	30EB KATAKANA LETTER RU
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30EB KATAKANA LETTER RU
+ * 	30D5 KATAKANA LETTER HU
+ * 3355 SQUARE REMU
+ * 	30EC KATAKANA LETTER RE
+ * 	30E0 KATAKANA LETTER MU
+ * 3356 SQUARE RENTOGEN
+ * 	30EC KATAKANA LETTER RE
+ * 	30F3 KATAKANA LETTER N
+ * 	30C8 KATAKANA LETTER TO
+ * 	30F3 KATAKANA LETTER N
+ * 	30B1 KATAKANA LETTER KE
+ * 3357 SQUARE WATTO
+ * 	30EF KATAKANA LETTER WA
+ * 	30C3 KATAKANA LETTER SMALL TU
+ * 	30C8 KATAKANA LETTER TO
+ * 3358 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO
+ * 	0030 DIGIT ZERO
+ * 	70B9 ??
+ * 3359 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE
+ * 	0031 DIGIT ONE
+ * 	70B9 ??
+ * 335A IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO
+ * 	0032 DIGIT TWO
+ * 	70B9 ??
+ * 335B IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE
+ * 	0033 DIGIT THREE
+ * 	70B9 ??
+ * 335C IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR
+ * 	0034 DIGIT FOUR
+ * 	70B9 ??
+ * 335D IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE
+ * 	0035 DIGIT FIVE
+ * 	70B9 ??
+ * 335E IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX
+ * 	0036 DIGIT SIX
+ * 	70B9 ??
+ * 335F IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN
+ * 	0037 DIGIT SEVEN
+ * 	70B9 ??
+ * 3360 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT
+ * 	0038 DIGIT EIGHT
+ * 	70B9 ??
+ * 3361 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE
+ * 	0039 DIGIT NINE
+ * 	70B9 ??
+ * 3362 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN
+ * 	0031 DIGIT ONE
+ * 	0030 DIGIT ZERO
+ * 	70B9 ??
+ * 3363 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN
+ * 	0031 DIGIT ONE
+ * 	0031 DIGIT ONE
+ * 	70B9 ??
+ * 3364 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE
+ * 	0031 DIGIT ONE
+ * 	0032 DIGIT TWO
+ * 	70B9 ??
+ * 3365 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN
+ * 	0031 DIGIT ONE
+ * 	0033 DIGIT THREE
+ * 	70B9 ??
+ * 3366 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN
+ * 	0031 DIGIT ONE
+ * 	0034 DIGIT FOUR
+ * 	70B9 ??
+ * 3367 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN
+ * 	0031 DIGIT ONE
+ * 	0035 DIGIT FIVE
+ * 	70B9 ??
+ * 3368 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN
+ * 	0031 DIGIT ONE
+ * 	0036 DIGIT SIX
+ * 	70B9 ??
+ * 3369 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN
+ * 	0031 DIGIT ONE
+ * 	0037 DIGIT SEVEN
+ * 	70B9 ??
+ * 336A IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN
+ * 	0031 DIGIT ONE
+ * 	0038 DIGIT EIGHT
+ * 	70B9 ??
+ * 336B IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN
+ * 	0031 DIGIT ONE
+ * 	0039 DIGIT NINE
+ * 	70B9 ??
+ * 336C IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY
+ * 	0032 DIGIT TWO
+ * 	0030 DIGIT ZERO
+ * 	70B9 ??
+ * 336D IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE
+ * 	0032 DIGIT TWO
+ * 	0031 DIGIT ONE
+ * 	70B9 ??
+ * 336E IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO
+ * 	0032 DIGIT TWO
+ * 	0032 DIGIT TWO
+ * 	70B9 ??
+ * 336F IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE
+ * 	0032 DIGIT TWO
+ * 	0033 DIGIT THREE
+ * 	70B9 ??
+ * 3370 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR
+ * 	0032 DIGIT TWO
+ * 	0034 DIGIT FOUR
+ * 	70B9 ??
+ * 3371 SQUARE HPA
+ * 	0068 LATIN SMALL LETTER H
+ * 	0050 LATIN CAPITAL LETTER P
+ * 	0061 LATIN SMALL LETTER A
+ * 3372 SQUARE DA
+ * 	0064 LATIN SMALL LETTER D
+ * 	0061 LATIN SMALL LETTER A
+ * 3373 SQUARE AU
+ * 	0041 LATIN CAPITAL LETTER A
+ * 	0055 LATIN CAPITAL LETTER U
+ * 3374 SQUARE BAR
+ * 	0062 LATIN SMALL LETTER B
+ * 	0061 LATIN SMALL LETTER A
+ * 	0072 LATIN SMALL LETTER R
+ * 3375 SQUARE OV
+ * 	006F LATIN SMALL LETTER O
+ * 	0056 LATIN CAPITAL LETTER V
+ * 3376 SQUARE PC
+ * 	0070 LATIN SMALL LETTER P
+ * 	0063 LATIN SMALL LETTER C
+ * 337B SQUARE ERA NAME HEISEI
+ * 	5E73 ??
+ * 	6210 ??
+ * 337C SQUARE ERA NAME SYOUWA
+ * 	662D ??
+ * 	548C ??
+ * 337D SQUARE ERA NAME TAISYOU
+ * 	5927 ??
+ * 	6B63 ??
+ * 337E SQUARE ERA NAME MEIZI
+ * 	660E ??
+ * 	6CBB ??
+ * 337F SQUARE CORPORATION
+ * 	682A ??
+ * 	5F0F ??
+ * 	4F1A ??
+ * 	793E ??
+ * 3380 SQUARE PA AMPS
+ * 	0070 LATIN SMALL LETTER P
+ * 	0041 LATIN CAPITAL LETTER A
+ * 3381 SQUARE NA
+ * 	006E LATIN SMALL LETTER N
+ * 	0041 LATIN CAPITAL LETTER A
+ * 3382 SQUARE MU A
+ * 	03BC GREEK SMALL LETTER MU
+ * 	0041 LATIN CAPITAL LETTER A
+ * 3383 SQUARE MA
+ * 	006D LATIN SMALL LETTER M
+ * 	0041 LATIN CAPITAL LETTER A
+ * 3384 SQUARE KA
+ * 	006B LATIN SMALL LETTER K
+ * 	0041 LATIN CAPITAL LETTER A
+ * 3385 SQUARE KB
+ * 	004B LATIN CAPITAL LETTER K
+ * 	0042 LATIN CAPITAL LETTER B
+ * 3386 SQUARE MB
+ * 	004D LATIN CAPITAL LETTER M
+ * 	0042 LATIN CAPITAL LETTER B
+ * 3387 SQUARE GB
+ * 	0047 LATIN CAPITAL LETTER G
+ * 	0042 LATIN CAPITAL LETTER B
+ * 3388 SQUARE CAL
+ * 	0063 LATIN SMALL LETTER C
+ * 	0061 LATIN SMALL LETTER A
+ * 	006C LATIN SMALL LETTER L
+ * 3389 SQUARE KCAL
+ * 	006B LATIN SMALL LETTER K
+ * 	0063 LATIN SMALL LETTER C
+ * 	0061 LATIN SMALL LETTER A
+ * 	006C LATIN SMALL LETTER L
+ * 338A SQUARE PF
+ * 	0070 LATIN SMALL LETTER P
+ * 	0046 LATIN CAPITAL LETTER F
+ * 338B SQUARE NF
+ * 	006E LATIN SMALL LETTER N
+ * 	0046 LATIN CAPITAL LETTER F
+ * 338C SQUARE MU F
+ * 	03BC GREEK SMALL LETTER MU
+ * 	0046 LATIN CAPITAL LETTER F
+ * 338D SQUARE MU G
+ * 	03BC GREEK SMALL LETTER MU
+ * 	0067 LATIN SMALL LETTER G
+ * 338E SQUARE MG
+ * 	006D LATIN SMALL LETTER M
+ * 	0067 LATIN SMALL LETTER G
+ * 338F SQUARE KG
+ * 	006B LATIN SMALL LETTER K
+ * 	0067 LATIN SMALL LETTER G
+ * 3390 SQUARE HZ
+ * 	0048 LATIN CAPITAL LETTER H
+ * 	007A LATIN SMALL LETTER Z
+ * 3391 SQUARE KHZ
+ * 	006B LATIN SMALL LETTER K
+ * 	0048 LATIN CAPITAL LETTER H
+ * 	007A LATIN SMALL LETTER Z
+ * 3392 SQUARE MHZ
+ * 	004D LATIN CAPITAL LETTER M
+ * 	0048 LATIN CAPITAL LETTER H
+ * 	007A LATIN SMALL LETTER Z
+ * 3393 SQUARE GHZ
+ * 	0047 LATIN CAPITAL LETTER G
+ * 	0048 LATIN CAPITAL LETTER H
+ * 	007A LATIN SMALL LETTER Z
+ * 3394 SQUARE THZ
+ * 	0054 LATIN CAPITAL LETTER T
+ * 	0048 LATIN CAPITAL LETTER H
+ * 	007A LATIN SMALL LETTER Z
+ * 3395 SQUARE MU L
+ * 	03BC GREEK SMALL LETTER MU
+ * 	006C LATIN SMALL LETTER L
+ * 3396 SQUARE ML
+ * 	006D LATIN SMALL LETTER M
+ * 	006C LATIN SMALL LETTER L
+ * 3397 SQUARE DL
+ * 	0064 LATIN SMALL LETTER D
+ * 	006C LATIN SMALL LETTER L
+ * 3398 SQUARE KL
+ * 	006B LATIN SMALL LETTER K
+ * 	006C LATIN SMALL LETTER L
+ * 3399 SQUARE FM
+ * 	0066 LATIN SMALL LETTER F
+ * 	006D LATIN SMALL LETTER M
+ * 339A SQUARE NM
+ * 	006E LATIN SMALL LETTER N
+ * 	006D LATIN SMALL LETTER M
+ * 339B SQUARE MU M
+ * 	03BC GREEK SMALL LETTER MU
+ * 	006D LATIN SMALL LETTER M
+ * 339C SQUARE MM
+ * 	006D LATIN SMALL LETTER M
+ * 	006D LATIN SMALL LETTER M
+ * 339D SQUARE CM
+ * 	0063 LATIN SMALL LETTER C
+ * 	006D LATIN SMALL LETTER M
+ * 339E SQUARE KM
+ * 	006B LATIN SMALL LETTER K
+ * 	006D LATIN SMALL LETTER M
+ * 339F SQUARE MM SQUARED
+ * 	006D LATIN SMALL LETTER M
+ * 	006D LATIN SMALL LETTER M
+ * 	0032 DIGIT TWO
+ * 33A0 SQUARE CM SQUARED
+ * 	0063 LATIN SMALL LETTER C
+ * 	006D LATIN SMALL LETTER M
+ * 	0032 DIGIT TWO
+ * 33A1 SQUARE M SQUARED
+ * 	006D LATIN SMALL LETTER M
+ * 	0032 DIGIT TWO
+ * 33A2 SQUARE KM SQUARED
+ * 	006B LATIN SMALL LETTER K
+ * 	006D LATIN SMALL LETTER M
+ * 	0032 DIGIT TWO
+ * 33A3 SQUARE MM CUBED
+ * 	006D LATIN SMALL LETTER M
+ * 	006D LATIN SMALL LETTER M
+ * 	0033 DIGIT THREE
+ * 33A4 SQUARE CM CUBED
+ * 	0063 LATIN SMALL LETTER C
+ * 	006D LATIN SMALL LETTER M
+ * 	0033 DIGIT THREE
+ * 33A5 SQUARE M CUBED
+ * 	006D LATIN SMALL LETTER M
+ * 	0033 DIGIT THREE
+ * 33A6 SQUARE KM CUBED
+ * 	006B LATIN SMALL LETTER K
+ * 	006D LATIN SMALL LETTER M
+ * 	0033 DIGIT THREE
+ * 33A7 SQUARE M OVER S
+ * 	006D LATIN SMALL LETTER M
+ * 	2215 DIVISION SLASH
+ * 	0073 LATIN SMALL LETTER S
+ * 33A8 SQUARE M OVER S SQUARED
+ * 	006D LATIN SMALL LETTER M
+ * 	2215 DIVISION SLASH
+ * 	0073 LATIN SMALL LETTER S
+ * 	0032 DIGIT TWO
+ * 33A9 SQUARE PA
+ * 	0050 LATIN CAPITAL LETTER P
+ * 	0061 LATIN SMALL LETTER A
+ * 33AA SQUARE KPA
+ * 	006B LATIN SMALL LETTER K
+ * 	0050 LATIN CAPITAL LETTER P
+ * 	0061 LATIN SMALL LETTER A
+ * 33AB SQUARE MPA
+ * 	004D LATIN CAPITAL LETTER M
+ * 	0050 LATIN CAPITAL LETTER P
+ * 	0061 LATIN SMALL LETTER A
+ * 33AC SQUARE GPA
+ * 	0047 LATIN CAPITAL LETTER G
+ * 	0050 LATIN CAPITAL LETTER P
+ * 	0061 LATIN SMALL LETTER A
+ * 33AD SQUARE RAD
+ * 	0072 LATIN SMALL LETTER R
+ * 	0061 LATIN SMALL LETTER A
+ * 	0064 LATIN SMALL LETTER D
+ * 33AE SQUARE RAD OVER S
+ * 	0072 LATIN SMALL LETTER R
+ * 	0061 LATIN SMALL LETTER A
+ * 	0064 LATIN SMALL LETTER D
+ * 	2215 DIVISION SLASH
+ * 	0073 LATIN SMALL LETTER S
+ * 33AF SQUARE RAD OVER S SQUARED
+ * 	0072 LATIN SMALL LETTER R
+ * 	0061 LATIN SMALL LETTER A
+ * 	0064 LATIN SMALL LETTER D
+ * 	2215 DIVISION SLASH
+ * 	0073 LATIN SMALL LETTER S
+ * 	0032 DIGIT TWO
+ * 33B0 SQUARE PS
+ * 	0070 LATIN SMALL LETTER P
+ * 	0073 LATIN SMALL LETTER S
+ * 33B1 SQUARE NS
+ * 	006E LATIN SMALL LETTER N
+ * 	0073 LATIN SMALL LETTER S
+ * 33B2 SQUARE MU S
+ * 	03BC GREEK SMALL LETTER MU
+ * 	0073 LATIN SMALL LETTER S
+ * 33B3 SQUARE MS
+ * 	006D LATIN SMALL LETTER M
+ * 	0073 LATIN SMALL LETTER S
+ * 33B4 SQUARE PV
+ * 	0070 LATIN SMALL LETTER P
+ * 	0056 LATIN CAPITAL LETTER V
+ * 33B5 SQUARE NV
+ * 	006E LATIN SMALL LETTER N
+ * 	0056 LATIN CAPITAL LETTER V
+ * 33B6 SQUARE MU V
+ * 	03BC GREEK SMALL LETTER MU
+ * 	0056 LATIN CAPITAL LETTER V
+ * 33B7 SQUARE MV
+ * 	006D LATIN SMALL LETTER M
+ * 	0056 LATIN CAPITAL LETTER V
+ * 33B8 SQUARE KV
+ * 	006B LATIN SMALL LETTER K
+ * 	0056 LATIN CAPITAL LETTER V
+ * 33B9 SQUARE MV MEGA
+ * 	004D LATIN CAPITAL LETTER M
+ * 	0056 LATIN CAPITAL LETTER V
+ * 33BA SQUARE PW
+ * 	0070 LATIN SMALL LETTER P
+ * 	0057 LATIN CAPITAL LETTER W
+ * 33BB SQUARE NW
+ * 	006E LATIN SMALL LETTER N
+ * 	0057 LATIN CAPITAL LETTER W
+ * 33BC SQUARE MU W
+ * 	03BC GREEK SMALL LETTER MU
+ * 	0057 LATIN CAPITAL LETTER W
+ * 33BD SQUARE MW
+ * 	006D LATIN SMALL LETTER M
+ * 	0057 LATIN CAPITAL LETTER W
+ * 33BE SQUARE KW
+ * 	006B LATIN SMALL LETTER K
+ * 	0057 LATIN CAPITAL LETTER W
+ * 33BF SQUARE MW MEGA
+ * 	004D LATIN CAPITAL LETTER M
+ * 	0057 LATIN CAPITAL LETTER W
+ * 33C0 SQUARE K OHM
+ * 	006B LATIN SMALL LETTER K
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 33C1 SQUARE M OHM
+ * 	004D LATIN CAPITAL LETTER M
+ * 	03A9 GREEK CAPITAL LETTER OMEGA
+ * 33C2 SQUARE AM
+ * 	0061 LATIN SMALL LETTER A
+ * 	002E FULL STOP
+ * 	006D LATIN SMALL LETTER M
+ * 	002E FULL STOP
+ * 33C3 SQUARE BQ
+ * 	0042 LATIN CAPITAL LETTER B
+ * 	0071 LATIN SMALL LETTER Q
+ * 33C4 SQUARE CC
+ * 	0063 LATIN SMALL LETTER C
+ * 	0063 LATIN SMALL LETTER C
+ * 33C5 SQUARE CD
+ * 	0063 LATIN SMALL LETTER C
+ * 	0064 LATIN SMALL LETTER D
+ * 33C6 SQUARE C OVER KG
+ * 	0043 LATIN CAPITAL LETTER C
+ * 	2215 DIVISION SLASH
+ * 	006B LATIN SMALL LETTER K
+ * 	0067 LATIN SMALL LETTER G
+ * 33C7 SQUARE CO
+ * 	0043 LATIN CAPITAL LETTER C
+ * 	006F LATIN SMALL LETTER O
+ * 	002E FULL STOP
+ * 33C8 SQUARE DB
+ * 	0064 LATIN SMALL LETTER D
+ * 	0042 LATIN CAPITAL LETTER B
+ * 33C9 SQUARE GY
+ * 	0047 LATIN CAPITAL LETTER G
+ * 	0079 LATIN SMALL LETTER Y
+ * 33CA SQUARE HA
+ * 	0068 LATIN SMALL LETTER H
+ * 	0061 LATIN SMALL LETTER A
+ * 33CB SQUARE HP
+ * 	0048 LATIN CAPITAL LETTER H
+ * 	0050 LATIN CAPITAL LETTER P
+ * 33CC SQUARE IN
+ * 	0069 LATIN SMALL LETTER I
+ * 	006E LATIN SMALL LETTER N
+ * 33CD SQUARE KK
+ * 	004B LATIN CAPITAL LETTER K
+ * 	004B LATIN CAPITAL LETTER K
+ * 33CE SQUARE KM CAPITAL
+ * 	004B LATIN CAPITAL LETTER K
+ * 	004D LATIN CAPITAL LETTER M
+ * 33CF SQUARE KT
+ * 	006B LATIN SMALL LETTER K
+ * 	0074 LATIN SMALL LETTER T
+ * 33D0 SQUARE LM
+ * 	006C LATIN SMALL LETTER L
+ * 	006D LATIN SMALL LETTER M
+ * 33D1 SQUARE LN
+ * 	006C LATIN SMALL LETTER L
+ * 	006E LATIN SMALL LETTER N
+ * 33D2 SQUARE LOG
+ * 	006C LATIN SMALL LETTER L
+ * 	006F LATIN SMALL LETTER O
+ * 	0067 LATIN SMALL LETTER G
+ * 33D3 SQUARE LX
+ * 	006C LATIN SMALL LETTER L
+ * 	0078 LATIN SMALL LETTER X
+ * 33D4 SQUARE MB SMALL
+ * 	006D LATIN SMALL LETTER M
+ * 	0062 LATIN SMALL LETTER B
+ * 33D5 SQUARE MIL
+ * 	006D LATIN SMALL LETTER M
+ * 	0069 LATIN SMALL LETTER I
+ * 	006C LATIN SMALL LETTER L
+ * 33D6 SQUARE MOL
+ * 	006D LATIN SMALL LETTER M
+ * 	006F LATIN SMALL LETTER O
+ * 	006C LATIN SMALL LETTER L
+ * 33D7 SQUARE PH
+ * 	0050 LATIN CAPITAL LETTER P
+ * 	0048 LATIN CAPITAL LETTER H
+ * 33D8 SQUARE PM
+ * 	0070 LATIN SMALL LETTER P
+ * 	002E FULL STOP
+ * 	006D LATIN SMALL LETTER M
+ * 	002E FULL STOP
+ * 33D9 SQUARE PPM
+ * 	0050 LATIN CAPITAL LETTER P
+ * 	0050 LATIN CAPITAL LETTER P
+ * 	004D LATIN CAPITAL LETTER M
+ * 33DA SQUARE PR
+ * 	0050 LATIN CAPITAL LETTER P
+ * 	0052 LATIN CAPITAL LETTER R
+ * 33DB SQUARE SR
+ * 	0073 LATIN SMALL LETTER S
+ * 	0072 LATIN SMALL LETTER R
+ * 33DC SQUARE SV
+ * 	0053 LATIN CAPITAL LETTER S
+ * 	0076 LATIN SMALL LETTER V
+ * 33DD SQUARE WB
+ * 	0057 LATIN CAPITAL LETTER W
+ * 	0062 LATIN SMALL LETTER B
+ * 33E0 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE
+ * 	0031 DIGIT ONE
+ * 	65E5 ??
+ * 33E1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO
+ * 	0032 DIGIT TWO
+ * 	65E5 ??
+ * 33E2 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE
+ * 	0033 DIGIT THREE
+ * 	65E5 ??
+ * 33E3 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR
+ * 	0034 DIGIT FOUR
+ * 	65E5 ??
+ * 33E4 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE
+ * 	0035 DIGIT FIVE
+ * 	65E5 ??
+ * 33E5 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX
+ * 	0036 DIGIT SIX
+ * 	65E5 ??
+ * 33E6 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN
+ * 	0037 DIGIT SEVEN
+ * 	65E5 ??
+ * 33E7 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT
+ * 	0038 DIGIT EIGHT
+ * 	65E5 ??
+ * 33E8 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE
+ * 	0039 DIGIT NINE
+ * 	65E5 ??
+ * 33E9 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN
+ * 	0031 DIGIT ONE
+ * 	0030 DIGIT ZERO
+ * 	65E5 ??
+ * 33EA IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN
+ * 	0031 DIGIT ONE
+ * 	0031 DIGIT ONE
+ * 	65E5 ??
+ * 33EB IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE
+ * 	0031 DIGIT ONE
+ * 	0032 DIGIT TWO
+ * 	65E5 ??
+ * 33EC IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN
+ * 	0031 DIGIT ONE
+ * 	0033 DIGIT THREE
+ * 	65E5 ??
+ * 33ED IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN
+ * 	0031 DIGIT ONE
+ * 	0034 DIGIT FOUR
+ * 	65E5 ??
+ * 33EE IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN
+ * 	0031 DIGIT ONE
+ * 	0035 DIGIT FIVE
+ * 	65E5 ??
+ * 33EF IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN
+ * 	0031 DIGIT ONE
+ * 	0036 DIGIT SIX
+ * 	65E5 ??
+ * 33F0 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN
+ * 	0031 DIGIT ONE
+ * 	0037 DIGIT SEVEN
+ * 	65E5 ??
+ * 33F1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN
+ * 	0031 DIGIT ONE
+ * 	0038 DIGIT EIGHT
+ * 	65E5 ??
+ * 33F2 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN
+ * 	0031 DIGIT ONE
+ * 	0039 DIGIT NINE
+ * 	65E5 ??
+ * 33F3 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY
+ * 	0032 DIGIT TWO
+ * 	0030 DIGIT ZERO
+ * 	65E5 ??
+ * 33F4 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE
+ * 	0032 DIGIT TWO
+ * 	0031 DIGIT ONE
+ * 	65E5 ??
+ * 33F5 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO
+ * 	0032 DIGIT TWO
+ * 	0032 DIGIT TWO
+ * 	65E5 ??
+ * 33F6 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE
+ * 	0032 DIGIT TWO
+ * 	0033 DIGIT THREE
+ * 	65E5 ??
+ * 33F7 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR
+ * 	0032 DIGIT TWO
+ * 	0034 DIGIT FOUR
+ * 	65E5 ??
+ * 33F8 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE
+ * 	0032 DIGIT TWO
+ * 	0035 DIGIT FIVE
+ * 	65E5 ??
+ * 33F9 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX
+ * 	0032 DIGIT TWO
+ * 	0036 DIGIT SIX
+ * 	65E5 ??
+ * 33FA IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN
+ * 	0032 DIGIT TWO
+ * 	0037 DIGIT SEVEN
+ * 	65E5 ??
+ * 33FB IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT
+ * 	0032 DIGIT TWO
+ * 	0038 DIGIT EIGHT
+ * 	65E5 ??
+ * 33FC IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE
+ * 	0032 DIGIT TWO
+ * 	0039 DIGIT NINE
+ * 	65E5 ??
+ * 33FD IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY
+ * 	0033 DIGIT THREE
+ * 	0030 DIGIT ZERO
+ * 	65E5 ??
+ * 33FE IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE
+ * 	0033 DIGIT THREE
+ * 	0031 DIGIT ONE
+ * 	65E5 ??
+ * F900 CJK COMPATIBILITY IDEOGRAPH-F900
+ * 	8C48 ??
+ * F901 CJK COMPATIBILITY IDEOGRAPH-F901
+ * 	66F4 ??
+ * F902 CJK COMPATIBILITY IDEOGRAPH-F902
+ * 	8ECA ??
+ * F903 CJK COMPATIBILITY IDEOGRAPH-F903
+ * 	8CC8 ??
+ * F904 CJK COMPATIBILITY IDEOGRAPH-F904
+ * 	6ED1 ??
+ * F905 CJK COMPATIBILITY IDEOGRAPH-F905
+ * 	4E32 ??
+ * F906 CJK COMPATIBILITY IDEOGRAPH-F906
+ * 	53E5 ??
+ * F907 CJK COMPATIBILITY IDEOGRAPH-F907
+ * 	9F9C ??
+ * F908 CJK COMPATIBILITY IDEOGRAPH-F908
+ * 	9F9C ??
+ * F909 CJK COMPATIBILITY IDEOGRAPH-F909
+ * 	5951 ??
+ * F90A CJK COMPATIBILITY IDEOGRAPH-F90A
+ * 	91D1 ??
+ * F90B CJK COMPATIBILITY IDEOGRAPH-F90B
+ * 	5587 ??
+ * F90C CJK COMPATIBILITY IDEOGRAPH-F90C
+ * 	5948 ??
+ * F90D CJK COMPATIBILITY IDEOGRAPH-F90D
+ * 	61F6 ??
+ * F90E CJK COMPATIBILITY IDEOGRAPH-F90E
+ * 	7669 ??
+ * F90F CJK COMPATIBILITY IDEOGRAPH-F90F
+ * 	7F85 ??
+ * F910 CJK COMPATIBILITY IDEOGRAPH-F910
+ * 	863F ??
+ * F911 CJK COMPATIBILITY IDEOGRAPH-F911
+ * 	87BA ??
+ * F912 CJK COMPATIBILITY IDEOGRAPH-F912
+ * 	88F8 ??
+ * F913 CJK COMPATIBILITY IDEOGRAPH-F913
+ * 	908F ??
+ * F914 CJK COMPATIBILITY IDEOGRAPH-F914
+ * 	6A02 ??
+ * F915 CJK COMPATIBILITY IDEOGRAPH-F915
+ * 	6D1B ??
+ * F916 CJK COMPATIBILITY IDEOGRAPH-F916
+ * 	70D9 ??
+ * F917 CJK COMPATIBILITY IDEOGRAPH-F917
+ * 	73DE ??
+ * F918 CJK COMPATIBILITY IDEOGRAPH-F918
+ * 	843D ??
+ * F919 CJK COMPATIBILITY IDEOGRAPH-F919
+ * 	916A ??
+ * F91A CJK COMPATIBILITY IDEOGRAPH-F91A
+ * 	99F1 ??
+ * F91B CJK COMPATIBILITY IDEOGRAPH-F91B
+ * 	4E82 ??
+ * F91C CJK COMPATIBILITY IDEOGRAPH-F91C
+ * 	5375 ??
+ * F91D CJK COMPATIBILITY IDEOGRAPH-F91D
+ * 	6B04 ??
+ * F91E CJK COMPATIBILITY IDEOGRAPH-F91E
+ * 	721B ??
+ * F91F CJK COMPATIBILITY IDEOGRAPH-F91F
+ * 	862D ??
+ * F920 CJK COMPATIBILITY IDEOGRAPH-F920
+ * 	9E1E ??
+ * F921 CJK COMPATIBILITY IDEOGRAPH-F921
+ * 	5D50 ??
+ * F922 CJK COMPATIBILITY IDEOGRAPH-F922
+ * 	6FEB ??
+ * F923 CJK COMPATIBILITY IDEOGRAPH-F923
+ * 	85CD ??
+ * F924 CJK COMPATIBILITY IDEOGRAPH-F924
+ * 	8964 ??
+ * F925 CJK COMPATIBILITY IDEOGRAPH-F925
+ * 	62C9 ??
+ * F926 CJK COMPATIBILITY IDEOGRAPH-F926
+ * 	81D8 ??
+ * F927 CJK COMPATIBILITY IDEOGRAPH-F927
+ * 	881F ??
+ * F928 CJK COMPATIBILITY IDEOGRAPH-F928
+ * 	5ECA ??
+ * F929 CJK COMPATIBILITY IDEOGRAPH-F929
+ * 	6717 ??
+ * F92A CJK COMPATIBILITY IDEOGRAPH-F92A
+ * 	6D6A ??
+ * F92B CJK COMPATIBILITY IDEOGRAPH-F92B
+ * 	72FC ??
+ * F92C CJK COMPATIBILITY IDEOGRAPH-F92C
+ * 	90CE ??
+ * F92D CJK COMPATIBILITY IDEOGRAPH-F92D
+ * 	4F86 ??
+ * F92E CJK COMPATIBILITY IDEOGRAPH-F92E
+ * 	51B7 ??
+ * F92F CJK COMPATIBILITY IDEOGRAPH-F92F
+ * 	52DE ??
+ * F930 CJK COMPATIBILITY IDEOGRAPH-F930
+ * 	64C4 ??
+ * F931 CJK COMPATIBILITY IDEOGRAPH-F931
+ * 	6AD3 ??
+ * F932 CJK COMPATIBILITY IDEOGRAPH-F932
+ * 	7210 ??
+ * F933 CJK COMPATIBILITY IDEOGRAPH-F933
+ * 	76E7 ??
+ * F934 CJK COMPATIBILITY IDEOGRAPH-F934
+ * 	8001 ??
+ * F935 CJK COMPATIBILITY IDEOGRAPH-F935
+ * 	8606 ??
+ * F936 CJK COMPATIBILITY IDEOGRAPH-F936
+ * 	865C ??
+ * F937 CJK COMPATIBILITY IDEOGRAPH-F937
+ * 	8DEF ??
+ * F938 CJK COMPATIBILITY IDEOGRAPH-F938
+ * 	9732 ??
+ * F939 CJK COMPATIBILITY IDEOGRAPH-F939
+ * 	9B6F ??
+ * F93A CJK COMPATIBILITY IDEOGRAPH-F93A
+ * 	9DFA ??
+ * F93B CJK COMPATIBILITY IDEOGRAPH-F93B
+ * 	788C ??
+ * F93C CJK COMPATIBILITY IDEOGRAPH-F93C
+ * 	797F ??
+ * F93D CJK COMPATIBILITY IDEOGRAPH-F93D
+ * 	7DA0 ??
+ * F93E CJK COMPATIBILITY IDEOGRAPH-F93E
+ * 	83C9 ??
+ * F93F CJK COMPATIBILITY IDEOGRAPH-F93F
+ * 	9304 ??
+ * F940 CJK COMPATIBILITY IDEOGRAPH-F940
+ * 	9E7F ??
+ * F941 CJK COMPATIBILITY IDEOGRAPH-F941
+ * 	8AD6 ??
+ * F942 CJK COMPATIBILITY IDEOGRAPH-F942
+ * 	58DF ??
+ * F943 CJK COMPATIBILITY IDEOGRAPH-F943
+ * 	5F04 ??
+ * F944 CJK COMPATIBILITY IDEOGRAPH-F944
+ * 	7C60 ??
+ * F945 CJK COMPATIBILITY IDEOGRAPH-F945
+ * 	807E ??
+ * F946 CJK COMPATIBILITY IDEOGRAPH-F946
+ * 	7262 ??
+ * F947 CJK COMPATIBILITY IDEOGRAPH-F947
+ * 	78CA ??
+ * F948 CJK COMPATIBILITY IDEOGRAPH-F948
+ * 	8CC2 ??
+ * F949 CJK COMPATIBILITY IDEOGRAPH-F949
+ * 	96F7 ??
+ * F94A CJK COMPATIBILITY IDEOGRAPH-F94A
+ * 	58D8 ??
+ * F94B CJK COMPATIBILITY IDEOGRAPH-F94B
+ * 	5C62 ??
+ * F94C CJK COMPATIBILITY IDEOGRAPH-F94C
+ * 	6A13 ??
+ * F94D CJK COMPATIBILITY IDEOGRAPH-F94D
+ * 	6DDA ??
+ * F94E CJK COMPATIBILITY IDEOGRAPH-F94E
+ * 	6F0F ??
+ * F94F CJK COMPATIBILITY IDEOGRAPH-F94F
+ * 	7D2F ??
+ * F950 CJK COMPATIBILITY IDEOGRAPH-F950
+ * 	7E37 ??
+ * F951 CJK COMPATIBILITY IDEOGRAPH-F951
+ * 	964B ??
+ * F952 CJK COMPATIBILITY IDEOGRAPH-F952
+ * 	52D2 ??
+ * F953 CJK COMPATIBILITY IDEOGRAPH-F953
+ * 	808B ??
+ * F954 CJK COMPATIBILITY IDEOGRAPH-F954
+ * 	51DC ??
+ * F955 CJK COMPATIBILITY IDEOGRAPH-F955
+ * 	51CC ??
+ * F956 CJK COMPATIBILITY IDEOGRAPH-F956
+ * 	7A1C ??
+ * F957 CJK COMPATIBILITY IDEOGRAPH-F957
+ * 	7DBE ??
+ * F958 CJK COMPATIBILITY IDEOGRAPH-F958
+ * 	83F1 ??
+ * F959 CJK COMPATIBILITY IDEOGRAPH-F959
+ * 	9675 ??
+ * F95A CJK COMPATIBILITY IDEOGRAPH-F95A
+ * 	8B80 ??
+ * F95B CJK COMPATIBILITY IDEOGRAPH-F95B
+ * 	62CF ??
+ * F95C CJK COMPATIBILITY IDEOGRAPH-F95C
+ * 	6A02 ??
+ * F95D CJK COMPATIBILITY IDEOGRAPH-F95D
+ * 	8AFE ??
+ * F95E CJK COMPATIBILITY IDEOGRAPH-F95E
+ * 	4E39 ??
+ * F95F CJK COMPATIBILITY IDEOGRAPH-F95F
+ * 	5BE7 ??
+ * F960 CJK COMPATIBILITY IDEOGRAPH-F960
+ * 	6012 ??
+ * F961 CJK COMPATIBILITY IDEOGRAPH-F961
+ * 	7387 ??
+ * F962 CJK COMPATIBILITY IDEOGRAPH-F962
+ * 	7570 ??
+ * F963 CJK COMPATIBILITY IDEOGRAPH-F963
+ * 	5317 ??
+ * F964 CJK COMPATIBILITY IDEOGRAPH-F964
+ * 	78FB ??
+ * F965 CJK COMPATIBILITY IDEOGRAPH-F965
+ * 	4FBF ??
+ * F966 CJK COMPATIBILITY IDEOGRAPH-F966
+ * 	5FA9 ??
+ * F967 CJK COMPATIBILITY IDEOGRAPH-F967
+ * 	4E0D ??
+ * F968 CJK COMPATIBILITY IDEOGRAPH-F968
+ * 	6CCC ??
+ * F969 CJK COMPATIBILITY IDEOGRAPH-F969
+ * 	6578 ??
+ * F96A CJK COMPATIBILITY IDEOGRAPH-F96A
+ * 	7D22 ??
+ * F96B CJK COMPATIBILITY IDEOGRAPH-F96B
+ * 	53C3 ??
+ * F96C CJK COMPATIBILITY IDEOGRAPH-F96C
+ * 	585E ??
+ * F96D CJK COMPATIBILITY IDEOGRAPH-F96D
+ * 	7701 ??
+ * F96E CJK COMPATIBILITY IDEOGRAPH-F96E
+ * 	8449 ??
+ * F96F CJK COMPATIBILITY IDEOGRAPH-F96F
+ * 	8AAA ??
+ * F970 CJK COMPATIBILITY IDEOGRAPH-F970
+ * 	6BBA ??
+ * F971 CJK COMPATIBILITY IDEOGRAPH-F971
+ * 	8FB0 ??
+ * F972 CJK COMPATIBILITY IDEOGRAPH-F972
+ * 	6C88 ??
+ * F973 CJK COMPATIBILITY IDEOGRAPH-F973
+ * 	62FE ??
+ * F974 CJK COMPATIBILITY IDEOGRAPH-F974
+ * 	82E5 ??
+ * F975 CJK COMPATIBILITY IDEOGRAPH-F975
+ * 	63A0 ??
+ * F976 CJK COMPATIBILITY IDEOGRAPH-F976
+ * 	7565 ??
+ * F977 CJK COMPATIBILITY IDEOGRAPH-F977
+ * 	4EAE ??
+ * F978 CJK COMPATIBILITY IDEOGRAPH-F978
+ * 	5169 ??
+ * F979 CJK COMPATIBILITY IDEOGRAPH-F979
+ * 	51C9 ??
+ * F97A CJK COMPATIBILITY IDEOGRAPH-F97A
+ * 	6881 ??
+ * F97B CJK COMPATIBILITY IDEOGRAPH-F97B
+ * 	7CE7 ??
+ * F97C CJK COMPATIBILITY IDEOGRAPH-F97C
+ * 	826F ??
+ * F97D CJK COMPATIBILITY IDEOGRAPH-F97D
+ * 	8AD2 ??
+ * F97E CJK COMPATIBILITY IDEOGRAPH-F97E
+ * 	91CF ??
+ * F97F CJK COMPATIBILITY IDEOGRAPH-F97F
+ * 	52F5 ??
+ * F980 CJK COMPATIBILITY IDEOGRAPH-F980
+ * 	5442 ??
+ * F981 CJK COMPATIBILITY IDEOGRAPH-F981
+ * 	5973 ??
+ * F982 CJK COMPATIBILITY IDEOGRAPH-F982
+ * 	5EEC ??
+ * F983 CJK COMPATIBILITY IDEOGRAPH-F983
+ * 	65C5 ??
+ * F984 CJK COMPATIBILITY IDEOGRAPH-F984
+ * 	6FFE ??
+ * F985 CJK COMPATIBILITY IDEOGRAPH-F985
+ * 	792A ??
+ * F986 CJK COMPATIBILITY IDEOGRAPH-F986
+ * 	95AD ??
+ * F987 CJK COMPATIBILITY IDEOGRAPH-F987
+ * 	9A6A ??
+ * F988 CJK COMPATIBILITY IDEOGRAPH-F988
+ * 	9E97 ??
+ * F989 CJK COMPATIBILITY IDEOGRAPH-F989
+ * 	9ECE ??
+ * F98A CJK COMPATIBILITY IDEOGRAPH-F98A
+ * 	529B ??
+ * F98B CJK COMPATIBILITY IDEOGRAPH-F98B
+ * 	66C6 ??
+ * F98C CJK COMPATIBILITY IDEOGRAPH-F98C
+ * 	6B77 ??
+ * F98D CJK COMPATIBILITY IDEOGRAPH-F98D
+ * 	8F62 ??
+ * F98E CJK COMPATIBILITY IDEOGRAPH-F98E
+ * 	5E74 ??
+ * F98F CJK COMPATIBILITY IDEOGRAPH-F98F
+ * 	6190 ??
+ * F990 CJK COMPATIBILITY IDEOGRAPH-F990
+ * 	6200 ??
+ * F991 CJK COMPATIBILITY IDEOGRAPH-F991
+ * 	649A ??
+ * F992 CJK COMPATIBILITY IDEOGRAPH-F992
+ * 	6F23 ??
+ * F993 CJK COMPATIBILITY IDEOGRAPH-F993
+ * 	7149 ??
+ * F994 CJK COMPATIBILITY IDEOGRAPH-F994
+ * 	7489 ??
+ * F995 CJK COMPATIBILITY IDEOGRAPH-F995
+ * 	79CA ??
+ * F996 CJK COMPATIBILITY IDEOGRAPH-F996
+ * 	7DF4 ??
+ * F997 CJK COMPATIBILITY IDEOGRAPH-F997
+ * 	806F ??
+ * F998 CJK COMPATIBILITY IDEOGRAPH-F998
+ * 	8F26 ??
+ * F999 CJK COMPATIBILITY IDEOGRAPH-F999
+ * 	84EE ??
+ * F99A CJK COMPATIBILITY IDEOGRAPH-F99A
+ * 	9023 ??
+ * F99B CJK COMPATIBILITY IDEOGRAPH-F99B
+ * 	934A ??
+ * F99C CJK COMPATIBILITY IDEOGRAPH-F99C
+ * 	5217 ??
+ * F99D CJK COMPATIBILITY IDEOGRAPH-F99D
+ * 	52A3 ??
+ * F99E CJK COMPATIBILITY IDEOGRAPH-F99E
+ * 	54BD ??
+ * F99F CJK COMPATIBILITY IDEOGRAPH-F99F
+ * 	70C8 ??
+ * F9A0 CJK COMPATIBILITY IDEOGRAPH-F9A0
+ * 	88C2 ??
+ * F9A1 CJK COMPATIBILITY IDEOGRAPH-F9A1
+ * 	8AAA ??
+ * F9A2 CJK COMPATIBILITY IDEOGRAPH-F9A2
+ * 	5EC9 ??
+ * F9A3 CJK COMPATIBILITY IDEOGRAPH-F9A3
+ * 	5FF5 ??
+ * F9A4 CJK COMPATIBILITY IDEOGRAPH-F9A4
+ * 	637B ??
+ * F9A5 CJK COMPATIBILITY IDEOGRAPH-F9A5
+ * 	6BAE ??
+ * F9A6 CJK COMPATIBILITY IDEOGRAPH-F9A6
+ * 	7C3E ??
+ * F9A7 CJK COMPATIBILITY IDEOGRAPH-F9A7
+ * 	7375 ??
+ * F9A8 CJK COMPATIBILITY IDEOGRAPH-F9A8
+ * 	4EE4 ??
+ * F9A9 CJK COMPATIBILITY IDEOGRAPH-F9A9
+ * 	56F9 ??
+ * F9AA CJK COMPATIBILITY IDEOGRAPH-F9AA
+ * 	5BE7 ??
+ * F9AB CJK COMPATIBILITY IDEOGRAPH-F9AB
+ * 	5DBA ??
+ * F9AC CJK COMPATIBILITY IDEOGRAPH-F9AC
+ * 	601C ??
+ * F9AD CJK COMPATIBILITY IDEOGRAPH-F9AD
+ * 	73B2 ??
+ * F9AE CJK COMPATIBILITY IDEOGRAPH-F9AE
+ * 	7469 ??
+ * F9AF CJK COMPATIBILITY IDEOGRAPH-F9AF
+ * 	7F9A ??
+ * F9B0 CJK COMPATIBILITY IDEOGRAPH-F9B0
+ * 	8046 ??
+ * F9B1 CJK COMPATIBILITY IDEOGRAPH-F9B1
+ * 	9234 ??
+ * F9B2 CJK COMPATIBILITY IDEOGRAPH-F9B2
+ * 	96F6 ??
+ * F9B3 CJK COMPATIBILITY IDEOGRAPH-F9B3
+ * 	9748 ??
+ * F9B4 CJK COMPATIBILITY IDEOGRAPH-F9B4
+ * 	9818 ??
+ * F9B5 CJK COMPATIBILITY IDEOGRAPH-F9B5
+ * 	4F8B ??
+ * F9B6 CJK COMPATIBILITY IDEOGRAPH-F9B6
+ * 	79AE ??
+ * F9B7 CJK COMPATIBILITY IDEOGRAPH-F9B7
+ * 	91B4 ??
+ * F9B8 CJK COMPATIBILITY IDEOGRAPH-F9B8
+ * 	96B8 ??
+ * F9B9 CJK COMPATIBILITY IDEOGRAPH-F9B9
+ * 	60E1 ??
+ * F9BA CJK COMPATIBILITY IDEOGRAPH-F9BA
+ * 	4E86 ??
+ * F9BB CJK COMPATIBILITY IDEOGRAPH-F9BB
+ * 	50DA ??
+ * F9BC CJK COMPATIBILITY IDEOGRAPH-F9BC
+ * 	5BEE ??
+ * F9BD CJK COMPATIBILITY IDEOGRAPH-F9BD
+ * 	5C3F ??
+ * F9BE CJK COMPATIBILITY IDEOGRAPH-F9BE
+ * 	6599 ??
+ * F9BF CJK COMPATIBILITY IDEOGRAPH-F9BF
+ * 	6A02 ??
+ * F9C0 CJK COMPATIBILITY IDEOGRAPH-F9C0
+ * 	71CE ??
+ * F9C1 CJK COMPATIBILITY IDEOGRAPH-F9C1
+ * 	7642 ??
+ * F9C2 CJK COMPATIBILITY IDEOGRAPH-F9C2
+ * 	84FC ??
+ * F9C3 CJK COMPATIBILITY IDEOGRAPH-F9C3
+ * 	907C ??
+ * F9C4 CJK COMPATIBILITY IDEOGRAPH-F9C4
+ * 	9F8D ??
+ * F9C5 CJK COMPATIBILITY IDEOGRAPH-F9C5
+ * 	6688 ??
+ * F9C6 CJK COMPATIBILITY IDEOGRAPH-F9C6
+ * 	962E ??
+ * F9C7 CJK COMPATIBILITY IDEOGRAPH-F9C7
+ * 	5289 ??
+ * F9C8 CJK COMPATIBILITY IDEOGRAPH-F9C8
+ * 	677B ??
+ * F9C9 CJK COMPATIBILITY IDEOGRAPH-F9C9
+ * 	67F3 ??
+ * F9CA CJK COMPATIBILITY IDEOGRAPH-F9CA
+ * 	6D41 ??
+ * F9CB CJK COMPATIBILITY IDEOGRAPH-F9CB
+ * 	6E9C ??
+ * F9CC CJK COMPATIBILITY IDEOGRAPH-F9CC
+ * 	7409 ??
+ * F9CD CJK COMPATIBILITY IDEOGRAPH-F9CD
+ * 	7559 ??
+ * F9CE CJK COMPATIBILITY IDEOGRAPH-F9CE
+ * 	786B ??
+ * F9CF CJK COMPATIBILITY IDEOGRAPH-F9CF
+ * 	7D10 ??
+ * F9D0 CJK COMPATIBILITY IDEOGRAPH-F9D0
+ * 	985E ??
+ * F9D1 CJK COMPATIBILITY IDEOGRAPH-F9D1
+ * 	516D ??
+ * F9D2 CJK COMPATIBILITY IDEOGRAPH-F9D2
+ * 	622E ??
+ * F9D3 CJK COMPATIBILITY IDEOGRAPH-F9D3
+ * 	9678 ??
+ * F9D4 CJK COMPATIBILITY IDEOGRAPH-F9D4
+ * 	502B ??
+ * F9D5 CJK COMPATIBILITY IDEOGRAPH-F9D5
+ * 	5D19 ??
+ * F9D6 CJK COMPATIBILITY IDEOGRAPH-F9D6
+ * 	6DEA ??
+ * F9D7 CJK COMPATIBILITY IDEOGRAPH-F9D7
+ * 	8F2A ??
+ * F9D8 CJK COMPATIBILITY IDEOGRAPH-F9D8
+ * 	5F8B ??
+ * F9D9 CJK COMPATIBILITY IDEOGRAPH-F9D9
+ * 	6144 ??
+ * F9DA CJK COMPATIBILITY IDEOGRAPH-F9DA
+ * 	6817 ??
+ * F9DB CJK COMPATIBILITY IDEOGRAPH-F9DB
+ * 	7387 ??
+ * F9DC CJK COMPATIBILITY IDEOGRAPH-F9DC
+ * 	9686 ??
+ * F9DD CJK COMPATIBILITY IDEOGRAPH-F9DD
+ * 	5229 ??
+ * F9DE CJK COMPATIBILITY IDEOGRAPH-F9DE
+ * 	540F ??
+ * F9DF CJK COMPATIBILITY IDEOGRAPH-F9DF
+ * 	5C65 ??
+ * F9E0 CJK COMPATIBILITY IDEOGRAPH-F9E0
+ * 	6613 ??
+ * F9E1 CJK COMPATIBILITY IDEOGRAPH-F9E1
+ * 	674E ??
+ * F9E2 CJK COMPATIBILITY IDEOGRAPH-F9E2
+ * 	68A8 ??
+ * F9E3 CJK COMPATIBILITY IDEOGRAPH-F9E3
+ * 	6CE5 ??
+ * F9E4 CJK COMPATIBILITY IDEOGRAPH-F9E4
+ * 	7406 ??
+ * F9E5 CJK COMPATIBILITY IDEOGRAPH-F9E5
+ * 	75E2 ??
+ * F9E6 CJK COMPATIBILITY IDEOGRAPH-F9E6
+ * 	7F79 ??
+ * F9E7 CJK COMPATIBILITY IDEOGRAPH-F9E7
+ * 	88CF ??
+ * F9E8 CJK COMPATIBILITY IDEOGRAPH-F9E8
+ * 	88E1 ??
+ * F9E9 CJK COMPATIBILITY IDEOGRAPH-F9E9
+ * 	91CC ??
+ * F9EA CJK COMPATIBILITY IDEOGRAPH-F9EA
+ * 	96E2 ??
+ * F9EB CJK COMPATIBILITY IDEOGRAPH-F9EB
+ * 	533F ??
+ * F9EC CJK COMPATIBILITY IDEOGRAPH-F9EC
+ * 	6EBA ??
+ * F9ED CJK COMPATIBILITY IDEOGRAPH-F9ED
+ * 	541D ??
+ * F9EE CJK COMPATIBILITY IDEOGRAPH-F9EE
+ * 	71D0 ??
+ * F9EF CJK COMPATIBILITY IDEOGRAPH-F9EF
+ * 	7498 ??
+ * F9F0 CJK COMPATIBILITY IDEOGRAPH-F9F0
+ * 	85FA ??
+ * F9F1 CJK COMPATIBILITY IDEOGRAPH-F9F1
+ * 	96A3 ??
+ * F9F2 CJK COMPATIBILITY IDEOGRAPH-F9F2
+ * 	9C57 ??
+ * F9F3 CJK COMPATIBILITY IDEOGRAPH-F9F3
+ * 	9E9F ??
+ * F9F4 CJK COMPATIBILITY IDEOGRAPH-F9F4
+ * 	6797 ??
+ * F9F5 CJK COMPATIBILITY IDEOGRAPH-F9F5
+ * 	6DCB ??
+ * F9F6 CJK COMPATIBILITY IDEOGRAPH-F9F6
+ * 	81E8 ??
+ * F9F7 CJK COMPATIBILITY IDEOGRAPH-F9F7
+ * 	7ACB ??
+ * F9F8 CJK COMPATIBILITY IDEOGRAPH-F9F8
+ * 	7B20 ??
+ * F9F9 CJK COMPATIBILITY IDEOGRAPH-F9F9
+ * 	7C92 ??
+ * F9FA CJK COMPATIBILITY IDEOGRAPH-F9FA
+ * 	72C0 ??
+ * F9FB CJK COMPATIBILITY IDEOGRAPH-F9FB
+ * 	7099 ??
+ * F9FC CJK COMPATIBILITY IDEOGRAPH-F9FC
+ * 	8B58 ??
+ * F9FD CJK COMPATIBILITY IDEOGRAPH-F9FD
+ * 	4EC0 ??
+ * F9FE CJK COMPATIBILITY IDEOGRAPH-F9FE
+ * 	8336 ??
+ * F9FF CJK COMPATIBILITY IDEOGRAPH-F9FF
+ * 	523A ??
+ * FA00 CJK COMPATIBILITY IDEOGRAPH-FA00
+ * 	5207 ??
+ * FA01 CJK COMPATIBILITY IDEOGRAPH-FA01
+ * 	5EA6 ??
+ * FA02 CJK COMPATIBILITY IDEOGRAPH-FA02
+ * 	62D3 ??
+ * FA03 CJK COMPATIBILITY IDEOGRAPH-FA03
+ * 	7CD6 ??
+ * FA04 CJK COMPATIBILITY IDEOGRAPH-FA04
+ * 	5B85 ??
+ * FA05 CJK COMPATIBILITY IDEOGRAPH-FA05
+ * 	6D1E ??
+ * FA06 CJK COMPATIBILITY IDEOGRAPH-FA06
+ * 	66B4 ??
+ * FA07 CJK COMPATIBILITY IDEOGRAPH-FA07
+ * 	8F3B ??
+ * FA08 CJK COMPATIBILITY IDEOGRAPH-FA08
+ * 	884C ??
+ * FA09 CJK COMPATIBILITY IDEOGRAPH-FA09
+ * 	964D ??
+ * FA0A CJK COMPATIBILITY IDEOGRAPH-FA0A
+ * 	898B ??
+ * FA0B CJK COMPATIBILITY IDEOGRAPH-FA0B
+ * 	5ED3 ??
+ * FA0C CJK COMPATIBILITY IDEOGRAPH-FA0C
+ * 	5140 ??
+ * FA0D CJK COMPATIBILITY IDEOGRAPH-FA0D
+ * 	55C0 ??
+ * FA10 CJK COMPATIBILITY IDEOGRAPH-FA10
+ * 	585A ??
+ * FA12 CJK COMPATIBILITY IDEOGRAPH-FA12
+ * 	6674 ??
+ * FA15 CJK COMPATIBILITY IDEOGRAPH-FA15
+ * 	51DE ??
+ * FA16 CJK COMPATIBILITY IDEOGRAPH-FA16
+ * 	732A ??
+ * FA17 CJK COMPATIBILITY IDEOGRAPH-FA17
+ * 	76CA ??
+ * FA18 CJK COMPATIBILITY IDEOGRAPH-FA18
+ * 	793C ??
+ * FA19 CJK COMPATIBILITY IDEOGRAPH-FA19
+ * 	795E ??
+ * FA1A CJK COMPATIBILITY IDEOGRAPH-FA1A
+ * 	7965 ??
+ * FA1B CJK COMPATIBILITY IDEOGRAPH-FA1B
+ * 	798F ??
+ * FA1C CJK COMPATIBILITY IDEOGRAPH-FA1C
+ * 	9756 ??
+ * FA1D CJK COMPATIBILITY IDEOGRAPH-FA1D
+ * 	7CBE ??
+ * FA1E CJK COMPATIBILITY IDEOGRAPH-FA1E
+ * 	7FBD ??
+ * FA20 CJK COMPATIBILITY IDEOGRAPH-FA20
+ * 	8612 ??
+ * FA22 CJK COMPATIBILITY IDEOGRAPH-FA22
+ * 	8AF8 ??
+ * FA25 CJK COMPATIBILITY IDEOGRAPH-FA25
+ * 	9038 ??
+ * FA26 CJK COMPATIBILITY IDEOGRAPH-FA26
+ * 	90FD ??
+ * FA2A CJK COMPATIBILITY IDEOGRAPH-FA2A
+ * 	98EF ??
+ * FA2B CJK COMPATIBILITY IDEOGRAPH-FA2B
+ * 	98FC ??
+ * FA2C CJK COMPATIBILITY IDEOGRAPH-FA2C
+ * 	9928 ??
+ * FA2D CJK COMPATIBILITY IDEOGRAPH-FA2D
+ * 	9DB4 ??
+ * FA30 CJK COMPATIBILITY IDEOGRAPH-FA30
+ * 	4FAE ??
+ * FA31 CJK COMPATIBILITY IDEOGRAPH-FA31
+ * 	50E7 ??
+ * FA32 CJK COMPATIBILITY IDEOGRAPH-FA32
+ * 	514D ??
+ * FA33 CJK COMPATIBILITY IDEOGRAPH-FA33
+ * 	52C9 ??
+ * FA34 CJK COMPATIBILITY IDEOGRAPH-FA34
+ * 	52E4 ??
+ * FA35 CJK COMPATIBILITY IDEOGRAPH-FA35
+ * 	5351 ??
+ * FA36 CJK COMPATIBILITY IDEOGRAPH-FA36
+ * 	559D ??
+ * FA37 CJK COMPATIBILITY IDEOGRAPH-FA37
+ * 	5606 ??
+ * FA38 CJK COMPATIBILITY IDEOGRAPH-FA38
+ * 	5668 ??
+ * FA39 CJK COMPATIBILITY IDEOGRAPH-FA39
+ * 	5840 ??
+ * FA3A CJK COMPATIBILITY IDEOGRAPH-FA3A
+ * 	58A8 ??
+ * FA3B CJK COMPATIBILITY IDEOGRAPH-FA3B
+ * 	5C64 ??
+ * FA3C CJK COMPATIBILITY IDEOGRAPH-FA3C
+ * 	5C6E ??
+ * FA3D CJK COMPATIBILITY IDEOGRAPH-FA3D
+ * 	6094 ??
+ * FA3E CJK COMPATIBILITY IDEOGRAPH-FA3E
+ * 	6168 ??
+ * FA3F CJK COMPATIBILITY IDEOGRAPH-FA3F
+ * 	618E ??
+ * FA40 CJK COMPATIBILITY IDEOGRAPH-FA40
+ * 	61F2 ??
+ * FA41 CJK COMPATIBILITY IDEOGRAPH-FA41
+ * 	654F ??
+ * FA42 CJK COMPATIBILITY IDEOGRAPH-FA42
+ * 	65E2 ??
+ * FA43 CJK COMPATIBILITY IDEOGRAPH-FA43
+ * 	6691 ??
+ * FA44 CJK COMPATIBILITY IDEOGRAPH-FA44
+ * 	6885 ??
+ * FA45 CJK COMPATIBILITY IDEOGRAPH-FA45
+ * 	6D77 ??
+ * FA46 CJK COMPATIBILITY IDEOGRAPH-FA46
+ * 	6E1A ??
+ * FA47 CJK COMPATIBILITY IDEOGRAPH-FA47
+ * 	6F22 ??
+ * FA48 CJK COMPATIBILITY IDEOGRAPH-FA48
+ * 	716E ??
+ * FA49 CJK COMPATIBILITY IDEOGRAPH-FA49
+ * 	722B ??
+ * FA4A CJK COMPATIBILITY IDEOGRAPH-FA4A
+ * 	7422 ??
+ * FA4B CJK COMPATIBILITY IDEOGRAPH-FA4B
+ * 	7891 ??
+ * FA4C CJK COMPATIBILITY IDEOGRAPH-FA4C
+ * 	793E ??
+ * FA4D CJK COMPATIBILITY IDEOGRAPH-FA4D
+ * 	7949 ??
+ * FA4E CJK COMPATIBILITY IDEOGRAPH-FA4E
+ * 	7948 ??
+ * FA4F CJK COMPATIBILITY IDEOGRAPH-FA4F
+ * 	7950 ??
+ * FA50 CJK COMPATIBILITY IDEOGRAPH-FA50
+ * 	7956 ??
+ * FA51 CJK COMPATIBILITY IDEOGRAPH-FA51
+ * 	795D ??
+ * FA52 CJK COMPATIBILITY IDEOGRAPH-FA52
+ * 	798D ??
+ * FA53 CJK COMPATIBILITY IDEOGRAPH-FA53
+ * 	798E ??
+ * FA54 CJK COMPATIBILITY IDEOGRAPH-FA54
+ * 	7A40 ??
+ * FA55 CJK COMPATIBILITY IDEOGRAPH-FA55
+ * 	7A81 ??
+ * FA56 CJK COMPATIBILITY IDEOGRAPH-FA56
+ * 	7BC0 ??
+ * FA57 CJK COMPATIBILITY IDEOGRAPH-FA57
+ * 	7DF4 ??
+ * FA58 CJK COMPATIBILITY IDEOGRAPH-FA58
+ * 	7E09 ??
+ * FA59 CJK COMPATIBILITY IDEOGRAPH-FA59
+ * 	7E41 ??
+ * FA5A CJK COMPATIBILITY IDEOGRAPH-FA5A
+ * 	7F72 ??
+ * FA5B CJK COMPATIBILITY IDEOGRAPH-FA5B
+ * 	8005 ??
+ * FA5C CJK COMPATIBILITY IDEOGRAPH-FA5C
+ * 	81ED ??
+ * FA5D CJK COMPATIBILITY IDEOGRAPH-FA5D
+ * 	8279 ??
+ * FA5E CJK COMPATIBILITY IDEOGRAPH-FA5E
+ * 	8279 ??
+ * FA5F CJK COMPATIBILITY IDEOGRAPH-FA5F
+ * 	8457 ??
+ * FA60 CJK COMPATIBILITY IDEOGRAPH-FA60
+ * 	8910 ??
+ * FA61 CJK COMPATIBILITY IDEOGRAPH-FA61
+ * 	8996 ??
+ * FA62 CJK COMPATIBILITY IDEOGRAPH-FA62
+ * 	8B01 ??
+ * FA63 CJK COMPATIBILITY IDEOGRAPH-FA63
+ * 	8B39 ??
+ * FA64 CJK COMPATIBILITY IDEOGRAPH-FA64
+ * 	8CD3 ??
+ * FA65 CJK COMPATIBILITY IDEOGRAPH-FA65
+ * 	8D08 ??
+ * FA66 CJK COMPATIBILITY IDEOGRAPH-FA66
+ * 	8FB6 ??
+ * FA67 CJK COMPATIBILITY IDEOGRAPH-FA67
+ * 	9038 ??
+ * FA68 CJK COMPATIBILITY IDEOGRAPH-FA68
+ * 	96E3 ??
+ * FA69 CJK COMPATIBILITY IDEOGRAPH-FA69
+ * 	97FF ??
+ * FA6A CJK COMPATIBILITY IDEOGRAPH-FA6A
+ * 	983B ??
+ * FB00 LATIN SMALL LIGATURE FF
+ * 	0066 LATIN SMALL LETTER F
+ * 	0066 LATIN SMALL LETTER F
+ * FB01 LATIN SMALL LIGATURE FI
+ * 	0066 LATIN SMALL LETTER F
+ * 	0069 LATIN SMALL LETTER I
+ * FB02 LATIN SMALL LIGATURE FL
+ * 	0066 LATIN SMALL LETTER F
+ * 	006C LATIN SMALL LETTER L
+ * FB03 LATIN SMALL LIGATURE FFI
+ * 	0066 LATIN SMALL LETTER F
+ * 	0066 LATIN SMALL LETTER F
+ * 	0069 LATIN SMALL LETTER I
+ * FB04 LATIN SMALL LIGATURE FFL
+ * 	0066 LATIN SMALL LETTER F
+ * 	0066 LATIN SMALL LETTER F
+ * 	006C LATIN SMALL LETTER L
+ * FB05 LATIN SMALL LIGATURE LONG S T
+ * 	0074 LATIN SMALL LETTER T
+ * 	0073 LATIN SMALL LETTER S
+ * FB06 LATIN SMALL LIGATURE ST
+ * 	0073 LATIN SMALL LETTER S
+ * 	0074 LATIN SMALL LETTER T
+ * FB13 ARMENIAN SMALL LIGATURE MEN NOW
+ * 	0574 ARMENIAN SMALL LETTER MEN
+ * 	0576 ARMENIAN SMALL LETTER NOW
+ * FB14 ARMENIAN SMALL LIGATURE MEN ECH
+ * 	0574 ARMENIAN SMALL LETTER MEN
+ * 	0565 ARMENIAN SMALL LETTER ECH
+ * FB15 ARMENIAN SMALL LIGATURE MEN INI
+ * 	0574 ARMENIAN SMALL LETTER MEN
+ * 	056B ARMENIAN SMALL LETTER INI
+ * FB16 ARMENIAN SMALL LIGATURE VEW NOW
+ * 	057E ARMENIAN SMALL LETTER VEW
+ * 	0576 ARMENIAN SMALL LETTER NOW
+ * FB17 ARMENIAN SMALL LIGATURE MEN XEH
+ * 	0574 ARMENIAN SMALL LETTER MEN
+ * 	056D ARMENIAN SMALL LETTER XEH
+ * FB1D HEBREW LETTER YOD WITH HIRIQ
+ * 	05D9 HEBREW LETTER YOD
+ * FB1F HEBREW LIGATURE YIDDISH YOD YOD PATAH
+ * 	05F2 HEBREW LIGATURE YIDDISH DOUBLE YOD
+ * FB20 HEBREW LETTER ALTERNATIVE AYIN
+ * 	05E2 HEBREW LETTER AYIN
+ * FB21 HEBREW LETTER WIDE ALEF
+ * 	05D0 HEBREW LETTER ALEF
+ * FB22 HEBREW LETTER WIDE DALET
+ * 	05D3 HEBREW LETTER DALET
+ * FB23 HEBREW LETTER WIDE HE
+ * 	05D4 HEBREW LETTER HE
+ * FB24 HEBREW LETTER WIDE KAF
+ * 	05DB HEBREW LETTER KAF
+ * FB25 HEBREW LETTER WIDE LAMED
+ * 	05DC HEBREW LETTER LAMED
+ * FB26 HEBREW LETTER WIDE FINAL MEM
+ * 	05DD HEBREW LETTER FINAL MEM
+ * FB27 HEBREW LETTER WIDE RESH
+ * 	05E8 HEBREW LETTER RESH
+ * FB28 HEBREW LETTER WIDE TAV
+ * 	05EA HEBREW LETTER TAV
+ * FB29 HEBREW LETTER ALTERNATIVE PLUS SIGN
+ * 	002B PLUS SIGN
+ * FB2A HEBREW LETTER SHIN WITH SHIN DOT
+ * 	05E9 HEBREW LETTER SHIN
+ * FB2B HEBREW LETTER SHIN WITH SIN DOT
+ * 	05E9 HEBREW LETTER SHIN
+ * FB2C HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT
+ * 	05E9 HEBREW LETTER SHIN
+ * FB2D HEBREW LETTER SHIN WITH DAGESH AND SIN DOT
+ * 	05E9 HEBREW LETTER SHIN
+ * FB2E HEBREW LETTER ALEF WITH PATAH
+ * 	05D0 HEBREW LETTER ALEF
+ * FB2F HEBREW LETTER ALEF WITH QAMATS
+ * 	05D0 HEBREW LETTER ALEF
+ * FB30 HEBREW LETTER ALEF WITH MAPIQ
+ * 	05D0 HEBREW LETTER ALEF
+ * FB31 HEBREW LETTER BET WITH DAGESH
+ * 	05D1 HEBREW LETTER BET
+ * FB32 HEBREW LETTER GIMEL WITH DAGESH
+ * 	05D2 HEBREW LETTER GIMEL
+ * FB33 HEBREW LETTER DALET WITH DAGESH
+ * 	05D3 HEBREW LETTER DALET
+ * FB34 HEBREW LETTER HE WITH MAPIQ
+ * 	05D4 HEBREW LETTER HE
+ * FB35 HEBREW LETTER VAV WITH DAGESH
+ * 	05D5 HEBREW LETTER VAV
+ * FB36 HEBREW LETTER ZAYIN WITH DAGESH
+ * 	05D6 HEBREW LETTER ZAYIN
+ * FB38 HEBREW LETTER TET WITH DAGESH
+ * 	05D8 HEBREW LETTER TET
+ * FB39 HEBREW LETTER YOD WITH DAGESH
+ * 	05D9 HEBREW LETTER YOD
+ * FB3A HEBREW LETTER FINAL KAF WITH DAGESH
+ * 	05DA HEBREW LETTER FINAL KAF
+ * FB3B HEBREW LETTER KAF WITH DAGESH
+ * 	05DB HEBREW LETTER KAF
+ * FB3C HEBREW LETTER LAMED WITH DAGESH
+ * 	05DC HEBREW LETTER LAMED
+ * FB3E HEBREW LETTER MEM WITH DAGESH
+ * 	05DE HEBREW LETTER MEM
+ * FB40 HEBREW LETTER NUN WITH DAGESH
+ * 	05E0 HEBREW LETTER NUN
+ * FB41 HEBREW LETTER SAMEKH WITH DAGESH
+ * 	05E1 HEBREW LETTER SAMEKH
+ * FB43 HEBREW LETTER FINAL PE WITH DAGESH
+ * 	05E3 HEBREW LETTER FINAL PE
+ * FB44 HEBREW LETTER PE WITH DAGESH
+ * 	05E4 HEBREW LETTER PE
+ * FB46 HEBREW LETTER TSADI WITH DAGESH
+ * 	05E6 HEBREW LETTER TSADI
+ * FB47 HEBREW LETTER QOF WITH DAGESH
+ * 	05E7 HEBREW LETTER QOF
+ * FB48 HEBREW LETTER RESH WITH DAGESH
+ * 	05E8 HEBREW LETTER RESH
+ * FB49 HEBREW LETTER SHIN WITH DAGESH
+ * 	05E9 HEBREW LETTER SHIN
+ * FB4A HEBREW LETTER TAV WITH DAGESH
+ * 	05EA HEBREW LETTER TAV
+ * FB4B HEBREW LETTER VAV WITH HOLAM
+ * 	05D5 HEBREW LETTER VAV
+ * FB4C HEBREW LETTER BET WITH RAFE
+ * 	05D1 HEBREW LETTER BET
+ * FB4D HEBREW LETTER KAF WITH RAFE
+ * 	05DB HEBREW LETTER KAF
+ * FB4E HEBREW LETTER PE WITH RAFE
+ * 	05E4 HEBREW LETTER PE
+ * FB4F HEBREW LIGATURE ALEF LAMED
+ * 	05D0 HEBREW LETTER ALEF
+ * 	05DC HEBREW LETTER LAMED
+ * FB50 ARABIC LETTER ALEF WASLA ISOLATED FORM
+ * 	0671 ARABIC LETTER ALEF WASLA
+ * FB51 ARABIC LETTER ALEF WASLA FINAL FORM
+ * 	0671 ARABIC LETTER ALEF WASLA
+ * FB52 ARABIC LETTER BEEH ISOLATED FORM
+ * 	067B ARABIC LETTER BEEH
+ * FB53 ARABIC LETTER BEEH FINAL FORM
+ * 	067B ARABIC LETTER BEEH
+ * FB54 ARABIC LETTER BEEH INITIAL FORM
+ * 	067B ARABIC LETTER BEEH
+ * FB55 ARABIC LETTER BEEH MEDIAL FORM
+ * 	067B ARABIC LETTER BEEH
+ * FB56 ARABIC LETTER PEH ISOLATED FORM
+ * 	067E ARABIC LETTER PEH
+ * FB57 ARABIC LETTER PEH FINAL FORM
+ * 	067E ARABIC LETTER PEH
+ * FB58 ARABIC LETTER PEH INITIAL FORM
+ * 	067E ARABIC LETTER PEH
+ * FB59 ARABIC LETTER PEH MEDIAL FORM
+ * 	067E ARABIC LETTER PEH
+ * FB5A ARABIC LETTER BEHEH ISOLATED FORM
+ * 	0680 ARABIC LETTER BEHEH
+ * FB5B ARABIC LETTER BEHEH FINAL FORM
+ * 	0680 ARABIC LETTER BEHEH
+ * FB5C ARABIC LETTER BEHEH INITIAL FORM
+ * 	0680 ARABIC LETTER BEHEH
+ * FB5D ARABIC LETTER BEHEH MEDIAL FORM
+ * 	0680 ARABIC LETTER BEHEH
+ * FB5E ARABIC LETTER TTEHEH ISOLATED FORM
+ * 	067A ARABIC LETTER TTEHEH
+ * FB5F ARABIC LETTER TTEHEH FINAL FORM
+ * 	067A ARABIC LETTER TTEHEH
+ * FB60 ARABIC LETTER TTEHEH INITIAL FORM
+ * 	067A ARABIC LETTER TTEHEH
+ * FB61 ARABIC LETTER TTEHEH MEDIAL FORM
+ * 	067A ARABIC LETTER TTEHEH
+ * FB62 ARABIC LETTER TEHEH ISOLATED FORM
+ * 	067F ARABIC LETTER TEHEH
+ * FB63 ARABIC LETTER TEHEH FINAL FORM
+ * 	067F ARABIC LETTER TEHEH
+ * FB64 ARABIC LETTER TEHEH INITIAL FORM
+ * 	067F ARABIC LETTER TEHEH
+ * FB65 ARABIC LETTER TEHEH MEDIAL FORM
+ * 	067F ARABIC LETTER TEHEH
+ * FB66 ARABIC LETTER TTEH ISOLATED FORM
+ * 	0679 ARABIC LETTER TTEH
+ * FB67 ARABIC LETTER TTEH FINAL FORM
+ * 	0679 ARABIC LETTER TTEH
+ * FB68 ARABIC LETTER TTEH INITIAL FORM
+ * 	0679 ARABIC LETTER TTEH
+ * FB69 ARABIC LETTER TTEH MEDIAL FORM
+ * 	0679 ARABIC LETTER TTEH
+ * FB6A ARABIC LETTER VEH ISOLATED FORM
+ * 	06A4 ARABIC LETTER VEH
+ * FB6B ARABIC LETTER VEH FINAL FORM
+ * 	06A4 ARABIC LETTER VEH
+ * FB6C ARABIC LETTER VEH INITIAL FORM
+ * 	06A4 ARABIC LETTER VEH
+ * FB6D ARABIC LETTER VEH MEDIAL FORM
+ * 	06A4 ARABIC LETTER VEH
+ * FB6E ARABIC LETTER PEHEH ISOLATED FORM
+ * 	06A6 ARABIC LETTER PEHEH
+ * FB6F ARABIC LETTER PEHEH FINAL FORM
+ * 	06A6 ARABIC LETTER PEHEH
+ * FB70 ARABIC LETTER PEHEH INITIAL FORM
+ * 	06A6 ARABIC LETTER PEHEH
+ * FB71 ARABIC LETTER PEHEH MEDIAL FORM
+ * 	06A6 ARABIC LETTER PEHEH
+ * FB72 ARABIC LETTER DYEH ISOLATED FORM
+ * 	0684 ARABIC LETTER DYEH
+ * FB73 ARABIC LETTER DYEH FINAL FORM
+ * 	0684 ARABIC LETTER DYEH
+ * FB74 ARABIC LETTER DYEH INITIAL FORM
+ * 	0684 ARABIC LETTER DYEH
+ * FB75 ARABIC LETTER DYEH MEDIAL FORM
+ * 	0684 ARABIC LETTER DYEH
+ * FB76 ARABIC LETTER NYEH ISOLATED FORM
+ * 	0683 ARABIC LETTER NYEH
+ * FB77 ARABIC LETTER NYEH FINAL FORM
+ * 	0683 ARABIC LETTER NYEH
+ * FB78 ARABIC LETTER NYEH INITIAL FORM
+ * 	0683 ARABIC LETTER NYEH
+ * FB79 ARABIC LETTER NYEH MEDIAL FORM
+ * 	0683 ARABIC LETTER NYEH
+ * FB7A ARABIC LETTER TCHEH ISOLATED FORM
+ * 	0686 ARABIC LETTER TCHEH
+ * FB7B ARABIC LETTER TCHEH FINAL FORM
+ * 	0686 ARABIC LETTER TCHEH
+ * FB7C ARABIC LETTER TCHEH INITIAL FORM
+ * 	0686 ARABIC LETTER TCHEH
+ * FB7D ARABIC LETTER TCHEH MEDIAL FORM
+ * 	0686 ARABIC LETTER TCHEH
+ * FB7E ARABIC LETTER TCHEHEH ISOLATED FORM
+ * 	0687 ARABIC LETTER TCHEHEH
+ * FB7F ARABIC LETTER TCHEHEH FINAL FORM
+ * 	0687 ARABIC LETTER TCHEHEH
+ * FB80 ARABIC LETTER TCHEHEH INITIAL FORM
+ * 	0687 ARABIC LETTER TCHEHEH
+ * FB81 ARABIC LETTER TCHEHEH MEDIAL FORM
+ * 	0687 ARABIC LETTER TCHEHEH
+ * FB82 ARABIC LETTER DDAHAL ISOLATED FORM
+ * 	068D ARABIC LETTER DDAHAL
+ * FB83 ARABIC LETTER DDAHAL FINAL FORM
+ * 	068D ARABIC LETTER DDAHAL
+ * FB84 ARABIC LETTER DAHAL ISOLATED FORM
+ * 	068C ARABIC LETTER DAHAL
+ * FB85 ARABIC LETTER DAHAL FINAL FORM
+ * 	068C ARABIC LETTER DAHAL
+ * FB86 ARABIC LETTER DUL ISOLATED FORM
+ * 	068E ARABIC LETTER DUL
+ * FB87 ARABIC LETTER DUL FINAL FORM
+ * 	068E ARABIC LETTER DUL
+ * FB88 ARABIC LETTER DDAL ISOLATED FORM
+ * 	0688 ARABIC LETTER DDAL
+ * FB89 ARABIC LETTER DDAL FINAL FORM
+ * 	0688 ARABIC LETTER DDAL
+ * FB8A ARABIC LETTER JEH ISOLATED FORM
+ * 	0698 ARABIC LETTER JEH
+ * FB8B ARABIC LETTER JEH FINAL FORM
+ * 	0698 ARABIC LETTER JEH
+ * FB8C ARABIC LETTER RREH ISOLATED FORM
+ * 	0691 ARABIC LETTER RREH
+ * FB8D ARABIC LETTER RREH FINAL FORM
+ * 	0691 ARABIC LETTER RREH
+ * FB8E ARABIC LETTER KEHEH ISOLATED FORM
+ * 	06A9 ARABIC LETTER KEHEH
+ * FB8F ARABIC LETTER KEHEH FINAL FORM
+ * 	06A9 ARABIC LETTER KEHEH
+ * FB90 ARABIC LETTER KEHEH INITIAL FORM
+ * 	06A9 ARABIC LETTER KEHEH
+ * FB91 ARABIC LETTER KEHEH MEDIAL FORM
+ * 	06A9 ARABIC LETTER KEHEH
+ * FB92 ARABIC LETTER GAF ISOLATED FORM
+ * 	06AF ARABIC LETTER GAF
+ * FB93 ARABIC LETTER GAF FINAL FORM
+ * 	06AF ARABIC LETTER GAF
+ * FB94 ARABIC LETTER GAF INITIAL FORM
+ * 	06AF ARABIC LETTER GAF
+ * FB95 ARABIC LETTER GAF MEDIAL FORM
+ * 	06AF ARABIC LETTER GAF
+ * FB96 ARABIC LETTER GUEH ISOLATED FORM
+ * 	06B3 ARABIC LETTER GUEH
+ * FB97 ARABIC LETTER GUEH FINAL FORM
+ * 	06B3 ARABIC LETTER GUEH
+ * FB98 ARABIC LETTER GUEH INITIAL FORM
+ * 	06B3 ARABIC LETTER GUEH
+ * FB99 ARABIC LETTER GUEH MEDIAL FORM
+ * 	06B3 ARABIC LETTER GUEH
+ * FB9A ARABIC LETTER NGOEH ISOLATED FORM
+ * 	06B1 ARABIC LETTER NGOEH
+ * FB9B ARABIC LETTER NGOEH FINAL FORM
+ * 	06B1 ARABIC LETTER NGOEH
+ * FB9C ARABIC LETTER NGOEH INITIAL FORM
+ * 	06B1 ARABIC LETTER NGOEH
+ * FB9D ARABIC LETTER NGOEH MEDIAL FORM
+ * 	06B1 ARABIC LETTER NGOEH
+ * FB9E ARABIC LETTER NOON GHUNNA ISOLATED FORM
+ * 	06BA ARABIC LETTER NOON GHUNNA
+ * FB9F ARABIC LETTER NOON GHUNNA FINAL FORM
+ * 	06BA ARABIC LETTER NOON GHUNNA
+ * FBA0 ARABIC LETTER RNOON ISOLATED FORM
+ * 	06BB ARABIC LETTER RNOON
+ * FBA1 ARABIC LETTER RNOON FINAL FORM
+ * 	06BB ARABIC LETTER RNOON
+ * FBA2 ARABIC LETTER RNOON INITIAL FORM
+ * 	06BB ARABIC LETTER RNOON
+ * FBA3 ARABIC LETTER RNOON MEDIAL FORM
+ * 	06BB ARABIC LETTER RNOON
+ * FBA4 ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM
+ * 	06D5 ARABIC LETTER AE
+ * FBA5 ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM
+ * 	06D5 ARABIC LETTER AE
+ * FBA6 ARABIC LETTER HEH GOAL ISOLATED FORM
+ * 	06C1 ARABIC LETTER HEH GOAL
+ * FBA7 ARABIC LETTER HEH GOAL FINAL FORM
+ * 	06C1 ARABIC LETTER HEH GOAL
+ * FBA8 ARABIC LETTER HEH GOAL INITIAL FORM
+ * 	06C1 ARABIC LETTER HEH GOAL
+ * FBA9 ARABIC LETTER HEH GOAL MEDIAL FORM
+ * 	06C1 ARABIC LETTER HEH GOAL
+ * FBAA ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM
+ * 	06BE ARABIC LETTER HEH DOACHASHMEE
+ * FBAB ARABIC LETTER HEH DOACHASHMEE FINAL FORM
+ * 	06BE ARABIC LETTER HEH DOACHASHMEE
+ * FBAC ARABIC LETTER HEH DOACHASHMEE INITIAL FORM
+ * 	06BE ARABIC LETTER HEH DOACHASHMEE
+ * FBAD ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM
+ * 	06BE ARABIC LETTER HEH DOACHASHMEE
+ * FBAE ARABIC LETTER YEH BARREE ISOLATED FORM
+ * 	06D2 ARABIC LETTER YEH BARREE
+ * FBAF ARABIC LETTER YEH BARREE FINAL FORM
+ * 	06D2 ARABIC LETTER YEH BARREE
+ * FBB0 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM
+ * 	06D2 ARABIC LETTER YEH BARREE
+ * FBB1 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM
+ * 	06D2 ARABIC LETTER YEH BARREE
+ * FBD3 ARABIC LETTER NG ISOLATED FORM
+ * 	06AD ARABIC LETTER NG
+ * FBD4 ARABIC LETTER NG FINAL FORM
+ * 	06AD ARABIC LETTER NG
+ * FBD5 ARABIC LETTER NG INITIAL FORM
+ * 	06AD ARABIC LETTER NG
+ * FBD6 ARABIC LETTER NG MEDIAL FORM
+ * 	06AD ARABIC LETTER NG
+ * FBD7 ARABIC LETTER U ISOLATED FORM
+ * 	06C7 ARABIC LETTER U
+ * FBD8 ARABIC LETTER U FINAL FORM
+ * 	06C7 ARABIC LETTER U
+ * FBD9 ARABIC LETTER OE ISOLATED FORM
+ * 	06C6 ARABIC LETTER OE
+ * FBDA ARABIC LETTER OE FINAL FORM
+ * 	06C6 ARABIC LETTER OE
+ * FBDB ARABIC LETTER YU ISOLATED FORM
+ * 	06C8 ARABIC LETTER YU
+ * FBDC ARABIC LETTER YU FINAL FORM
+ * 	06C8 ARABIC LETTER YU
+ * FBDD ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM
+ * 	06C7 ARABIC LETTER U
+ * 	0674 ARABIC LETTER HIGH HAMZA
+ * FBDE ARABIC LETTER VE ISOLATED FORM
+ * 	06CB ARABIC LETTER VE
+ * FBDF ARABIC LETTER VE FINAL FORM
+ * 	06CB ARABIC LETTER VE
+ * FBE0 ARABIC LETTER KIRGHIZ OE ISOLATED FORM
+ * 	06C5 ARABIC LETTER KIRGHIZ OE
+ * FBE1 ARABIC LETTER KIRGHIZ OE FINAL FORM
+ * 	06C5 ARABIC LETTER KIRGHIZ OE
+ * FBE2 ARABIC LETTER KIRGHIZ YU ISOLATED FORM
+ * 	06C9 ARABIC LETTER KIRGHIZ YU
+ * FBE3 ARABIC LETTER KIRGHIZ YU FINAL FORM
+ * 	06C9 ARABIC LETTER KIRGHIZ YU
+ * FBE4 ARABIC LETTER E ISOLATED FORM
+ * 	06D0 ARABIC LETTER E
+ * FBE5 ARABIC LETTER E FINAL FORM
+ * 	06D0 ARABIC LETTER E
+ * FBE6 ARABIC LETTER E INITIAL FORM
+ * 	06D0 ARABIC LETTER E
+ * FBE7 ARABIC LETTER E MEDIAL FORM
+ * 	06D0 ARABIC LETTER E
+ * FBE8 ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FBE9 ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FBEA ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM
+ * 	0627 ARABIC LETTER ALEF
+ * 	064A ARABIC LETTER YEH
+ * FBEB ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM
+ * 	0627 ARABIC LETTER ALEF
+ * 	064A ARABIC LETTER YEH
+ * FBEC ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM
+ * 	06D5 ARABIC LETTER AE
+ * 	064A ARABIC LETTER YEH
+ * FBED ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM
+ * 	06D5 ARABIC LETTER AE
+ * 	064A ARABIC LETTER YEH
+ * FBEE ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM
+ * 	0648 ARABIC LETTER WAW
+ * 	064A ARABIC LETTER YEH
+ * FBEF ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM
+ * 	0648 ARABIC LETTER WAW
+ * 	064A ARABIC LETTER YEH
+ * FBF0 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM
+ * 	06C7 ARABIC LETTER U
+ * 	064A ARABIC LETTER YEH
+ * FBF1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM
+ * 	06C7 ARABIC LETTER U
+ * 	064A ARABIC LETTER YEH
+ * FBF2 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM
+ * 	06C6 ARABIC LETTER OE
+ * 	064A ARABIC LETTER YEH
+ * FBF3 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM
+ * 	06C6 ARABIC LETTER OE
+ * 	064A ARABIC LETTER YEH
+ * FBF4 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM
+ * 	06C8 ARABIC LETTER YU
+ * 	064A ARABIC LETTER YEH
+ * FBF5 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM
+ * 	06C8 ARABIC LETTER YU
+ * 	064A ARABIC LETTER YEH
+ * FBF6 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM
+ * 	06D0 ARABIC LETTER E
+ * 	064A ARABIC LETTER YEH
+ * FBF7 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM
+ * 	06D0 ARABIC LETTER E
+ * 	064A ARABIC LETTER YEH
+ * FBF8 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM
+ * 	06D0 ARABIC LETTER E
+ * 	064A ARABIC LETTER YEH
+ * FBF9 ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * 	064A ARABIC LETTER YEH
+ * FBFA ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * 	064A ARABIC LETTER YEH
+ * FBFB ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * 	064A ARABIC LETTER YEH
+ * FBFC ARABIC LETTER FARSI YEH ISOLATED FORM
+ * 	06CC ARABIC LETTER FARSI YEH
+ * FBFD ARABIC LETTER FARSI YEH FINAL FORM
+ * 	06CC ARABIC LETTER FARSI YEH
+ * FBFE ARABIC LETTER FARSI YEH INITIAL FORM
+ * 	06CC ARABIC LETTER FARSI YEH
+ * FBFF ARABIC LETTER FARSI YEH MEDIAL FORM
+ * 	06CC ARABIC LETTER FARSI YEH
+ * FC00 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	064A ARABIC LETTER YEH
+ * FC01 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FC02 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FC03 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * 	064A ARABIC LETTER YEH
+ * FC04 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM
+ * 	064A ARABIC LETTER YEH
+ * 	064A ARABIC LETTER YEH
+ * FC05 ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	062C ARABIC LETTER JEEM
+ * FC06 ARABIC LIGATURE BEH WITH HAH ISOLATED FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	062D ARABIC LETTER HAH
+ * FC07 ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	062E ARABIC LETTER KHAH
+ * FC08 ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	0645 ARABIC LETTER MEEM
+ * FC09 ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC0A ARABIC LIGATURE BEH WITH YEH ISOLATED FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	064A ARABIC LETTER YEH
+ * FC0B ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062C ARABIC LETTER JEEM
+ * FC0C ARABIC LIGATURE TEH WITH HAH ISOLATED FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062D ARABIC LETTER HAH
+ * FC0D ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062E ARABIC LETTER KHAH
+ * FC0E ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0645 ARABIC LETTER MEEM
+ * FC0F ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC10 ARABIC LIGATURE TEH WITH YEH ISOLATED FORM
+ * 	062A ARABIC LETTER TEH
+ * 	064A ARABIC LETTER YEH
+ * FC11 ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM
+ * 	062B ARABIC LETTER THEH
+ * 	062C ARABIC LETTER JEEM
+ * FC12 ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM
+ * 	062B ARABIC LETTER THEH
+ * 	0645 ARABIC LETTER MEEM
+ * FC13 ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM
+ * 	062B ARABIC LETTER THEH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC14 ARABIC LIGATURE THEH WITH YEH ISOLATED FORM
+ * 	062B ARABIC LETTER THEH
+ * 	064A ARABIC LETTER YEH
+ * FC15 ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	062D ARABIC LETTER HAH
+ * FC16 ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FC17 ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM
+ * 	062D ARABIC LETTER HAH
+ * 	062C ARABIC LETTER JEEM
+ * FC18 ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM
+ * 	062D ARABIC LETTER HAH
+ * 	0645 ARABIC LETTER MEEM
+ * FC19 ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM
+ * 	062E ARABIC LETTER KHAH
+ * 	062C ARABIC LETTER JEEM
+ * FC1A ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM
+ * 	062E ARABIC LETTER KHAH
+ * 	062D ARABIC LETTER HAH
+ * FC1B ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM
+ * 	062E ARABIC LETTER KHAH
+ * 	0645 ARABIC LETTER MEEM
+ * FC1C ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062C ARABIC LETTER JEEM
+ * FC1D ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062D ARABIC LETTER HAH
+ * FC1E ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062E ARABIC LETTER KHAH
+ * FC1F ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0645 ARABIC LETTER MEEM
+ * FC20 ARABIC LIGATURE SAD WITH HAH ISOLATED FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	062D ARABIC LETTER HAH
+ * FC21 ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	0645 ARABIC LETTER MEEM
+ * FC22 ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	062C ARABIC LETTER JEEM
+ * FC23 ARABIC LIGATURE DAD WITH HAH ISOLATED FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	062D ARABIC LETTER HAH
+ * FC24 ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	062E ARABIC LETTER KHAH
+ * FC25 ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	0645 ARABIC LETTER MEEM
+ * FC26 ARABIC LIGATURE TAH WITH HAH ISOLATED FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	062D ARABIC LETTER HAH
+ * FC27 ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	0645 ARABIC LETTER MEEM
+ * FC28 ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM
+ * 	0638 ARABIC LETTER ZAH
+ * 	0645 ARABIC LETTER MEEM
+ * FC29 ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	062C ARABIC LETTER JEEM
+ * FC2A ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	0645 ARABIC LETTER MEEM
+ * FC2B ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM
+ * 	063A ARABIC LETTER GHAIN
+ * 	062C ARABIC LETTER JEEM
+ * FC2C ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM
+ * 	063A ARABIC LETTER GHAIN
+ * 	0645 ARABIC LETTER MEEM
+ * FC2D ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	062C ARABIC LETTER JEEM
+ * FC2E ARABIC LIGATURE FEH WITH HAH ISOLATED FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	062D ARABIC LETTER HAH
+ * FC2F ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	062E ARABIC LETTER KHAH
+ * FC30 ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	0645 ARABIC LETTER MEEM
+ * FC31 ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC32 ARABIC LIGATURE FEH WITH YEH ISOLATED FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	064A ARABIC LETTER YEH
+ * FC33 ARABIC LIGATURE QAF WITH HAH ISOLATED FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	062D ARABIC LETTER HAH
+ * FC34 ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	0645 ARABIC LETTER MEEM
+ * FC35 ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC36 ARABIC LIGATURE QAF WITH YEH ISOLATED FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	064A ARABIC LETTER YEH
+ * FC37 ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0627 ARABIC LETTER ALEF
+ * FC38 ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	062C ARABIC LETTER JEEM
+ * FC39 ARABIC LIGATURE KAF WITH HAH ISOLATED FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	062D ARABIC LETTER HAH
+ * FC3A ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	062E ARABIC LETTER KHAH
+ * FC3B ARABIC LIGATURE KAF WITH LAM ISOLATED FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0644 ARABIC LETTER LAM
+ * FC3C ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0645 ARABIC LETTER MEEM
+ * FC3D ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC3E ARABIC LIGATURE KAF WITH YEH ISOLATED FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	064A ARABIC LETTER YEH
+ * FC3F ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062C ARABIC LETTER JEEM
+ * FC40 ARABIC LIGATURE LAM WITH HAH ISOLATED FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062D ARABIC LETTER HAH
+ * FC41 ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062E ARABIC LETTER KHAH
+ * FC42 ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0645 ARABIC LETTER MEEM
+ * FC43 ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC44 ARABIC LIGATURE LAM WITH YEH ISOLATED FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	064A ARABIC LETTER YEH
+ * FC45 ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062C ARABIC LETTER JEEM
+ * FC46 ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FC47 ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062E ARABIC LETTER KHAH
+ * FC48 ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FC49 ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC4A ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FC4B ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062C ARABIC LETTER JEEM
+ * FC4C ARABIC LIGATURE NOON WITH HAH ISOLATED FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062D ARABIC LETTER HAH
+ * FC4D ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062E ARABIC LETTER KHAH
+ * FC4E ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0645 ARABIC LETTER MEEM
+ * FC4F ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC50 ARABIC LIGATURE NOON WITH YEH ISOLATED FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	064A ARABIC LETTER YEH
+ * FC51 ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM
+ * 	0647 ARABIC LETTER HEH
+ * 	062C ARABIC LETTER JEEM
+ * FC52 ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM
+ * 	0647 ARABIC LETTER HEH
+ * 	0645 ARABIC LETTER MEEM
+ * FC53 ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM
+ * 	0647 ARABIC LETTER HEH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC54 ARABIC LIGATURE HEH WITH YEH ISOLATED FORM
+ * 	0647 ARABIC LETTER HEH
+ * 	064A ARABIC LETTER YEH
+ * FC55 ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM
+ * 	064A ARABIC LETTER YEH
+ * 	062C ARABIC LETTER JEEM
+ * FC56 ARABIC LIGATURE YEH WITH HAH ISOLATED FORM
+ * 	064A ARABIC LETTER YEH
+ * 	062D ARABIC LETTER HAH
+ * FC57 ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM
+ * 	064A ARABIC LETTER YEH
+ * 	062E ARABIC LETTER KHAH
+ * FC58 ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0645 ARABIC LETTER MEEM
+ * FC59 ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC5A ARABIC LIGATURE YEH WITH YEH ISOLATED FORM
+ * 	064A ARABIC LETTER YEH
+ * 	064A ARABIC LETTER YEH
+ * FC5B ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM
+ * 	0630 ARABIC LETTER THAL
+ * FC5C ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM
+ * 	0631 ARABIC LETTER REH
+ * FC5D ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC5E ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM
+ * 	0020 SPACE
+ * FC5F ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM
+ * 	0020 SPACE
+ * FC60 ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM
+ * 	0020 SPACE
+ * FC61 ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM
+ * 	0020 SPACE
+ * FC62 ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM
+ * 	0020 SPACE
+ * FC63 ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM
+ * 	0020 SPACE
+ * FC64 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM
+ * 	0631 ARABIC LETTER REH
+ * 	064A ARABIC LETTER YEH
+ * FC65 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM
+ * 	0632 ARABIC LETTER ZAIN
+ * 	064A ARABIC LETTER YEH
+ * FC66 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FC67 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	064A ARABIC LETTER YEH
+ * FC68 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * 	064A ARABIC LETTER YEH
+ * FC69 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	064A ARABIC LETTER YEH
+ * FC6A ARABIC LIGATURE BEH WITH REH FINAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	0631 ARABIC LETTER REH
+ * FC6B ARABIC LIGATURE BEH WITH ZAIN FINAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	0632 ARABIC LETTER ZAIN
+ * FC6C ARABIC LIGATURE BEH WITH MEEM FINAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	0645 ARABIC LETTER MEEM
+ * FC6D ARABIC LIGATURE BEH WITH NOON FINAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	0646 ARABIC LETTER NOON
+ * FC6E ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC6F ARABIC LIGATURE BEH WITH YEH FINAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	064A ARABIC LETTER YEH
+ * FC70 ARABIC LIGATURE TEH WITH REH FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0631 ARABIC LETTER REH
+ * FC71 ARABIC LIGATURE TEH WITH ZAIN FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0632 ARABIC LETTER ZAIN
+ * FC72 ARABIC LIGATURE TEH WITH MEEM FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0645 ARABIC LETTER MEEM
+ * FC73 ARABIC LIGATURE TEH WITH NOON FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0646 ARABIC LETTER NOON
+ * FC74 ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC75 ARABIC LIGATURE TEH WITH YEH FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	064A ARABIC LETTER YEH
+ * FC76 ARABIC LIGATURE THEH WITH REH FINAL FORM
+ * 	062B ARABIC LETTER THEH
+ * 	0631 ARABIC LETTER REH
+ * FC77 ARABIC LIGATURE THEH WITH ZAIN FINAL FORM
+ * 	062B ARABIC LETTER THEH
+ * 	0632 ARABIC LETTER ZAIN
+ * FC78 ARABIC LIGATURE THEH WITH MEEM FINAL FORM
+ * 	062B ARABIC LETTER THEH
+ * 	0645 ARABIC LETTER MEEM
+ * FC79 ARABIC LIGATURE THEH WITH NOON FINAL FORM
+ * 	062B ARABIC LETTER THEH
+ * 	0646 ARABIC LETTER NOON
+ * FC7A ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM
+ * 	062B ARABIC LETTER THEH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC7B ARABIC LIGATURE THEH WITH YEH FINAL FORM
+ * 	062B ARABIC LETTER THEH
+ * 	064A ARABIC LETTER YEH
+ * FC7C ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC7D ARABIC LIGATURE FEH WITH YEH FINAL FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	064A ARABIC LETTER YEH
+ * FC7E ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC7F ARABIC LIGATURE QAF WITH YEH FINAL FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	064A ARABIC LETTER YEH
+ * FC80 ARABIC LIGATURE KAF WITH ALEF FINAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0627 ARABIC LETTER ALEF
+ * FC81 ARABIC LIGATURE KAF WITH LAM FINAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0644 ARABIC LETTER LAM
+ * FC82 ARABIC LIGATURE KAF WITH MEEM FINAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0645 ARABIC LETTER MEEM
+ * FC83 ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC84 ARABIC LIGATURE KAF WITH YEH FINAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	064A ARABIC LETTER YEH
+ * FC85 ARABIC LIGATURE LAM WITH MEEM FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0645 ARABIC LETTER MEEM
+ * FC86 ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC87 ARABIC LIGATURE LAM WITH YEH FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	064A ARABIC LETTER YEH
+ * FC88 ARABIC LIGATURE MEEM WITH ALEF FINAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	0627 ARABIC LETTER ALEF
+ * FC89 ARABIC LIGATURE MEEM WITH MEEM FINAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FC8A ARABIC LIGATURE NOON WITH REH FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0631 ARABIC LETTER REH
+ * FC8B ARABIC LIGATURE NOON WITH ZAIN FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0632 ARABIC LETTER ZAIN
+ * FC8C ARABIC LIGATURE NOON WITH MEEM FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0645 ARABIC LETTER MEEM
+ * FC8D ARABIC LIGATURE NOON WITH NOON FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0646 ARABIC LETTER NOON
+ * FC8E ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC8F ARABIC LIGATURE NOON WITH YEH FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	064A ARABIC LETTER YEH
+ * FC90 ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC91 ARABIC LIGATURE YEH WITH REH FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0631 ARABIC LETTER REH
+ * FC92 ARABIC LIGATURE YEH WITH ZAIN FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0632 ARABIC LETTER ZAIN
+ * FC93 ARABIC LIGATURE YEH WITH MEEM FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0645 ARABIC LETTER MEEM
+ * FC94 ARABIC LIGATURE YEH WITH NOON FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0646 ARABIC LETTER NOON
+ * FC95 ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FC96 ARABIC LIGATURE YEH WITH YEH FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	064A ARABIC LETTER YEH
+ * FC97 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	064A ARABIC LETTER YEH
+ * FC98 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FC99 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM
+ * 	062E ARABIC LETTER KHAH
+ * 	064A ARABIC LETTER YEH
+ * FC9A ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FC9B ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM
+ * 	0647 ARABIC LETTER HEH
+ * 	064A ARABIC LETTER YEH
+ * FC9C ARABIC LIGATURE BEH WITH JEEM INITIAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	062C ARABIC LETTER JEEM
+ * FC9D ARABIC LIGATURE BEH WITH HAH INITIAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	062D ARABIC LETTER HAH
+ * FC9E ARABIC LIGATURE BEH WITH KHAH INITIAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	062E ARABIC LETTER KHAH
+ * FC9F ARABIC LIGATURE BEH WITH MEEM INITIAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	0645 ARABIC LETTER MEEM
+ * FCA0 ARABIC LIGATURE BEH WITH HEH INITIAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	0647 ARABIC LETTER HEH
+ * FCA1 ARABIC LIGATURE TEH WITH JEEM INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062C ARABIC LETTER JEEM
+ * FCA2 ARABIC LIGATURE TEH WITH HAH INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062D ARABIC LETTER HAH
+ * FCA3 ARABIC LIGATURE TEH WITH KHAH INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062E ARABIC LETTER KHAH
+ * FCA4 ARABIC LIGATURE TEH WITH MEEM INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0645 ARABIC LETTER MEEM
+ * FCA5 ARABIC LIGATURE TEH WITH HEH INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0647 ARABIC LETTER HEH
+ * FCA6 ARABIC LIGATURE THEH WITH MEEM INITIAL FORM
+ * 	062B ARABIC LETTER THEH
+ * 	0645 ARABIC LETTER MEEM
+ * FCA7 ARABIC LIGATURE JEEM WITH HAH INITIAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	062D ARABIC LETTER HAH
+ * FCA8 ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FCA9 ARABIC LIGATURE HAH WITH JEEM INITIAL FORM
+ * 	062D ARABIC LETTER HAH
+ * 	062C ARABIC LETTER JEEM
+ * FCAA ARABIC LIGATURE HAH WITH MEEM INITIAL FORM
+ * 	062D ARABIC LETTER HAH
+ * 	0645 ARABIC LETTER MEEM
+ * FCAB ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM
+ * 	062E ARABIC LETTER KHAH
+ * 	062C ARABIC LETTER JEEM
+ * FCAC ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM
+ * 	062E ARABIC LETTER KHAH
+ * 	0645 ARABIC LETTER MEEM
+ * FCAD ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062C ARABIC LETTER JEEM
+ * FCAE ARABIC LIGATURE SEEN WITH HAH INITIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062D ARABIC LETTER HAH
+ * FCAF ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062E ARABIC LETTER KHAH
+ * FCB0 ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0645 ARABIC LETTER MEEM
+ * FCB1 ARABIC LIGATURE SAD WITH HAH INITIAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	062D ARABIC LETTER HAH
+ * FCB2 ARABIC LIGATURE SAD WITH KHAH INITIAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	062E ARABIC LETTER KHAH
+ * FCB3 ARABIC LIGATURE SAD WITH MEEM INITIAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	0645 ARABIC LETTER MEEM
+ * FCB4 ARABIC LIGATURE DAD WITH JEEM INITIAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	062C ARABIC LETTER JEEM
+ * FCB5 ARABIC LIGATURE DAD WITH HAH INITIAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	062D ARABIC LETTER HAH
+ * FCB6 ARABIC LIGATURE DAD WITH KHAH INITIAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	062E ARABIC LETTER KHAH
+ * FCB7 ARABIC LIGATURE DAD WITH MEEM INITIAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	0645 ARABIC LETTER MEEM
+ * FCB8 ARABIC LIGATURE TAH WITH HAH INITIAL FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	062D ARABIC LETTER HAH
+ * FCB9 ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM
+ * 	0638 ARABIC LETTER ZAH
+ * 	0645 ARABIC LETTER MEEM
+ * FCBA ARABIC LIGATURE AIN WITH JEEM INITIAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	062C ARABIC LETTER JEEM
+ * FCBB ARABIC LIGATURE AIN WITH MEEM INITIAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	0645 ARABIC LETTER MEEM
+ * FCBC ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM
+ * 	063A ARABIC LETTER GHAIN
+ * 	062C ARABIC LETTER JEEM
+ * FCBD ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM
+ * 	063A ARABIC LETTER GHAIN
+ * 	0645 ARABIC LETTER MEEM
+ * FCBE ARABIC LIGATURE FEH WITH JEEM INITIAL FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	062C ARABIC LETTER JEEM
+ * FCBF ARABIC LIGATURE FEH WITH HAH INITIAL FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	062D ARABIC LETTER HAH
+ * FCC0 ARABIC LIGATURE FEH WITH KHAH INITIAL FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	062E ARABIC LETTER KHAH
+ * FCC1 ARABIC LIGATURE FEH WITH MEEM INITIAL FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	0645 ARABIC LETTER MEEM
+ * FCC2 ARABIC LIGATURE QAF WITH HAH INITIAL FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	062D ARABIC LETTER HAH
+ * FCC3 ARABIC LIGATURE QAF WITH MEEM INITIAL FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	0645 ARABIC LETTER MEEM
+ * FCC4 ARABIC LIGATURE KAF WITH JEEM INITIAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	062C ARABIC LETTER JEEM
+ * FCC5 ARABIC LIGATURE KAF WITH HAH INITIAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	062D ARABIC LETTER HAH
+ * FCC6 ARABIC LIGATURE KAF WITH KHAH INITIAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	062E ARABIC LETTER KHAH
+ * FCC7 ARABIC LIGATURE KAF WITH LAM INITIAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0644 ARABIC LETTER LAM
+ * FCC8 ARABIC LIGATURE KAF WITH MEEM INITIAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0645 ARABIC LETTER MEEM
+ * FCC9 ARABIC LIGATURE LAM WITH JEEM INITIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062C ARABIC LETTER JEEM
+ * FCCA ARABIC LIGATURE LAM WITH HAH INITIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062D ARABIC LETTER HAH
+ * FCCB ARABIC LIGATURE LAM WITH KHAH INITIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062E ARABIC LETTER KHAH
+ * FCCC ARABIC LIGATURE LAM WITH MEEM INITIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0645 ARABIC LETTER MEEM
+ * FCCD ARABIC LIGATURE LAM WITH HEH INITIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0647 ARABIC LETTER HEH
+ * FCCE ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062C ARABIC LETTER JEEM
+ * FCCF ARABIC LIGATURE MEEM WITH HAH INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FCD0 ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062E ARABIC LETTER KHAH
+ * FCD1 ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FCD2 ARABIC LIGATURE NOON WITH JEEM INITIAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062C ARABIC LETTER JEEM
+ * FCD3 ARABIC LIGATURE NOON WITH HAH INITIAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062D ARABIC LETTER HAH
+ * FCD4 ARABIC LIGATURE NOON WITH KHAH INITIAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062E ARABIC LETTER KHAH
+ * FCD5 ARABIC LIGATURE NOON WITH MEEM INITIAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0645 ARABIC LETTER MEEM
+ * FCD6 ARABIC LIGATURE NOON WITH HEH INITIAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0647 ARABIC LETTER HEH
+ * FCD7 ARABIC LIGATURE HEH WITH JEEM INITIAL FORM
+ * 	0647 ARABIC LETTER HEH
+ * 	062C ARABIC LETTER JEEM
+ * FCD8 ARABIC LIGATURE HEH WITH MEEM INITIAL FORM
+ * 	0647 ARABIC LETTER HEH
+ * 	0645 ARABIC LETTER MEEM
+ * FCD9 ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM
+ * 	0647 ARABIC LETTER HEH
+ * FCDA ARABIC LIGATURE YEH WITH JEEM INITIAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	062C ARABIC LETTER JEEM
+ * FCDB ARABIC LIGATURE YEH WITH HAH INITIAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	062D ARABIC LETTER HAH
+ * FCDC ARABIC LIGATURE YEH WITH KHAH INITIAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	062E ARABIC LETTER KHAH
+ * FCDD ARABIC LIGATURE YEH WITH MEEM INITIAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0645 ARABIC LETTER MEEM
+ * FCDE ARABIC LIGATURE YEH WITH HEH INITIAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0647 ARABIC LETTER HEH
+ * FCDF ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FCE0 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM
+ * 	0647 ARABIC LETTER HEH
+ * 	064A ARABIC LETTER YEH
+ * FCE1 ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	0645 ARABIC LETTER MEEM
+ * FCE2 ARABIC LIGATURE BEH WITH HEH MEDIAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	0647 ARABIC LETTER HEH
+ * FCE3 ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0645 ARABIC LETTER MEEM
+ * FCE4 ARABIC LIGATURE TEH WITH HEH MEDIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0647 ARABIC LETTER HEH
+ * FCE5 ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM
+ * 	062B ARABIC LETTER THEH
+ * 	0645 ARABIC LETTER MEEM
+ * FCE6 ARABIC LIGATURE THEH WITH HEH MEDIAL FORM
+ * 	062B ARABIC LETTER THEH
+ * 	0647 ARABIC LETTER HEH
+ * FCE7 ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0645 ARABIC LETTER MEEM
+ * FCE8 ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0647 ARABIC LETTER HEH
+ * FCE9 ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0645 ARABIC LETTER MEEM
+ * FCEA ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0647 ARABIC LETTER HEH
+ * FCEB ARABIC LIGATURE KAF WITH LAM MEDIAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0644 ARABIC LETTER LAM
+ * FCEC ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0645 ARABIC LETTER MEEM
+ * FCED ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0645 ARABIC LETTER MEEM
+ * FCEE ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0645 ARABIC LETTER MEEM
+ * FCEF ARABIC LIGATURE NOON WITH HEH MEDIAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0647 ARABIC LETTER HEH
+ * FCF0 ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0645 ARABIC LETTER MEEM
+ * FCF1 ARABIC LIGATURE YEH WITH HEH MEDIAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0647 ARABIC LETTER HEH
+ * FCF2 ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM
+ * 	0640 ARABIC TATWEEL
+ * FCF3 ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM
+ * 	0640 ARABIC TATWEEL
+ * FCF4 ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM
+ * 	0640 ARABIC TATWEEL
+ * FCF5 ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FCF6 ARABIC LIGATURE TAH WITH YEH ISOLATED FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	064A ARABIC LETTER YEH
+ * FCF7 ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FCF8 ARABIC LIGATURE AIN WITH YEH ISOLATED FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	064A ARABIC LETTER YEH
+ * FCF9 ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM
+ * 	063A ARABIC LETTER GHAIN
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FCFA ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM
+ * 	063A ARABIC LETTER GHAIN
+ * 	064A ARABIC LETTER YEH
+ * FCFB ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FCFC ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	064A ARABIC LETTER YEH
+ * FCFD ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FCFE ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	064A ARABIC LETTER YEH
+ * FCFF ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM
+ * 	062D ARABIC LETTER HAH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD00 ARABIC LIGATURE HAH WITH YEH ISOLATED FORM
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FD01 ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD02 ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	064A ARABIC LETTER YEH
+ * FD03 ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM
+ * 	062E ARABIC LETTER KHAH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD04 ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM
+ * 	062E ARABIC LETTER KHAH
+ * 	064A ARABIC LETTER YEH
+ * FD05 ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD06 ARABIC LIGATURE SAD WITH YEH ISOLATED FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	064A ARABIC LETTER YEH
+ * FD07 ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD08 ARABIC LIGATURE DAD WITH YEH ISOLATED FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	064A ARABIC LETTER YEH
+ * FD09 ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062C ARABIC LETTER JEEM
+ * FD0A ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062D ARABIC LETTER HAH
+ * FD0B ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062E ARABIC LETTER KHAH
+ * FD0C ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0645 ARABIC LETTER MEEM
+ * FD0D ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0631 ARABIC LETTER REH
+ * FD0E ARABIC LIGATURE SEEN WITH REH ISOLATED FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0631 ARABIC LETTER REH
+ * FD0F ARABIC LIGATURE SAD WITH REH ISOLATED FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	0631 ARABIC LETTER REH
+ * FD10 ARABIC LIGATURE DAD WITH REH ISOLATED FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	0631 ARABIC LETTER REH
+ * FD11 ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD12 ARABIC LIGATURE TAH WITH YEH FINAL FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	064A ARABIC LETTER YEH
+ * FD13 ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD14 ARABIC LIGATURE AIN WITH YEH FINAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	064A ARABIC LETTER YEH
+ * FD15 ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM
+ * 	063A ARABIC LETTER GHAIN
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD16 ARABIC LIGATURE GHAIN WITH YEH FINAL FORM
+ * 	063A ARABIC LETTER GHAIN
+ * 	064A ARABIC LETTER YEH
+ * FD17 ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD18 ARABIC LIGATURE SEEN WITH YEH FINAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	064A ARABIC LETTER YEH
+ * FD19 ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD1A ARABIC LIGATURE SHEEN WITH YEH FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	064A ARABIC LETTER YEH
+ * FD1B ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM
+ * 	062D ARABIC LETTER HAH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD1C ARABIC LIGATURE HAH WITH YEH FINAL FORM
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FD1D ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD1E ARABIC LIGATURE JEEM WITH YEH FINAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	064A ARABIC LETTER YEH
+ * FD1F ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM
+ * 	062E ARABIC LETTER KHAH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD20 ARABIC LIGATURE KHAH WITH YEH FINAL FORM
+ * 	062E ARABIC LETTER KHAH
+ * 	064A ARABIC LETTER YEH
+ * FD21 ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD22 ARABIC LIGATURE SAD WITH YEH FINAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	064A ARABIC LETTER YEH
+ * FD23 ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD24 ARABIC LIGATURE DAD WITH YEH FINAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	064A ARABIC LETTER YEH
+ * FD25 ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062C ARABIC LETTER JEEM
+ * FD26 ARABIC LIGATURE SHEEN WITH HAH FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062D ARABIC LETTER HAH
+ * FD27 ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062E ARABIC LETTER KHAH
+ * FD28 ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0645 ARABIC LETTER MEEM
+ * FD29 ARABIC LIGATURE SHEEN WITH REH FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0631 ARABIC LETTER REH
+ * FD2A ARABIC LIGATURE SEEN WITH REH FINAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0631 ARABIC LETTER REH
+ * FD2B ARABIC LIGATURE SAD WITH REH FINAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	0631 ARABIC LETTER REH
+ * FD2C ARABIC LIGATURE DAD WITH REH FINAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	0631 ARABIC LETTER REH
+ * FD2D ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062C ARABIC LETTER JEEM
+ * FD2E ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062D ARABIC LETTER HAH
+ * FD2F ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062E ARABIC LETTER KHAH
+ * FD30 ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0645 ARABIC LETTER MEEM
+ * FD31 ARABIC LIGATURE SEEN WITH HEH INITIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0647 ARABIC LETTER HEH
+ * FD32 ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0647 ARABIC LETTER HEH
+ * FD33 ARABIC LIGATURE TAH WITH MEEM INITIAL FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD34 ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062C ARABIC LETTER JEEM
+ * FD35 ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062D ARABIC LETTER HAH
+ * FD36 ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062E ARABIC LETTER KHAH
+ * FD37 ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062C ARABIC LETTER JEEM
+ * FD38 ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062D ARABIC LETTER HAH
+ * FD39 ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062E ARABIC LETTER KHAH
+ * FD3A ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD3B ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM
+ * 	0638 ARABIC LETTER ZAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD3C ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM
+ * 	0627 ARABIC LETTER ALEF
+ * FD3D ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM
+ * 	0627 ARABIC LETTER ALEF
+ * FD50 ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD51 ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062D ARABIC LETTER HAH
+ * 	062C ARABIC LETTER JEEM
+ * FD52 ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062D ARABIC LETTER HAH
+ * 	062C ARABIC LETTER JEEM
+ * FD53 ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062D ARABIC LETTER HAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD54 ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062E ARABIC LETTER KHAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD55 ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0645 ARABIC LETTER MEEM
+ * 	062C ARABIC LETTER JEEM
+ * FD56 ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FD57 ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0645 ARABIC LETTER MEEM
+ * 	062E ARABIC LETTER KHAH
+ * FD58 ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FD59 ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FD5A ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM
+ * 	062D ARABIC LETTER HAH
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FD5B ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM
+ * 	062D ARABIC LETTER HAH
+ * 	0645 ARABIC LETTER MEEM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD5C ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062D ARABIC LETTER HAH
+ * 	062C ARABIC LETTER JEEM
+ * FD5D ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062C ARABIC LETTER JEEM
+ * 	062D ARABIC LETTER HAH
+ * FD5E ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062C ARABIC LETTER JEEM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD5F ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FD60 ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FD61 ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0645 ARABIC LETTER MEEM
+ * 	062C ARABIC LETTER JEEM
+ * FD62 ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD63 ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD64 ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	062D ARABIC LETTER HAH
+ * 	062D ARABIC LETTER HAH
+ * FD65 ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	062D ARABIC LETTER HAH
+ * 	062D ARABIC LETTER HAH
+ * FD66 ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD67 ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062D ARABIC LETTER HAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD68 ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062D ARABIC LETTER HAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD69 ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062C ARABIC LETTER JEEM
+ * 	064A ARABIC LETTER YEH
+ * FD6A ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0645 ARABIC LETTER MEEM
+ * 	062E ARABIC LETTER KHAH
+ * FD6B ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0645 ARABIC LETTER MEEM
+ * 	062E ARABIC LETTER KHAH
+ * FD6C ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD6D ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD6E ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	062D ARABIC LETTER HAH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD6F ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	062E ARABIC LETTER KHAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD70 ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	062E ARABIC LETTER KHAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD71 ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FD72 ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FD73 ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD74 ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM
+ * 	0637 ARABIC LETTER TAH
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FD75 ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD76 ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD77 ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD78 ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	0645 ARABIC LETTER MEEM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD79 ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM
+ * 	063A ARABIC LETTER GHAIN
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD7A ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM
+ * 	063A ARABIC LETTER GHAIN
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FD7B ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM
+ * 	063A ARABIC LETTER GHAIN
+ * 	0645 ARABIC LETTER MEEM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD7C ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	062E ARABIC LETTER KHAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD7D ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	062E ARABIC LETTER KHAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD7E ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FD7F ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD80 ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062D ARABIC LETTER HAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD81 ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FD82 ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062D ARABIC LETTER HAH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD83 ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062C ARABIC LETTER JEEM
+ * 	062C ARABIC LETTER JEEM
+ * FD84 ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062C ARABIC LETTER JEEM
+ * 	062C ARABIC LETTER JEEM
+ * FD85 ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062E ARABIC LETTER KHAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD86 ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062E ARABIC LETTER KHAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD87 ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FD88 ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FD89 ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * 	062C ARABIC LETTER JEEM
+ * FD8A ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD8B ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FD8C ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062C ARABIC LETTER JEEM
+ * 	062D ARABIC LETTER HAH
+ * FD8D ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD8E ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062E ARABIC LETTER KHAH
+ * 	062C ARABIC LETTER JEEM
+ * FD8F ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062E ARABIC LETTER KHAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD92 ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062C ARABIC LETTER JEEM
+ * 	062E ARABIC LETTER KHAH
+ * FD93 ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM
+ * 	0647 ARABIC LETTER HEH
+ * 	0645 ARABIC LETTER MEEM
+ * 	062C ARABIC LETTER JEEM
+ * FD94 ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM
+ * 	0647 ARABIC LETTER HEH
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD95 ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062D ARABIC LETTER HAH
+ * 	0645 ARABIC LETTER MEEM
+ * FD96 ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062D ARABIC LETTER HAH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD97 ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD98 ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD99 ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062C ARABIC LETTER JEEM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD9A ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FD9B ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	0645 ARABIC LETTER MEEM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FD9C ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD9D ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FD9E ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	062E ARABIC LETTER KHAH
+ * 	064A ARABIC LETTER YEH
+ * FD9F ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062C ARABIC LETTER JEEM
+ * 	064A ARABIC LETTER YEH
+ * FDA0 ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062C ARABIC LETTER JEEM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FDA1 ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062E ARABIC LETTER KHAH
+ * 	064A ARABIC LETTER YEH
+ * FDA2 ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	062E ARABIC LETTER KHAH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FDA3 ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FDA4 ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * 	0645 ARABIC LETTER MEEM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FDA5 ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FDA6 ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	062D ARABIC LETTER HAH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FDA7 ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FDA8 ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062E ARABIC LETTER KHAH
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FDA9 ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FDAA ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FDAB ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FDAC ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062C ARABIC LETTER JEEM
+ * 	064A ARABIC LETTER YEH
+ * FDAD ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FDAE ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FDAF ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	062C ARABIC LETTER JEEM
+ * 	064A ARABIC LETTER YEH
+ * FDB0 ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FDB1 ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FDB2 ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FDB3 ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FDB4 ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * FDB5 ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062D ARABIC LETTER HAH
+ * 	0645 ARABIC LETTER MEEM
+ * FDB6 ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FDB7 ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FDB8 ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062C ARABIC LETTER JEEM
+ * 	062D ARABIC LETTER HAH
+ * FDB9 ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062E ARABIC LETTER KHAH
+ * 	064A ARABIC LETTER YEH
+ * FDBA ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FDBB ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FDBC ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FDBD ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062C ARABIC LETTER JEEM
+ * 	062D ARABIC LETTER HAH
+ * FDBE ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FDBF ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM
+ * 	062D ARABIC LETTER HAH
+ * 	062C ARABIC LETTER JEEM
+ * 	064A ARABIC LETTER YEH
+ * FDC0 ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062C ARABIC LETTER JEEM
+ * 	064A ARABIC LETTER YEH
+ * FDC1 ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM
+ * 	0641 ARABIC LETTER FEH
+ * 	0645 ARABIC LETTER MEEM
+ * 	064A ARABIC LETTER YEH
+ * FDC2 ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * 	062D ARABIC LETTER HAH
+ * 	064A ARABIC LETTER YEH
+ * FDC3 ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FDC4 ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	062C ARABIC LETTER JEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FDC5 ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	0645 ARABIC LETTER MEEM
+ * 	0645 ARABIC LETTER MEEM
+ * FDC6 ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * 	062E ARABIC LETTER KHAH
+ * 	064A ARABIC LETTER YEH
+ * FDC7 ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * 	062C ARABIC LETTER JEEM
+ * 	064A ARABIC LETTER YEH
+ * FDF0 ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	0644 ARABIC LETTER LAM
+ * 	06D2 ARABIC LETTER YEH BARREE
+ * FDF1 ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM
+ * 	0642 ARABIC LETTER QAF
+ * 	0644 ARABIC LETTER LAM
+ * 	06D2 ARABIC LETTER YEH BARREE
+ * FDF2 ARABIC LIGATURE ALLAH ISOLATED FORM
+ * 	0627 ARABIC LETTER ALEF
+ * 	0644 ARABIC LETTER LAM
+ * 	0644 ARABIC LETTER LAM
+ * 	0647 ARABIC LETTER HEH
+ * FDF3 ARABIC LIGATURE AKBAR ISOLATED FORM
+ * 	0627 ARABIC LETTER ALEF
+ * 	0643 ARABIC LETTER KAF
+ * 	0628 ARABIC LETTER BEH
+ * 	0631 ARABIC LETTER REH
+ * FDF4 ARABIC LIGATURE MOHAMMAD ISOLATED FORM
+ * 	0645 ARABIC LETTER MEEM
+ * 	062D ARABIC LETTER HAH
+ * 	0645 ARABIC LETTER MEEM
+ * 	062F ARABIC LETTER DAL
+ * FDF5 ARABIC LIGATURE SALAM ISOLATED FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	0644 ARABIC LETTER LAM
+ * 	0639 ARABIC LETTER AIN
+ * 	0645 ARABIC LETTER MEEM
+ * FDF6 ARABIC LIGATURE RASOUL ISOLATED FORM
+ * 	0631 ARABIC LETTER REH
+ * 	0633 ARABIC LETTER SEEN
+ * 	0648 ARABIC LETTER WAW
+ * 	0644 ARABIC LETTER LAM
+ * FDF7 ARABIC LIGATURE ALAYHE ISOLATED FORM
+ * 	0639 ARABIC LETTER AIN
+ * 	0644 ARABIC LETTER LAM
+ * 	064A ARABIC LETTER YEH
+ * 	0647 ARABIC LETTER HEH
+ * FDF8 ARABIC LIGATURE WASALLAM ISOLATED FORM
+ * 	0648 ARABIC LETTER WAW
+ * 	0633 ARABIC LETTER SEEN
+ * 	0644 ARABIC LETTER LAM
+ * 	0645 ARABIC LETTER MEEM
+ * FDF9 ARABIC LIGATURE SALLA ISOLATED FORM
+ * 	0635 ARABIC LETTER SAD
+ * 	0644 ARABIC LETTER LAM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FDFA ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM
+ * 	0635 ARABIC LETTER SAD
+ * 	0644 ARABIC LETTER LAM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * 	0020 SPACE
+ * 	0627 ARABIC LETTER ALEF
+ * 	0644 ARABIC LETTER LAM
+ * 	0644 ARABIC LETTER LAM
+ * 	0647 ARABIC LETTER HEH
+ * 	0020 SPACE
+ * 	0639 ARABIC LETTER AIN
+ * 	0644 ARABIC LETTER LAM
+ * 	064A ARABIC LETTER YEH
+ * 	0647 ARABIC LETTER HEH
+ * 	0020 SPACE
+ * 	0648 ARABIC LETTER WAW
+ * 	0633 ARABIC LETTER SEEN
+ * 	0644 ARABIC LETTER LAM
+ * 	0645 ARABIC LETTER MEEM
+ * FDFB ARABIC LIGATURE JALLAJALALOUHOU
+ * 	062C ARABIC LETTER JEEM
+ * 	0644 ARABIC LETTER LAM
+ * 	0020 SPACE
+ * 	062C ARABIC LETTER JEEM
+ * 	0644 ARABIC LETTER LAM
+ * 	0627 ARABIC LETTER ALEF
+ * 	0644 ARABIC LETTER LAM
+ * 	0647 ARABIC LETTER HEH
+ * FDFC RIAL SIGN
+ * 	0631 ARABIC LETTER REH
+ * 	06CC ARABIC LETTER FARSI YEH
+ * 	0627 ARABIC LETTER ALEF
+ * 	0644 ARABIC LETTER LAM
+ * FE30 PRESENTATION FORM FOR VERTICAL TWO DOT LEADER
+ * 	002E FULL STOP
+ * 	002E FULL STOP
+ * FE31 PRESENTATION FORM FOR VERTICAL EM DASH
+ * 	2014 EM DASH
+ * FE32 PRESENTATION FORM FOR VERTICAL EN DASH
+ * 	2013 EN DASH
+ * FE33 PRESENTATION FORM FOR VERTICAL LOW LINE
+ * 	005F LOW LINE
+ * FE34 PRESENTATION FORM FOR VERTICAL WAVY LOW LINE
+ * 	005F LOW LINE
+ * FE35 PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS
+ * 	0028 LEFT PARENTHESIS
+ * FE36 PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS
+ * 	0029 RIGHT PARENTHESIS
+ * FE37 PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET
+ * 	007B LEFT CURLY BRACKET
+ * FE38 PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET
+ * 	007D RIGHT CURLY BRACKET
+ * FE39 PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET
+ * 	3014 LEFT TORTOISE SHELL BRACKET
+ * FE3A PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET
+ * 	3015 RIGHT TORTOISE SHELL BRACKET
+ * FE3B PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET
+ * 	3010 LEFT BLACK LENTICULAR BRACKET
+ * FE3C PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET
+ * 	3011 RIGHT BLACK LENTICULAR BRACKET
+ * FE3D PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET
+ * 	300A LEFT DOUBLE ANGLE BRACKET
+ * FE3E PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET
+ * 	300B RIGHT DOUBLE ANGLE BRACKET
+ * FE3F PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET
+ * 	3008 LEFT ANGLE BRACKET
+ * FE40 PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET
+ * 	3009 RIGHT ANGLE BRACKET
+ * FE41 PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET
+ * 	300C LEFT CORNER BRACKET
+ * FE42 PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET
+ * 	300D RIGHT CORNER BRACKET
+ * FE43 PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET
+ * 	300E LEFT WHITE CORNER BRACKET
+ * FE44 PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET
+ * 	300F RIGHT WHITE CORNER BRACKET
+ * FE49 DASHED OVERLINE
+ * 	0020 SPACE
+ * FE4A CENTRELINE OVERLINE
+ * 	0020 SPACE
+ * FE4B WAVY OVERLINE
+ * 	0020 SPACE
+ * FE4C DOUBLE WAVY OVERLINE
+ * 	0020 SPACE
+ * FE4D DASHED LOW LINE
+ * 	005F LOW LINE
+ * FE4E CENTRELINE LOW LINE
+ * 	005F LOW LINE
+ * FE4F WAVY LOW LINE
+ * 	005F LOW LINE
+ * FE50 SMALL COMMA
+ * 	002C COMMA
+ * FE51 SMALL IDEOGRAPHIC COMMA
+ * 	3001 IDEOGRAPHIC COMMA
+ * FE52 SMALL FULL STOP
+ * 	002E FULL STOP
+ * FE54 SMALL SEMICOLON
+ * 	003B SEMICOLON
+ * FE55 SMALL COLON
+ * 	003A COLON
+ * FE56 SMALL QUESTION MARK
+ * 	003F QUESTION MARK
+ * FE57 SMALL EXCLAMATION MARK
+ * 	0021 EXCLAMATION MARK
+ * FE58 SMALL EM DASH
+ * 	2014 EM DASH
+ * FE59 SMALL LEFT PARENTHESIS
+ * 	0028 LEFT PARENTHESIS
+ * FE5A SMALL RIGHT PARENTHESIS
+ * 	0029 RIGHT PARENTHESIS
+ * FE5B SMALL LEFT CURLY BRACKET
+ * 	007B LEFT CURLY BRACKET
+ * FE5C SMALL RIGHT CURLY BRACKET
+ * 	007D RIGHT CURLY BRACKET
+ * FE5D SMALL LEFT TORTOISE SHELL BRACKET
+ * 	3014 LEFT TORTOISE SHELL BRACKET
+ * FE5E SMALL RIGHT TORTOISE SHELL BRACKET
+ * 	3015 RIGHT TORTOISE SHELL BRACKET
+ * FE5F SMALL NUMBER SIGN
+ * 	0023 NUMBER SIGN
+ * FE60 SMALL AMPERSAND
+ * 	0026 AMPERSAND
+ * FE61 SMALL ASTERISK
+ * 	002A ASTERISK
+ * FE62 SMALL PLUS SIGN
+ * 	002B PLUS SIGN
+ * FE63 SMALL HYPHEN-MINUS
+ * 	002D HYPHEN-MINUS
+ * FE64 SMALL LESS-THAN SIGN
+ * 	003C LESS-THAN SIGN
+ * FE65 SMALL GREATER-THAN SIGN
+ * 	003E GREATER-THAN SIGN
+ * FE66 SMALL EQUALS SIGN
+ * 	003D EQUALS SIGN
+ * FE68 SMALL REVERSE SOLIDUS
+ * 	005C REVERSE SOLIDUS
+ * FE69 SMALL DOLLAR SIGN
+ * 	0024 DOLLAR SIGN
+ * FE6A SMALL PERCENT SIGN
+ * 	0025 PERCENT SIGN
+ * FE6B SMALL COMMERCIAL AT
+ * 	0040 COMMERCIAL AT
+ * FE70 ARABIC FATHATAN ISOLATED FORM
+ * 	0020 SPACE
+ * FE71 ARABIC TATWEEL WITH FATHATAN ABOVE
+ * 	0640 ARABIC TATWEEL
+ * FE72 ARABIC DAMMATAN ISOLATED FORM
+ * 	0020 SPACE
+ * FE74 ARABIC KASRATAN ISOLATED FORM
+ * 	0020 SPACE
+ * FE76 ARABIC FATHA ISOLATED FORM
+ * 	0020 SPACE
+ * FE77 ARABIC FATHA MEDIAL FORM
+ * 	0640 ARABIC TATWEEL
+ * FE78 ARABIC DAMMA ISOLATED FORM
+ * 	0020 SPACE
+ * FE79 ARABIC DAMMA MEDIAL FORM
+ * 	0640 ARABIC TATWEEL
+ * FE7A ARABIC KASRA ISOLATED FORM
+ * 	0020 SPACE
+ * FE7B ARABIC KASRA MEDIAL FORM
+ * 	0640 ARABIC TATWEEL
+ * FE7C ARABIC SHADDA ISOLATED FORM
+ * 	0020 SPACE
+ * FE7D ARABIC SHADDA MEDIAL FORM
+ * 	0640 ARABIC TATWEEL
+ * FE7E ARABIC SUKUN ISOLATED FORM
+ * 	0020 SPACE
+ * FE7F ARABIC SUKUN MEDIAL FORM
+ * 	0640 ARABIC TATWEEL
+ * FE80 ARABIC LETTER HAMZA ISOLATED FORM
+ * 	0621 ARABIC LETTER HAMZA
+ * FE81 ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM
+ * 	0627 ARABIC LETTER ALEF
+ * FE82 ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
+ * 	0627 ARABIC LETTER ALEF
+ * FE83 ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM
+ * 	0627 ARABIC LETTER ALEF
+ * FE84 ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
+ * 	0627 ARABIC LETTER ALEF
+ * FE85 ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM
+ * 	0648 ARABIC LETTER WAW
+ * FE86 ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM
+ * 	0648 ARABIC LETTER WAW
+ * FE87 ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM
+ * 	0627 ARABIC LETTER ALEF
+ * FE88 ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM
+ * 	0627 ARABIC LETTER ALEF
+ * FE89 ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM
+ * 	064A ARABIC LETTER YEH
+ * FE8A ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * FE8B ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM
+ * 	064A ARABIC LETTER YEH
+ * FE8C ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM
+ * 	064A ARABIC LETTER YEH
+ * FE8D ARABIC LETTER ALEF ISOLATED FORM
+ * 	0627 ARABIC LETTER ALEF
+ * FE8E ARABIC LETTER ALEF FINAL FORM
+ * 	0627 ARABIC LETTER ALEF
+ * FE8F ARABIC LETTER BEH ISOLATED FORM
+ * 	0628 ARABIC LETTER BEH
+ * FE90 ARABIC LETTER BEH FINAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * FE91 ARABIC LETTER BEH INITIAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * FE92 ARABIC LETTER BEH MEDIAL FORM
+ * 	0628 ARABIC LETTER BEH
+ * FE93 ARABIC LETTER TEH MARBUTA ISOLATED FORM
+ * 	0629 ARABIC LETTER TEH MARBUTA
+ * FE94 ARABIC LETTER TEH MARBUTA FINAL FORM
+ * 	0629 ARABIC LETTER TEH MARBUTA
+ * FE95 ARABIC LETTER TEH ISOLATED FORM
+ * 	062A ARABIC LETTER TEH
+ * FE96 ARABIC LETTER TEH FINAL FORM
+ * 	062A ARABIC LETTER TEH
+ * FE97 ARABIC LETTER TEH INITIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * FE98 ARABIC LETTER TEH MEDIAL FORM
+ * 	062A ARABIC LETTER TEH
+ * FE99 ARABIC LETTER THEH ISOLATED FORM
+ * 	062B ARABIC LETTER THEH
+ * FE9A ARABIC LETTER THEH FINAL FORM
+ * 	062B ARABIC LETTER THEH
+ * FE9B ARABIC LETTER THEH INITIAL FORM
+ * 	062B ARABIC LETTER THEH
+ * FE9C ARABIC LETTER THEH MEDIAL FORM
+ * 	062B ARABIC LETTER THEH
+ * FE9D ARABIC LETTER JEEM ISOLATED FORM
+ * 	062C ARABIC LETTER JEEM
+ * FE9E ARABIC LETTER JEEM FINAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * FE9F ARABIC LETTER JEEM INITIAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * FEA0 ARABIC LETTER JEEM MEDIAL FORM
+ * 	062C ARABIC LETTER JEEM
+ * FEA1 ARABIC LETTER HAH ISOLATED FORM
+ * 	062D ARABIC LETTER HAH
+ * FEA2 ARABIC LETTER HAH FINAL FORM
+ * 	062D ARABIC LETTER HAH
+ * FEA3 ARABIC LETTER HAH INITIAL FORM
+ * 	062D ARABIC LETTER HAH
+ * FEA4 ARABIC LETTER HAH MEDIAL FORM
+ * 	062D ARABIC LETTER HAH
+ * FEA5 ARABIC LETTER KHAH ISOLATED FORM
+ * 	062E ARABIC LETTER KHAH
+ * FEA6 ARABIC LETTER KHAH FINAL FORM
+ * 	062E ARABIC LETTER KHAH
+ * FEA7 ARABIC LETTER KHAH INITIAL FORM
+ * 	062E ARABIC LETTER KHAH
+ * FEA8 ARABIC LETTER KHAH MEDIAL FORM
+ * 	062E ARABIC LETTER KHAH
+ * FEA9 ARABIC LETTER DAL ISOLATED FORM
+ * 	062F ARABIC LETTER DAL
+ * FEAA ARABIC LETTER DAL FINAL FORM
+ * 	062F ARABIC LETTER DAL
+ * FEAB ARABIC LETTER THAL ISOLATED FORM
+ * 	0630 ARABIC LETTER THAL
+ * FEAC ARABIC LETTER THAL FINAL FORM
+ * 	0630 ARABIC LETTER THAL
+ * FEAD ARABIC LETTER REH ISOLATED FORM
+ * 	0631 ARABIC LETTER REH
+ * FEAE ARABIC LETTER REH FINAL FORM
+ * 	0631 ARABIC LETTER REH
+ * FEAF ARABIC LETTER ZAIN ISOLATED FORM
+ * 	0632 ARABIC LETTER ZAIN
+ * FEB0 ARABIC LETTER ZAIN FINAL FORM
+ * 	0632 ARABIC LETTER ZAIN
+ * FEB1 ARABIC LETTER SEEN ISOLATED FORM
+ * 	0633 ARABIC LETTER SEEN
+ * FEB2 ARABIC LETTER SEEN FINAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * FEB3 ARABIC LETTER SEEN INITIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * FEB4 ARABIC LETTER SEEN MEDIAL FORM
+ * 	0633 ARABIC LETTER SEEN
+ * FEB5 ARABIC LETTER SHEEN ISOLATED FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * FEB6 ARABIC LETTER SHEEN FINAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * FEB7 ARABIC LETTER SHEEN INITIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * FEB8 ARABIC LETTER SHEEN MEDIAL FORM
+ * 	0634 ARABIC LETTER SHEEN
+ * FEB9 ARABIC LETTER SAD ISOLATED FORM
+ * 	0635 ARABIC LETTER SAD
+ * FEBA ARABIC LETTER SAD FINAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * FEBB ARABIC LETTER SAD INITIAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * FEBC ARABIC LETTER SAD MEDIAL FORM
+ * 	0635 ARABIC LETTER SAD
+ * FEBD ARABIC LETTER DAD ISOLATED FORM
+ * 	0636 ARABIC LETTER DAD
+ * FEBE ARABIC LETTER DAD FINAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * FEBF ARABIC LETTER DAD INITIAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * FEC0 ARABIC LETTER DAD MEDIAL FORM
+ * 	0636 ARABIC LETTER DAD
+ * FEC1 ARABIC LETTER TAH ISOLATED FORM
+ * 	0637 ARABIC LETTER TAH
+ * FEC2 ARABIC LETTER TAH FINAL FORM
+ * 	0637 ARABIC LETTER TAH
+ * FEC3 ARABIC LETTER TAH INITIAL FORM
+ * 	0637 ARABIC LETTER TAH
+ * FEC4 ARABIC LETTER TAH MEDIAL FORM
+ * 	0637 ARABIC LETTER TAH
+ * FEC5 ARABIC LETTER ZAH ISOLATED FORM
+ * 	0638 ARABIC LETTER ZAH
+ * FEC6 ARABIC LETTER ZAH FINAL FORM
+ * 	0638 ARABIC LETTER ZAH
+ * FEC7 ARABIC LETTER ZAH INITIAL FORM
+ * 	0638 ARABIC LETTER ZAH
+ * FEC8 ARABIC LETTER ZAH MEDIAL FORM
+ * 	0638 ARABIC LETTER ZAH
+ * FEC9 ARABIC LETTER AIN ISOLATED FORM
+ * 	0639 ARABIC LETTER AIN
+ * FECA ARABIC LETTER AIN FINAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * FECB ARABIC LETTER AIN INITIAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * FECC ARABIC LETTER AIN MEDIAL FORM
+ * 	0639 ARABIC LETTER AIN
+ * FECD ARABIC LETTER GHAIN ISOLATED FORM
+ * 	063A ARABIC LETTER GHAIN
+ * FECE ARABIC LETTER GHAIN FINAL FORM
+ * 	063A ARABIC LETTER GHAIN
+ * FECF ARABIC LETTER GHAIN INITIAL FORM
+ * 	063A ARABIC LETTER GHAIN
+ * FED0 ARABIC LETTER GHAIN MEDIAL FORM
+ * 	063A ARABIC LETTER GHAIN
+ * FED1 ARABIC LETTER FEH ISOLATED FORM
+ * 	0641 ARABIC LETTER FEH
+ * FED2 ARABIC LETTER FEH FINAL FORM
+ * 	0641 ARABIC LETTER FEH
+ * FED3 ARABIC LETTER FEH INITIAL FORM
+ * 	0641 ARABIC LETTER FEH
+ * FED4 ARABIC LETTER FEH MEDIAL FORM
+ * 	0641 ARABIC LETTER FEH
+ * FED5 ARABIC LETTER QAF ISOLATED FORM
+ * 	0642 ARABIC LETTER QAF
+ * FED6 ARABIC LETTER QAF FINAL FORM
+ * 	0642 ARABIC LETTER QAF
+ * FED7 ARABIC LETTER QAF INITIAL FORM
+ * 	0642 ARABIC LETTER QAF
+ * FED8 ARABIC LETTER QAF MEDIAL FORM
+ * 	0642 ARABIC LETTER QAF
+ * FED9 ARABIC LETTER KAF ISOLATED FORM
+ * 	0643 ARABIC LETTER KAF
+ * FEDA ARABIC LETTER KAF FINAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * FEDB ARABIC LETTER KAF INITIAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * FEDC ARABIC LETTER KAF MEDIAL FORM
+ * 	0643 ARABIC LETTER KAF
+ * FEDD ARABIC LETTER LAM ISOLATED FORM
+ * 	0644 ARABIC LETTER LAM
+ * FEDE ARABIC LETTER LAM FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * FEDF ARABIC LETTER LAM INITIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * FEE0 ARABIC LETTER LAM MEDIAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * FEE1 ARABIC LETTER MEEM ISOLATED FORM
+ * 	0645 ARABIC LETTER MEEM
+ * FEE2 ARABIC LETTER MEEM FINAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * FEE3 ARABIC LETTER MEEM INITIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * FEE4 ARABIC LETTER MEEM MEDIAL FORM
+ * 	0645 ARABIC LETTER MEEM
+ * FEE5 ARABIC LETTER NOON ISOLATED FORM
+ * 	0646 ARABIC LETTER NOON
+ * FEE6 ARABIC LETTER NOON FINAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * FEE7 ARABIC LETTER NOON INITIAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * FEE8 ARABIC LETTER NOON MEDIAL FORM
+ * 	0646 ARABIC LETTER NOON
+ * FEE9 ARABIC LETTER HEH ISOLATED FORM
+ * 	0647 ARABIC LETTER HEH
+ * FEEA ARABIC LETTER HEH FINAL FORM
+ * 	0647 ARABIC LETTER HEH
+ * FEEB ARABIC LETTER HEH INITIAL FORM
+ * 	0647 ARABIC LETTER HEH
+ * FEEC ARABIC LETTER HEH MEDIAL FORM
+ * 	0647 ARABIC LETTER HEH
+ * FEED ARABIC LETTER WAW ISOLATED FORM
+ * 	0648 ARABIC LETTER WAW
+ * FEEE ARABIC LETTER WAW FINAL FORM
+ * 	0648 ARABIC LETTER WAW
+ * FEEF ARABIC LETTER ALEF MAKSURA ISOLATED FORM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FEF0 ARABIC LETTER ALEF MAKSURA FINAL FORM
+ * 	0649 ARABIC LETTER ALEF MAKSURA
+ * FEF1 ARABIC LETTER YEH ISOLATED FORM
+ * 	064A ARABIC LETTER YEH
+ * FEF2 ARABIC LETTER YEH FINAL FORM
+ * 	064A ARABIC LETTER YEH
+ * FEF3 ARABIC LETTER YEH INITIAL FORM
+ * 	064A ARABIC LETTER YEH
+ * FEF4 ARABIC LETTER YEH MEDIAL FORM
+ * 	064A ARABIC LETTER YEH
+ * FEF5 ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0627 ARABIC LETTER ALEF
+ * FEF6 ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0627 ARABIC LETTER ALEF
+ * FEF7 ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0627 ARABIC LETTER ALEF
+ * FEF8 ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0627 ARABIC LETTER ALEF
+ * FEF9 ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0627 ARABIC LETTER ALEF
+ * FEFA ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0627 ARABIC LETTER ALEF
+ * FEFB ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0627 ARABIC LETTER ALEF
+ * FEFC ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+ * 	0644 ARABIC LETTER LAM
+ * 	0627 ARABIC LETTER ALEF
+ * FF01 FULLWIDTH EXCLAMATION MARK
+ * 	0021 EXCLAMATION MARK
+ * FF02 FULLWIDTH QUOTATION MARK
+ * 	0022 QUOTATION MARK
+ * FF03 FULLWIDTH NUMBER SIGN
+ * 	0023 NUMBER SIGN
+ * FF04 FULLWIDTH DOLLAR SIGN
+ * 	0024 DOLLAR SIGN
+ * FF05 FULLWIDTH PERCENT SIGN
+ * 	0025 PERCENT SIGN
+ * FF06 FULLWIDTH AMPERSAND
+ * 	0026 AMPERSAND
+ * FF07 FULLWIDTH APOSTROPHE
+ * 	0027 APOSTROPHE
+ * FF08 FULLWIDTH LEFT PARENTHESIS
+ * 	0028 LEFT PARENTHESIS
+ * FF09 FULLWIDTH RIGHT PARENTHESIS
+ * 	0029 RIGHT PARENTHESIS
+ * FF0A FULLWIDTH ASTERISK
+ * 	002A ASTERISK
+ * FF0B FULLWIDTH PLUS SIGN
+ * 	002B PLUS SIGN
+ * FF0C FULLWIDTH COMMA
+ * 	002C COMMA
+ * FF0D FULLWIDTH HYPHEN-MINUS
+ * 	002D HYPHEN-MINUS
+ * FF0E FULLWIDTH FULL STOP
+ * 	002E FULL STOP
+ * FF0F FULLWIDTH SOLIDUS
+ * 	002F SOLIDUS
+ * FF10 FULLWIDTH DIGIT ZERO
+ * 	0030 DIGIT ZERO
+ * FF11 FULLWIDTH DIGIT ONE
+ * 	0031 DIGIT ONE
+ * FF12 FULLWIDTH DIGIT TWO
+ * 	0032 DIGIT TWO
+ * FF13 FULLWIDTH DIGIT THREE
+ * 	0033 DIGIT THREE
+ * FF14 FULLWIDTH DIGIT FOUR
+ * 	0034 DIGIT FOUR
+ * FF15 FULLWIDTH DIGIT FIVE
+ * 	0035 DIGIT FIVE
+ * FF16 FULLWIDTH DIGIT SIX
+ * 	0036 DIGIT SIX
+ * FF17 FULLWIDTH DIGIT SEVEN
+ * 	0037 DIGIT SEVEN
+ * FF18 FULLWIDTH DIGIT EIGHT
+ * 	0038 DIGIT EIGHT
+ * FF19 FULLWIDTH DIGIT NINE
+ * 	0039 DIGIT NINE
+ * FF1A FULLWIDTH COLON
+ * 	003A COLON
+ * FF1B FULLWIDTH SEMICOLON
+ * 	003B SEMICOLON
+ * FF1C FULLWIDTH LESS-THAN SIGN
+ * 	003C LESS-THAN SIGN
+ * FF1D FULLWIDTH EQUALS SIGN
+ * 	003D EQUALS SIGN
+ * FF1E FULLWIDTH GREATER-THAN SIGN
+ * 	003E GREATER-THAN SIGN
+ * FF1F FULLWIDTH QUESTION MARK
+ * 	003F QUESTION MARK
+ * FF20 FULLWIDTH COMMERCIAL AT
+ * 	0040 COMMERCIAL AT
+ * FF21 FULLWIDTH LATIN CAPITAL LETTER A
+ * 	0041 LATIN CAPITAL LETTER A
+ * FF22 FULLWIDTH LATIN CAPITAL LETTER B
+ * 	0042 LATIN CAPITAL LETTER B
+ * FF23 FULLWIDTH LATIN CAPITAL LETTER C
+ * 	0043 LATIN CAPITAL LETTER C
+ * FF24 FULLWIDTH LATIN CAPITAL LETTER D
+ * 	0044 LATIN CAPITAL LETTER D
+ * FF25 FULLWIDTH LATIN CAPITAL LETTER E
+ * 	0045 LATIN CAPITAL LETTER E
+ * FF26 FULLWIDTH LATIN CAPITAL LETTER F
+ * 	0046 LATIN CAPITAL LETTER F
+ * FF27 FULLWIDTH LATIN CAPITAL LETTER G
+ * 	0047 LATIN CAPITAL LETTER G
+ * FF28 FULLWIDTH LATIN CAPITAL LETTER H
+ * 	0048 LATIN CAPITAL LETTER H
+ * FF29 FULLWIDTH LATIN CAPITAL LETTER I
+ * 	0049 LATIN CAPITAL LETTER I
+ * FF2A FULLWIDTH LATIN CAPITAL LETTER J
+ * 	004A LATIN CAPITAL LETTER J
+ * FF2B FULLWIDTH LATIN CAPITAL LETTER K
+ * 	004B LATIN CAPITAL LETTER K
+ * FF2C FULLWIDTH LATIN CAPITAL LETTER L
+ * 	004C LATIN CAPITAL LETTER L
+ * FF2D FULLWIDTH LATIN CAPITAL LETTER M
+ * 	004D LATIN CAPITAL LETTER M
+ * FF2E FULLWIDTH LATIN CAPITAL LETTER N
+ * 	004E LATIN CAPITAL LETTER N
+ * FF2F FULLWIDTH LATIN CAPITAL LETTER O
+ * 	004F LATIN CAPITAL LETTER O
+ * FF30 FULLWIDTH LATIN CAPITAL LETTER P
+ * 	0050 LATIN CAPITAL LETTER P
+ * FF31 FULLWIDTH LATIN CAPITAL LETTER Q
+ * 	0051 LATIN CAPITAL LETTER Q
+ * FF32 FULLWIDTH LATIN CAPITAL LETTER R
+ * 	0052 LATIN CAPITAL LETTER R
+ * FF33 FULLWIDTH LATIN CAPITAL LETTER S
+ * 	0053 LATIN CAPITAL LETTER S
+ * FF34 FULLWIDTH LATIN CAPITAL LETTER T
+ * 	0054 LATIN CAPITAL LETTER T
+ * FF35 FULLWIDTH LATIN CAPITAL LETTER U
+ * 	0055 LATIN CAPITAL LETTER U
+ * FF36 FULLWIDTH LATIN CAPITAL LETTER V
+ * 	0056 LATIN CAPITAL LETTER V
+ * FF37 FULLWIDTH LATIN CAPITAL LETTER W
+ * 	0057 LATIN CAPITAL LETTER W
+ * FF38 FULLWIDTH LATIN CAPITAL LETTER X
+ * 	0058 LATIN CAPITAL LETTER X
+ * FF39 FULLWIDTH LATIN CAPITAL LETTER Y
+ * 	0059 LATIN CAPITAL LETTER Y
+ * FF3A FULLWIDTH LATIN CAPITAL LETTER Z
+ * 	005A LATIN CAPITAL LETTER Z
+ * FF3B FULLWIDTH LEFT SQUARE BRACKET
+ * 	005B LEFT SQUARE BRACKET
+ * FF3C FULLWIDTH REVERSE SOLIDUS
+ * 	005C REVERSE SOLIDUS
+ * FF3D FULLWIDTH RIGHT SQUARE BRACKET
+ * 	005D RIGHT SQUARE BRACKET
+ * FF3E FULLWIDTH CIRCUMFLEX ACCENT
+ * 	005E CIRCUMFLEX ACCENT
+ * FF3F FULLWIDTH LOW LINE
+ * 	005F LOW LINE
+ * FF40 FULLWIDTH GRAVE ACCENT
+ * 	0060 GRAVE ACCENT
+ * FF41 FULLWIDTH LATIN SMALL LETTER A
+ * 	0061 LATIN SMALL LETTER A
+ * FF42 FULLWIDTH LATIN SMALL LETTER B
+ * 	0062 LATIN SMALL LETTER B
+ * FF43 FULLWIDTH LATIN SMALL LETTER C
+ * 	0063 LATIN SMALL LETTER C
+ * FF44 FULLWIDTH LATIN SMALL LETTER D
+ * 	0064 LATIN SMALL LETTER D
+ * FF45 FULLWIDTH LATIN SMALL LETTER E
+ * 	0065 LATIN SMALL LETTER E
+ * FF46 FULLWIDTH LATIN SMALL LETTER F
+ * 	0066 LATIN SMALL LETTER F
+ * FF47 FULLWIDTH LATIN SMALL LETTER G
+ * 	0067 LATIN SMALL LETTER G
+ * FF48 FULLWIDTH LATIN SMALL LETTER H
+ * 	0068 LATIN SMALL LETTER H
+ * FF49 FULLWIDTH LATIN SMALL LETTER I
+ * 	0069 LATIN SMALL LETTER I
+ * FF4A FULLWIDTH LATIN SMALL LETTER J
+ * 	006A LATIN SMALL LETTER J
+ * FF4B FULLWIDTH LATIN SMALL LETTER K
+ * 	006B LATIN SMALL LETTER K
+ * FF4C FULLWIDTH LATIN SMALL LETTER L
+ * 	006C LATIN SMALL LETTER L
+ * FF4D FULLWIDTH LATIN SMALL LETTER M
+ * 	006D LATIN SMALL LETTER M
+ * FF4E FULLWIDTH LATIN SMALL LETTER N
+ * 	006E LATIN SMALL LETTER N
+ * FF4F FULLWIDTH LATIN SMALL LETTER O
+ * 	006F LATIN SMALL LETTER O
+ * FF50 FULLWIDTH LATIN SMALL LETTER P
+ * 	0070 LATIN SMALL LETTER P
+ * FF51 FULLWIDTH LATIN SMALL LETTER Q
+ * 	0071 LATIN SMALL LETTER Q
+ * FF52 FULLWIDTH LATIN SMALL LETTER R
+ * 	0072 LATIN SMALL LETTER R
+ * FF53 FULLWIDTH LATIN SMALL LETTER S
+ * 	0073 LATIN SMALL LETTER S
+ * FF54 FULLWIDTH LATIN SMALL LETTER T
+ * 	0074 LATIN SMALL LETTER T
+ * FF55 FULLWIDTH LATIN SMALL LETTER U
+ * 	0075 LATIN SMALL LETTER U
+ * FF56 FULLWIDTH LATIN SMALL LETTER V
+ * 	0076 LATIN SMALL LETTER V
+ * FF57 FULLWIDTH LATIN SMALL LETTER W
+ * 	0077 LATIN SMALL LETTER W
+ * FF58 FULLWIDTH LATIN SMALL LETTER X
+ * 	0078 LATIN SMALL LETTER X
+ * FF59 FULLWIDTH LATIN SMALL LETTER Y
+ * 	0079 LATIN SMALL LETTER Y
+ * FF5A FULLWIDTH LATIN SMALL LETTER Z
+ * 	007A LATIN SMALL LETTER Z
+ * FF5B FULLWIDTH LEFT CURLY BRACKET
+ * 	007B LEFT CURLY BRACKET
+ * FF5C FULLWIDTH VERTICAL LINE
+ * 	007C VERTICAL LINE
+ * FF5D FULLWIDTH RIGHT CURLY BRACKET
+ * 	007D RIGHT CURLY BRACKET
+ * FF5E FULLWIDTH TILDE
+ * 	007E TILDE
+ * FF5F FULLWIDTH LEFT WHITE PARENTHESIS
+ * 	2985 LEFT WHITE PARENTHESIS
+ * FF60 FULLWIDTH RIGHT WHITE PARENTHESIS
+ * 	2986 RIGHT WHITE PARENTHESIS
+ * FF61 HALFWIDTH IDEOGRAPHIC FULL STOP
+ * 	3002 IDEOGRAPHIC FULL STOP
+ * FF62 HALFWIDTH LEFT CORNER BRACKET
+ * 	300C LEFT CORNER BRACKET
+ * FF63 HALFWIDTH RIGHT CORNER BRACKET
+ * 	300D RIGHT CORNER BRACKET
+ * FF64 HALFWIDTH IDEOGRAPHIC COMMA
+ * 	3001 IDEOGRAPHIC COMMA
+ * FF65 HALFWIDTH KATAKANA MIDDLE DOT
+ * 	30FB KATAKANA MIDDLE DOT
+ * FF66 HALFWIDTH KATAKANA LETTER WO
+ * 	30F2 KATAKANA LETTER WO
+ * FF67 HALFWIDTH KATAKANA LETTER SMALL A
+ * 	30A1 KATAKANA LETTER SMALL A
+ * FF68 HALFWIDTH KATAKANA LETTER SMALL I
+ * 	30A3 KATAKANA LETTER SMALL I
+ * FF69 HALFWIDTH KATAKANA LETTER SMALL U
+ * 	30A5 KATAKANA LETTER SMALL U
+ * FF6A HALFWIDTH KATAKANA LETTER SMALL E
+ * 	30A7 KATAKANA LETTER SMALL E
+ * FF6B HALFWIDTH KATAKANA LETTER SMALL O
+ * 	30A9 KATAKANA LETTER SMALL O
+ * FF6C HALFWIDTH KATAKANA LETTER SMALL YA
+ * 	30E3 KATAKANA LETTER SMALL YA
+ * FF6D HALFWIDTH KATAKANA LETTER SMALL YU
+ * 	30E5 KATAKANA LETTER SMALL YU
+ * FF6E HALFWIDTH KATAKANA LETTER SMALL YO
+ * 	30E7 KATAKANA LETTER SMALL YO
+ * FF6F HALFWIDTH KATAKANA LETTER SMALL TU
+ * 	30C3 KATAKANA LETTER SMALL TU
+ * FF70 HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * 	30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ * FF71 HALFWIDTH KATAKANA LETTER A
+ * 	30A2 KATAKANA LETTER A
+ * FF72 HALFWIDTH KATAKANA LETTER I
+ * 	30A4 KATAKANA LETTER I
+ * FF73 HALFWIDTH KATAKANA LETTER U
+ * 	30A6 KATAKANA LETTER U
+ * FF74 HALFWIDTH KATAKANA LETTER E
+ * 	30A8 KATAKANA LETTER E
+ * FF75 HALFWIDTH KATAKANA LETTER O
+ * 	30AA KATAKANA LETTER O
+ * FF76 HALFWIDTH KATAKANA LETTER KA
+ * 	30AB KATAKANA LETTER KA
+ * FF77 HALFWIDTH KATAKANA LETTER KI
+ * 	30AD KATAKANA LETTER KI
+ * FF78 HALFWIDTH KATAKANA LETTER KU
+ * 	30AF KATAKANA LETTER KU
+ * FF79 HALFWIDTH KATAKANA LETTER KE
+ * 	30B1 KATAKANA LETTER KE
+ * FF7A HALFWIDTH KATAKANA LETTER KO
+ * 	30B3 KATAKANA LETTER KO
+ * FF7B HALFWIDTH KATAKANA LETTER SA
+ * 	30B5 KATAKANA LETTER SA
+ * FF7C HALFWIDTH KATAKANA LETTER SI
+ * 	30B7 KATAKANA LETTER SI
+ * FF7D HALFWIDTH KATAKANA LETTER SU
+ * 	30B9 KATAKANA LETTER SU
+ * FF7E HALFWIDTH KATAKANA LETTER SE
+ * 	30BB KATAKANA LETTER SE
+ * FF7F HALFWIDTH KATAKANA LETTER SO
+ * 	30BD KATAKANA LETTER SO
+ * FF80 HALFWIDTH KATAKANA LETTER TA
+ * 	30BF KATAKANA LETTER TA
+ * FF81 HALFWIDTH KATAKANA LETTER TI
+ * 	30C1 KATAKANA LETTER TI
+ * FF82 HALFWIDTH KATAKANA LETTER TU
+ * 	30C4 KATAKANA LETTER TU
+ * FF83 HALFWIDTH KATAKANA LETTER TE
+ * 	30C6 KATAKANA LETTER TE
+ * FF84 HALFWIDTH KATAKANA LETTER TO
+ * 	30C8 KATAKANA LETTER TO
+ * FF85 HALFWIDTH KATAKANA LETTER NA
+ * 	30CA KATAKANA LETTER NA
+ * FF86 HALFWIDTH KATAKANA LETTER NI
+ * 	30CB KATAKANA LETTER NI
+ * FF87 HALFWIDTH KATAKANA LETTER NU
+ * 	30CC KATAKANA LETTER NU
+ * FF88 HALFWIDTH KATAKANA LETTER NE
+ * 	30CD KATAKANA LETTER NE
+ * FF89 HALFWIDTH KATAKANA LETTER NO
+ * 	30CE KATAKANA LETTER NO
+ * FF8A HALFWIDTH KATAKANA LETTER HA
+ * 	30CF KATAKANA LETTER HA
+ * FF8B HALFWIDTH KATAKANA LETTER HI
+ * 	30D2 KATAKANA LETTER HI
+ * FF8C HALFWIDTH KATAKANA LETTER HU
+ * 	30D5 KATAKANA LETTER HU
+ * FF8D HALFWIDTH KATAKANA LETTER HE
+ * 	30D8 KATAKANA LETTER HE
+ * FF8E HALFWIDTH KATAKANA LETTER HO
+ * 	30DB KATAKANA LETTER HO
+ * FF8F HALFWIDTH KATAKANA LETTER MA
+ * 	30DE KATAKANA LETTER MA
+ * FF90 HALFWIDTH KATAKANA LETTER MI
+ * 	30DF KATAKANA LETTER MI
+ * FF91 HALFWIDTH KATAKANA LETTER MU
+ * 	30E0 KATAKANA LETTER MU
+ * FF92 HALFWIDTH KATAKANA LETTER ME
+ * 	30E1 KATAKANA LETTER ME
+ * FF93 HALFWIDTH KATAKANA LETTER MO
+ * 	30E2 KATAKANA LETTER MO
+ * FF94 HALFWIDTH KATAKANA LETTER YA
+ * 	30E4 KATAKANA LETTER YA
+ * FF95 HALFWIDTH KATAKANA LETTER YU
+ * 	30E6 KATAKANA LETTER YU
+ * FF96 HALFWIDTH KATAKANA LETTER YO
+ * 	30E8 KATAKANA LETTER YO
+ * FF97 HALFWIDTH KATAKANA LETTER RA
+ * 	30E9 KATAKANA LETTER RA
+ * FF98 HALFWIDTH KATAKANA LETTER RI
+ * 	30EA KATAKANA LETTER RI
+ * FF99 HALFWIDTH KATAKANA LETTER RU
+ * 	30EB KATAKANA LETTER RU
+ * FF9A HALFWIDTH KATAKANA LETTER RE
+ * 	30EC KATAKANA LETTER RE
+ * FF9B HALFWIDTH KATAKANA LETTER RO
+ * 	30ED KATAKANA LETTER RO
+ * FF9C HALFWIDTH KATAKANA LETTER WA
+ * 	30EF KATAKANA LETTER WA
+ * FF9D HALFWIDTH KATAKANA LETTER N
+ * 	30F3 KATAKANA LETTER N
+ * FFA0 HALFWIDTH HANGUL FILLER
+ * 	1160 HANGUL JUNGSEONG FILLER
+ * FFA1 HALFWIDTH HANGUL LETTER KIYEOK
+ * 	1100 HANGUL CHOSEONG KIYEOK
+ * FFA2 HALFWIDTH HANGUL LETTER SSANGKIYEOK
+ * 	1101 HANGUL CHOSEONG SSANGKIYEOK
+ * FFA3 HALFWIDTH HANGUL LETTER KIYEOK-SIOS
+ * 	11AA HANGUL JONGSEONG KIYEOK-SIOS
+ * FFA4 HALFWIDTH HANGUL LETTER NIEUN
+ * 	1102 HANGUL CHOSEONG NIEUN
+ * FFA5 HALFWIDTH HANGUL LETTER NIEUN-CIEUC
+ * 	11AC HANGUL JONGSEONG NIEUN-CIEUC
+ * FFA6 HALFWIDTH HANGUL LETTER NIEUN-HIEUH
+ * 	11AD HANGUL JONGSEONG NIEUN-HIEUH
+ * FFA7 HALFWIDTH HANGUL LETTER TIKEUT
+ * 	1103 HANGUL CHOSEONG TIKEUT
+ * FFA8 HALFWIDTH HANGUL LETTER SSANGTIKEUT
+ * 	1104 HANGUL CHOSEONG SSANGTIKEUT
+ * FFA9 HALFWIDTH HANGUL LETTER RIEUL
+ * 	1105 HANGUL CHOSEONG RIEUL
+ * FFAA HALFWIDTH HANGUL LETTER RIEUL-KIYEOK
+ * 	11B0 HANGUL JONGSEONG RIEUL-KIYEOK
+ * FFAB HALFWIDTH HANGUL LETTER RIEUL-MIEUM
+ * 	11B1 HANGUL JONGSEONG RIEUL-MIEUM
+ * FFAC HALFWIDTH HANGUL LETTER RIEUL-PIEUP
+ * 	11B2 HANGUL JONGSEONG RIEUL-PIEUP
+ * FFAD HALFWIDTH HANGUL LETTER RIEUL-SIOS
+ * 	11B3 HANGUL JONGSEONG RIEUL-SIOS
+ * FFAE HALFWIDTH HANGUL LETTER RIEUL-THIEUTH
+ * 	11B4 HANGUL JONGSEONG RIEUL-THIEUTH
+ * FFAF HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH
+ * 	11B5 HANGUL JONGSEONG RIEUL-PHIEUPH
+ * FFB0 HALFWIDTH HANGUL LETTER RIEUL-HIEUH
+ * 	111A HANGUL CHOSEONG RIEUL-HIEUH
+ * FFB1 HALFWIDTH HANGUL LETTER MIEUM
+ * 	1106 HANGUL CHOSEONG MIEUM
+ * FFB2 HALFWIDTH HANGUL LETTER PIEUP
+ * 	1107 HANGUL CHOSEONG PIEUP
+ * FFB3 HALFWIDTH HANGUL LETTER SSANGPIEUP
+ * 	1108 HANGUL CHOSEONG SSANGPIEUP
+ * FFB4 HALFWIDTH HANGUL LETTER PIEUP-SIOS
+ * 	1121 HANGUL CHOSEONG PIEUP-SIOS
+ * FFB5 HALFWIDTH HANGUL LETTER SIOS
+ * 	1109 HANGUL CHOSEONG SIOS
+ * FFB6 HALFWIDTH HANGUL LETTER SSANGSIOS
+ * 	110A HANGUL CHOSEONG SSANGSIOS
+ * FFB7 HALFWIDTH HANGUL LETTER IEUNG
+ * 	110B HANGUL CHOSEONG IEUNG
+ * FFB8 HALFWIDTH HANGUL LETTER CIEUC
+ * 	110C HANGUL CHOSEONG CIEUC
+ * FFB9 HALFWIDTH HANGUL LETTER SSANGCIEUC
+ * 	110D HANGUL CHOSEONG SSANGCIEUC
+ * FFBA HALFWIDTH HANGUL LETTER CHIEUCH
+ * 	110E HANGUL CHOSEONG CHIEUCH
+ * FFBB HALFWIDTH HANGUL LETTER KHIEUKH
+ * 	110F HANGUL CHOSEONG KHIEUKH
+ * FFBC HALFWIDTH HANGUL LETTER THIEUTH
+ * 	1110 HANGUL CHOSEONG THIEUTH
+ * FFBD HALFWIDTH HANGUL LETTER PHIEUPH
+ * 	1111 HANGUL CHOSEONG PHIEUPH
+ * FFBE HALFWIDTH HANGUL LETTER HIEUH
+ * 	1112 HANGUL CHOSEONG HIEUH
+ * FFC2 HALFWIDTH HANGUL LETTER A
+ * 	1161 HANGUL JUNGSEONG A
+ * FFC3 HALFWIDTH HANGUL LETTER AE
+ * 	1162 HANGUL JUNGSEONG AE
+ * FFC4 HALFWIDTH HANGUL LETTER YA
+ * 	1163 HANGUL JUNGSEONG YA
+ * FFC5 HALFWIDTH HANGUL LETTER YAE
+ * 	1164 HANGUL JUNGSEONG YAE
+ * FFC6 HALFWIDTH HANGUL LETTER EO
+ * 	1165 HANGUL JUNGSEONG EO
+ * FFC7 HALFWIDTH HANGUL LETTER E
+ * 	1166 HANGUL JUNGSEONG E
+ * FFCA HALFWIDTH HANGUL LETTER YEO
+ * 	1167 HANGUL JUNGSEONG YEO
+ * FFCB HALFWIDTH HANGUL LETTER YE
+ * 	1168 HANGUL JUNGSEONG YE
+ * FFCC HALFWIDTH HANGUL LETTER O
+ * 	1169 HANGUL JUNGSEONG O
+ * FFCD HALFWIDTH HANGUL LETTER WA
+ * 	116A HANGUL JUNGSEONG WA
+ * FFCE HALFWIDTH HANGUL LETTER WAE
+ * 	116B HANGUL JUNGSEONG WAE
+ * FFCF HALFWIDTH HANGUL LETTER OE
+ * 	116C HANGUL JUNGSEONG OE
+ * FFD2 HALFWIDTH HANGUL LETTER YO
+ * 	116D HANGUL JUNGSEONG YO
+ * FFD3 HALFWIDTH HANGUL LETTER U
+ * 	116E HANGUL JUNGSEONG U
+ * FFD4 HALFWIDTH HANGUL LETTER WEO
+ * 	116F HANGUL JUNGSEONG WEO
+ * FFD5 HALFWIDTH HANGUL LETTER WE
+ * 	1170 HANGUL JUNGSEONG WE
+ * FFD6 HALFWIDTH HANGUL LETTER WI
+ * 	1171 HANGUL JUNGSEONG WI
+ * FFD7 HALFWIDTH HANGUL LETTER YU
+ * 	1172 HANGUL JUNGSEONG YU
+ * FFDA HALFWIDTH HANGUL LETTER EU
+ * 	1173 HANGUL JUNGSEONG EU
+ * FFDB HALFWIDTH HANGUL LETTER YI
+ * 	1174 HANGUL JUNGSEONG YI
+ * FFDC HALFWIDTH HANGUL LETTER I
+ * 	1175 HANGUL JUNGSEONG I
+ * FFE0 FULLWIDTH CENT SIGN
+ * 	00A2 CENT SIGN
+ * FFE1 FULLWIDTH POUND SIGN
+ * 	00A3 POUND SIGN
+ * FFE2 FULLWIDTH NOT SIGN
+ * 	00AC NOT SIGN
+ * FFE3 FULLWIDTH MACRON
+ * 	0020 SPACE
+ * FFE4 FULLWIDTH BROKEN BAR
+ * 	00A6 BROKEN BAR
+ * FFE5 FULLWIDTH YEN SIGN
+ * 	00A5 YEN SIGN
+ * FFE6 FULLWIDTH WON SIGN
+ * 	20A9 WON SIGN
+ * FFE8 HALFWIDTH FORMS LIGHT VERTICAL
+ * 	2502 BOX DRAWINGS LIGHT VERTICAL
+ * FFE9 HALFWIDTH LEFTWARDS ARROW
+ * 	2190 LEFTWARDS ARROW
+ * FFEA HALFWIDTH UPWARDS ARROW
+ * 	2191 UPWARDS ARROW
+ * FFEB HALFWIDTH RIGHTWARDS ARROW
+ * 	2192 RIGHTWARDS ARROW
+ * FFEC HALFWIDTH DOWNWARDS ARROW
+ * 	2193 DOWNWARDS ARROW
+ * FFED HALFWIDTH BLACK SQUARE
+ * 	25A0 BLACK SQUARE
+ * FFEE HALFWIDTH WHITE CIRCLE
+ * 	25CB WHITE CIRCLE
+*/
+
+unsigned short unac_indexes[UNAC_INDEXES_SIZE] = {
+   0,   0,   0,   0,   0,   1,   2,   3,   4,   5,   6,   7,   0,   8,   9,
+  10,  11,  12,   0,   0,   0,  13,  14,  15,   0,   0,   0,  16,  17,  18,
+  19,  20,  21,  22,  23,  24,   0,   0,  25,  26,   0,   0,   0,   0,  27,
+   0,   0,   0,   0,  28,   0,  29,   0,   0,  30,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  31,  32,
+   0,   0,   0,  33,   0,   0,  34,  35,   0,   0,   0,   0,   0,   0,   0,
+  36,   0,  37,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,  38,   0,   0,   0,  39,  40,   0,
+  41,   0,  42,  43,   0,   0,   0,   0,   0,  44,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
+  60,  61,  62,  63,  64,  65,  66,   0,   0,  67,  68,  69,  70,  71,  72,
+  73,   0,  74,  75,  76,  77,  78,  79,   0,  80,   0,  81,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,  82,  83,  84,  85,  86,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,  87,   0,   0,  88,   0,   0,  89,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  90,   0,   0,
+  91,  92,  93,  94,  95,  96,  97,  98,   0,  99, 100, 101, 102, 103, 104,
+ 105, 106,   0, 107, 108, 109, 110,   0,   0,   0, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138,   0,   0,   0,   0, 139, 140,
+ 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162,   0, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177
+};
+
+unsigned char unac_positions[UNAC_BLOCK_COUNT][UNAC_BLOCK_SIZE + 1] = {
+/* 0 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 1 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 31, 34, 37, 38 },
+/* 2 */ { 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33 },
+/* 3 */ { 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33 },
+/* 4 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 5 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35 },
+/* 6 */ { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34 },
+/* 7 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 8 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 9 */ { 0, 1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41 },
+/* 10 */ { 0, 1, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 37, 38, 39 },
+/* 11 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 12 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 13 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 14 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 15 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 16 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 17 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 18 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 19 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 20 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 21 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 22 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 23 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 24 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 25 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 26 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 27 */ { 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33 },
+/* 28 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 29 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 27, 29, 30, 31, 32, 33, 34, 35, 36 },
+/* 30 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 31 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 32 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 33 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 34 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 35 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 36 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 37 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 38 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 39 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 40 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 32, 33, 34 },
+/* 41 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 42 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 43 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 44 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 45 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 46 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 47 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 48 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 49 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 29, 30, 31, 32, 33 },
+/* 50 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 51 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 52 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 53 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 54 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 55 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 56 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 57 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 58 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 59 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 60 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 61 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 62 */ { 0, 1, 2, 3, 4, 5, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 27, 28, 30, 33, 34, 35, 36, 37, 39, 40, 41, 42 },
+/* 63 */ { 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 30, 31, 32, 33, 34, 35, 36, 37, 38 },
+/* 64 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 65 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 66 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33 },
+/* 67 */ { 0, 3, 6, 7, 9, 10, 13, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43 },
+/* 68 */ { 0, 2, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36 },
+/* 69 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 57 },
+/* 70 */ { 0, 1, 3, 6, 8, 9, 11, 14, 18, 20, 21, 23, 26, 27, 28, 29, 30, 31, 33, 36, 38, 39, 41, 44, 48, 50, 51, 53, 56, 57, 58, 59, 60 },
+/* 71 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 72 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 73 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 74 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 75 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 17, 18, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38 },
+/* 76 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 77 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 78 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 79 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 80 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 81 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 82 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 62, 66, 70 },
+/* 83 */ { 0, 4, 8, 12, 16, 20, 24, 28, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95 },
+/* 84 */ { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76 },
+/* 85 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 86 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 87 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 },
+/* 88 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 23, 25, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37 },
+/* 89 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 90 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 91 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 92 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 93 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 94 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 95 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 96 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 97 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 98 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 99 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 100 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 101 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 102 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 103 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33 },
+/* 104 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 105 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 106 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33 },
+/* 107 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 108 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 109 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 110 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 111 */ { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 46, 50, 54, 58, 62, 66, 70, 74, 78, 82, 86, 90, 94, 98, 102, 103, 104, 105 },
+/* 112 */ { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96 },
+/* 113 */ { 0, 3, 6, 9, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55 },
+/* 114 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 43, 44, 45, 46 },
+/* 115 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 116 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47 },
+/* 117 */ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 21, 24, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47 },
+/* 118 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 119 */ { 0, 4, 8, 12, 15, 19, 22, 25, 30, 34, 37, 40, 43, 47, 51, 54, 57, 59, 62, 66, 70, 72, 77, 83, 88, 91, 96, 101, 105, 108, 111, 114, 118 },
+/* 120 */ { 0, 5, 9, 12, 15, 18, 20, 22, 24, 26, 29, 32, 37, 40, 44, 49, 52, 54, 56, 61, 65, 70, 73, 78, 80, 83, 86, 89, 92, 95, 99, 102, 104 },
+/* 121 */ { 0, 3, 6, 9, 13, 16, 19, 22, 27, 31, 33, 38, 40, 44, 48, 51, 54, 57, 61, 63, 66, 70, 72, 77, 80, 82, 84, 86, 88, 90, 92, 94, 96 },
+/* 122 */ { 0, 2, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 54, 56, 59, 61, 63, 64, 65, 66, 67, 69, 71, 73, 75, 79 },
+/* 123 */ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 19, 23, 25, 27, 29, 31, 33, 35, 37, 40, 43, 46, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 72 },
+/* 124 */ { 0, 3, 5, 8, 11, 14, 16, 19, 22, 26, 28, 31, 34, 37, 40, 45, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83 },
+/* 125 */ { 0, 2, 4, 8, 10, 12, 14, 18, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 44, 46, 48, 51, 54, 56, 60, 63, 65, 67, 69, 71, 72, 73 },
+/* 126 */ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 85 },
+/* 127 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 128 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 129 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 130 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 131 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 132 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 133 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 134 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 135 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 136 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 137 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 138 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 139 */ { 0, 2, 4, 6, 9, 12, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 32, 34, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46 },
+/* 140 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 141 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33 },
+/* 142 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 143 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 144 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 145 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33 },
+/* 146 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 47, 48, 49, 50 },
+/* 147 */ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64 },
+/* 148 */ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64 },
+/* 149 */ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 55, 56, 57, 58, 59 },
+/* 150 */ { 0, 1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60 },
+/* 151 */ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63 },
+/* 152 */ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64 },
+/* 153 */ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 51, 53, 55, 57, 59, 61, 63 },
+/* 154 */ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 37, 38, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61 },
+/* 155 */ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64 },
+/* 156 */ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 57, 58, 59, 60 },
+/* 157 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61, 64 },
+/* 158 */ { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96 },
+/* 159 */ { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 49, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92 },
+/* 160 */ { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96 },
+/* 161 */ { 0, 3, 6, 9, 12, 15, 18, 21, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48 },
+/* 162 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19, 22, 26, 30, 34, 38, 42, 46, 50, 53, 71, 79, 83, 84, 85, 86 },
+/* 163 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33 },
+/* 164 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 165 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 166 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 167 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 168 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 169 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 38, 39, 40 },
+/* 170 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 171 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 172 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 173 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 174 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 175 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 176 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 },
+/* 177 */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }
+};
+
+unsigned short unac_data0[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data1[] = { 0x0020, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0020, 0xFFFF, 0x0061, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0020, 0xFFFF, 0xFFFF, 0x0032, 0x0033, 0x0020, 0x03BC, 0xFFFF, 0xFFFF, 0x0020, 0x0031, 0x006F, 0xFFFF, 0x0031, 0x2044, 0x0034, 0x0031, 0x2044, 0x0032, 0x0033, 0x2044, 0x0034, 0xFFFF };
+unsigned short unac_data2[] = { 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0045, 0x0043, 0x0045, 0x0045, 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049, 0xFFFF, 0x004E, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, 0xFFFF, 0x004F, 0x0055, 0x0055, 0x0055, 0x0055, 0x0059, 0xFFFF, 0xFFFF };
+unsigned short unac_data3[] = { 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0065, 0x0063, 0x0065, 0x0065, 0x0065, 0x0065, 0x0069, 0x0069, 0x0069, 0x0069, 0xFFFF, 0x006E, 0x006F, 0x006F, 0x006F, 0x006F, 0x006F, 0xFFFF, 0x006F, 0x0075, 0x0075, 0x0075, 0x0075, 0x0079, 0xFFFF, 0x0079 };
+unsigned short unac_data4[] = { 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0043, 0x0063, 0x0043, 0x0063, 0x0043, 0x0063, 0x0043, 0x0063, 0x0044, 0x0064, 0xFFFF, 0xFFFF, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, 0x0047, 0x0067, 0x0047, 0x0067 };
+unsigned short unac_data5[] = { 0x0047, 0x0067, 0x0047, 0x0067, 0x0048, 0x0068, 0xFFFF, 0xFFFF, 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0xFFFF, 0x0049, 0x004A, 0x0069, 0x006A, 0x004A, 0x006A, 0x004B, 0x006B, 0xFFFF, 0x004C, 0x006C, 0x004C, 0x006C, 0x004C, 0x006C, 0x004C, 0x00B7 };
+unsigned short unac_data6[] = { 0x006C, 0x00B7, 0xFFFF, 0xFFFF, 0x004E, 0x006E, 0x004E, 0x006E, 0x004E, 0x006E, 0x02BC, 0x006E, 0xFFFF, 0xFFFF, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, 0xFFFF, 0xFFFF, 0x0052, 0x0072, 0x0052, 0x0072, 0x0052, 0x0072, 0x0053, 0x0073, 0x0053, 0x0073, 0x0053, 0x0073 };
+unsigned short unac_data7[] = { 0x0053, 0x0073, 0x0054, 0x0074, 0x0054, 0x0074, 0xFFFF, 0xFFFF, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0057, 0x0077, 0x0059, 0x0079, 0x0059, 0x005A, 0x007A, 0x005A, 0x007A, 0x005A, 0x007A, 0x0073 };
+unsigned short unac_data8[] = { 0x004F, 0x006F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0055, 0x0075, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data9[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0044, 0x005A, 0x0044, 0x007A, 0x0064, 0x007A, 0x004C, 0x004A, 0x004C, 0x006A, 0x006C, 0x006A, 0x004E, 0x004A, 0x004E, 0x006A, 0x006E, 0x006A, 0x0041, 0x0061, 0x0049, 0x0069, 0x004F, 0x006F, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0xFFFF, 0x0041, 0x0061 };
+unsigned short unac_data10[] = { 0x0041, 0x0061, 0x0041, 0x0045, 0x0061, 0x0065, 0xFFFF, 0xFFFF, 0x0047, 0x0067, 0x004B, 0x006B, 0x004F, 0x006F, 0x004F, 0x006F, 0x01B7, 0x0292, 0x006A, 0x0044, 0x005A, 0x0044, 0x007A, 0x0064, 0x007A, 0x0047, 0x0067, 0xFFFF, 0xFFFF, 0x004E, 0x006E, 0x0041, 0x0061, 0x0041, 0x0045, 0x0061, 0x0065, 0x004F, 0x006F };
+unsigned short unac_data11[] = { 0x0041, 0x0061, 0x0041, 0x0061, 0x0045, 0x0065, 0x0045, 0x0065, 0x0049, 0x0069, 0x0049, 0x0069, 0x004F, 0x006F, 0x004F, 0x006F, 0x0052, 0x0072, 0x0052, 0x0072, 0x0055, 0x0075, 0x0055, 0x0075, 0x0053, 0x0073, 0x0054, 0x0074, 0xFFFF, 0xFFFF, 0x0048, 0x0068 };
+unsigned short unac_data12[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0041, 0x0061, 0x0045, 0x0065, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, 0x0059, 0x0079, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data13[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0068, 0x0266, 0x006A, 0x0072, 0x0279, 0x027B, 0x0281, 0x0077, 0x0079, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data14[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0xFFFF, 0xFFFF };
+unsigned short unac_data15[] = { 0x0263, 0x006C, 0x0073, 0x0078, 0x0295, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data16[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x02B9, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0020, 0xFFFF, 0xFFFF, 0xFFFF, 0x003B, 0xFFFF };
+unsigned short unac_data17[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0020, 0x0020, 0x0391, 0x00B7, 0x0395, 0x0397, 0x0399, 0xFFFF, 0x039F, 0xFFFF, 0x03A5, 0x03A9, 0x03B9, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data18[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0399, 0x03A5, 0x03B1, 0x03B5, 0x03B7, 0x03B9, 0x03C5, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data19[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x03B9, 0x03C5, 0x03BF, 0x03C5, 0x03C9, 0xFFFF, 0x03B2, 0x03B8, 0x03A5, 0x03A5, 0x03A5, 0x03C6, 0x03C0, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data20[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x03BA, 0x03C1, 0x03C2, 0xFFFF, 0x0398, 0x03B5, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data21[] = { 0x0415, 0x0415, 0xFFFF, 0x0413, 0xFFFF, 0xFFFF, 0xFFFF, 0x0406, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x041A, 0x0418, 0x0423, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0418, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data22[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0438, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data23[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0435, 0x0435, 0xFFFF, 0x0433, 0xFFFF, 0xFFFF, 0xFFFF, 0x0456, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x043A, 0x0438, 0x0443, 0xFFFF };
+unsigned short unac_data24[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0474, 0x0475, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data25[] = { 0xFFFF, 0x0416, 0x0436, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0410, 0x0430, 0x0410, 0x0430, 0xFFFF, 0xFFFF, 0x0415, 0x0435, 0xFFFF, 0xFFFF, 0x04D8, 0x04D9, 0x0416, 0x0436, 0x0417, 0x0437 };
+unsigned short unac_data26[] = { 0xFFFF, 0xFFFF, 0x0418, 0x0438, 0x0418, 0x0438, 0x041E, 0x043E, 0xFFFF, 0xFFFF, 0x04E8, 0x04E9, 0x042D, 0x044D, 0x0423, 0x0443, 0x0423, 0x0443, 0x0423, 0x0443, 0x0427, 0x0447, 0xFFFF, 0xFFFF, 0x042B, 0x044B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data27[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0565, 0x0582, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data28[] = { 0xFFFF, 0xFFFF, 0x0627, 0x0627, 0x0648, 0x0627, 0x064A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data29[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0627, 0x0674, 0x0648, 0x0674, 0x06C7, 0x0674, 0x064A, 0x0674, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data30[] = { 0x06D5, 0xFFFF, 0x06C1, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x06D2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data31[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0928, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0930, 0xFFFF, 0xFFFF, 0x0933, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data32[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0915, 0x0916, 0x0917, 0x091C, 0x0921, 0x0922, 0x092B, 0x092F };
+unsigned short unac_data33[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x09A1, 0x09A2, 0xFFFF, 0x09AF };
+unsigned short unac_data34[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0A32, 0xFFFF, 0xFFFF, 0x0A38, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data35[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0A16, 0x0A17, 0x0A1C, 0xFFFF, 0xFFFF, 0x0A2B, 0xFFFF };
+unsigned short unac_data36[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0B21, 0x0B22, 0xFFFF, 0xFFFF };
+unsigned short unac_data37[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0B92, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data38[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0E32, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data39[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0EB2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data40[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0EAB, 0x0E99, 0x0EAB, 0x0EA1, 0xFFFF, 0xFFFF };
+unsigned short unac_data41[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0F0B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data42[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0x0F42, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0F4C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0F51, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0F56, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0F5B, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data43[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0F40, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data44[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x1025, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data45[] = { 0x0041, 0x0061, 0x0042, 0x0062, 0x0042, 0x0062, 0x0042, 0x0062, 0x0043, 0x0063, 0x0044, 0x0064, 0x0044, 0x0064, 0x0044, 0x0064, 0x0044, 0x0064, 0x0044, 0x0064, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, 0x0046, 0x0066 };
+unsigned short unac_data46[] = { 0x0047, 0x0067, 0x0048, 0x0068, 0x0048, 0x0068, 0x0048, 0x0068, 0x0048, 0x0068, 0x0048, 0x0068, 0x0049, 0x0069, 0x0049, 0x0069, 0x004B, 0x006B, 0x004B, 0x006B, 0x004B, 0x006B, 0x004C, 0x006C, 0x004C, 0x006C, 0x004C, 0x006C, 0x004C, 0x006C, 0x004D, 0x006D };
+unsigned short unac_data47[] = { 0x004D, 0x006D, 0x004D, 0x006D, 0x004E, 0x006E, 0x004E, 0x006E, 0x004E, 0x006E, 0x004E, 0x006E, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, 0x0050, 0x0070, 0x0050, 0x0070, 0x0052, 0x0072, 0x0052, 0x0072, 0x0052, 0x0072, 0x0052, 0x0072 };
+unsigned short unac_data48[] = { 0x0053, 0x0073, 0x0053, 0x0073, 0x0053, 0x0073, 0x0053, 0x0073, 0x0053, 0x0073, 0x0054, 0x0074, 0x0054, 0x0074, 0x0054, 0x0074, 0x0054, 0x0074, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0056, 0x0076, 0x0056, 0x0076 };
+unsigned short unac_data49[] = { 0x0057, 0x0077, 0x0057, 0x0077, 0x0057, 0x0077, 0x0057, 0x0077, 0x0057, 0x0077, 0x0058, 0x0078, 0x0058, 0x0078, 0x0059, 0x0079, 0x005A, 0x007A, 0x005A, 0x007A, 0x005A, 0x007A, 0x0068, 0x0074, 0x0077, 0x0079, 0x0061, 0x02BE, 0x0073, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data50[] = { 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065 };
+unsigned short unac_data51[] = { 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, 0x0049, 0x0069, 0x0049, 0x0069, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F };
+unsigned short unac_data52[] = { 0x004F, 0x006F, 0x004F, 0x006F, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0059, 0x0079, 0x0059, 0x0079, 0x0059, 0x0079, 0x0059, 0x0079, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data53[] = { 0x03B1, 0x03B1, 0x03B1, 0x03B1, 0x03B1, 0x03B1, 0x03B1, 0x03B1, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x03B5, 0x03B5, 0x03B5, 0x03B5, 0x03B5, 0x03B5, 0xFFFF, 0xFFFF, 0x0395, 0x0395, 0x0395, 0x0395, 0x0395, 0x0395, 0xFFFF, 0xFFFF };
+unsigned short unac_data54[] = { 0x03B7, 0x03B7, 0x03B7, 0x03B7, 0x03B7, 0x03B7, 0x03B7, 0x03B7, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x03B9, 0x03B9, 0x03B9, 0x03B9, 0x03B9, 0x03B9, 0x03B9, 0x03B9, 0x0399, 0x0399, 0x0399, 0x0399, 0x0399, 0x0399, 0x0399, 0x0399 };
+unsigned short unac_data55[] = { 0x03BF, 0x03BF, 0x03BF, 0x03BF, 0x03BF, 0x03BF, 0xFFFF, 0xFFFF, 0x039F, 0x039F, 0x039F, 0x039F, 0x039F, 0x039F, 0xFFFF, 0xFFFF, 0x03C5, 0x03C5, 0x03C5, 0x03C5, 0x03C5, 0x03C5, 0x03C5, 0x03C5, 0xFFFF, 0x03A5, 0xFFFF, 0x03A5, 0xFFFF, 0x03A5, 0xFFFF, 0x03A5 };
+unsigned short unac_data56[] = { 0x03C9, 0x03C9, 0x03C9, 0x03C9, 0x03C9, 0x03C9, 0x03C9, 0x03C9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03B1, 0x03B1, 0x03B5, 0x03B5, 0x03B7, 0x03B7, 0x03B9, 0x03B9, 0x03BF, 0x03BF, 0x03C5, 0x03C5, 0x03C9, 0x03C9, 0xFFFF, 0xFFFF };
+unsigned short unac_data57[] = { 0x03B1, 0x03B1, 0x03B1, 0x03B1, 0x03B1, 0x03B1, 0x03B1, 0x03B1, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x03B7, 0x03B7, 0x03B7, 0x03B7, 0x03B7, 0x03B7, 0x03B7, 0x03B7, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397, 0x0397 };
+unsigned short unac_data58[] = { 0x03C9, 0x03C9, 0x03C9, 0x03C9, 0x03C9, 0x03C9, 0x03C9, 0x03C9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03A9, 0x03B1, 0x03B1, 0x03B1, 0x03B1, 0x03B1, 0xFFFF, 0x03B1, 0x03B1, 0x0391, 0x0391, 0x0391, 0x0391, 0x0391, 0x0020, 0x03B9, 0x0020 };
+unsigned short unac_data59[] = { 0x0020, 0x0020, 0x03B7, 0x03B7, 0x03B7, 0xFFFF, 0x03B7, 0x03B7, 0x0395, 0x0395, 0x0397, 0x0397, 0x0397, 0x0020, 0x0020, 0x0020, 0x03B9, 0x03B9, 0x03B9, 0x03B9, 0xFFFF, 0xFFFF, 0x03B9, 0x03B9, 0x0399, 0x0399, 0x0399, 0x0399, 0xFFFF, 0x0020, 0x0020, 0x0020 };
+unsigned short unac_data60[] = { 0x03C5, 0x03C5, 0x03C5, 0x03C5, 0x03C1, 0x03C1, 0x03C5, 0x03C5, 0x03A5, 0x03A5, 0x03A5, 0x03A5, 0x03A1, 0x0020, 0x0020, 0x0060, 0xFFFF, 0xFFFF, 0x03C9, 0x03C9, 0x03C9, 0xFFFF, 0x03C9, 0x03C9, 0x039F, 0x039F, 0x03A9, 0x03A9, 0x03A9, 0x0020, 0x0020, 0xFFFF };
+unsigned short unac_data61[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2010, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0020, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data62[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x002E, 0x002E, 0x002E, 0x002E, 0x002E, 0x002E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0020, 0xFFFF, 0xFFFF, 0xFFFF, 0x2032, 0x2032, 0x2032, 0x2032, 0x2032, 0xFFFF, 0x2035, 0x2035, 0x2035, 0x2035, 0x2035, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0021, 0x0021, 0xFFFF, 0x0020, 0xFFFF };
+unsigned short unac_data63[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x003F, 0x003F, 0x003F, 0x0021, 0x0021, 0x003F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2032, 0x2032, 0x2032, 0x2032, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0020 };
+unsigned short unac_data64[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0030, 0x0069, 0xFFFF, 0xFFFF, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x002B, 0x2212, 0x003D, 0x0028, 0x0029, 0x006E };
+unsigned short unac_data65[] = { 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x002B, 0x2212, 0x003D, 0x0028, 0x0029, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data66[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0052, 0x0073, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data67[] = { 0x0061, 0x002F, 0x0063, 0x0061, 0x002F, 0x0073, 0x0043, 0x00B0, 0x0043, 0xFFFF, 0x0063, 0x002F, 0x006F, 0x0063, 0x002F, 0x0075, 0x0190, 0xFFFF, 0x00B0, 0x0046, 0x0067, 0x0048, 0x0048, 0x0048, 0x0068, 0x0127, 0x0049, 0x0049, 0x004C, 0x006C, 0xFFFF, 0x004E, 0x004E, 0x006F, 0xFFFF, 0xFFFF, 0x0050, 0x0051, 0x0052, 0x0052, 0x0052, 0xFFFF, 0xFFFF };
+unsigned short unac_data68[] = { 0x0053, 0x004D, 0x0054, 0x0045, 0x004C, 0x0054, 0x004D, 0xFFFF, 0x005A, 0xFFFF, 0x03A9, 0xFFFF, 0x005A, 0xFFFF, 0x004B, 0x0041, 0x0042, 0x0043, 0xFFFF, 0x0065, 0x0045, 0x0046, 0xFFFF, 0x004D, 0x006F, 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x0069, 0xFFFF, 0xFFFF, 0xFFFF, 0x03B3, 0x0393, 0x03A0 };
+unsigned short unac_data69[] = { 0x2211, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0044, 0x0064, 0x0065, 0x0069, 0x006A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0031, 0x2044, 0x0033, 0x0032, 0x2044, 0x0033, 0x0031, 0x2044, 0x0035, 0x0032, 0x2044, 0x0035, 0x0033, 0x2044, 0x0035, 0x0034, 0x2044, 0x0035, 0x0031, 0x2044, 0x0036, 0x0035, 0x2044, 0x0036, 0x0031, 0x2044, 0x0038, 0x0033, 0x2044, 0x0038, 0x0035, 0x2044, 0x0038, 0x0037, 0x2044, 0x0038, 0x0031, 0x2044 };
+unsigned short unac_data70[] = { 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x0056, 0x0056, 0x0056, 0x0049, 0x0056, 0x0049, 0x0049, 0x0056, 0x0049, 0x0049, 0x0049, 0x0049, 0x0058, 0x0058, 0x0058, 0x0049, 0x0058, 0x0049, 0x0049, 0x004C, 0x0043, 0x0044, 0x004D, 0x0069, 0x0069, 0x0069, 0x0069, 0x0069, 0x0069, 0x0069, 0x0076, 0x0076, 0x0076, 0x0069, 0x0076, 0x0069, 0x0069, 0x0076, 0x0069, 0x0069, 0x0069, 0x0069, 0x0078, 0x0078, 0x0078, 0x0069, 0x0078, 0x0069, 0x0069, 0x006C, 0x0063, 0x0064, 0x006D };
+unsigned short unac_data71[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2190, 0x2192, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data72[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2194, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data73[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x21D0, 0x21D4, 0x21D2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data74[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2203, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2208, 0xFFFF, 0xFFFF, 0x220B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data75[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2223, 0xFFFF, 0x2225, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x222B, 0x222B, 0x222B, 0x222B, 0x222B, 0xFFFF, 0x222E, 0x222E, 0x222E, 0x222E, 0x222E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data76[] = { 0xFFFF, 0x223C, 0xFFFF, 0xFFFF, 0x2243, 0xFFFF, 0xFFFF, 0x2245, 0xFFFF, 0x2248, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data77[] = { 0x003D, 0xFFFF, 0x2261, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x224D, 0x003C, 0x003E, 0x2264, 0x2265, 0xFFFF, 0xFFFF, 0x2272, 0x2273, 0xFFFF, 0xFFFF, 0x2276, 0x2277, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data78[] = { 0x227A, 0x227B, 0xFFFF, 0xFFFF, 0x2282, 0x2283, 0xFFFF, 0xFFFF, 0x2286, 0x2287, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data79[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x22A2, 0x22A8, 0x22A9, 0x22AB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data80[] = { 0x227C, 0x227D, 0x2291, 0x2292, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x22B2, 0x22B3, 0x22B4, 0x22B5, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data81[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x3008, 0x3009, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data82[] = { 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x0031, 0x0030, 0x0031, 0x0031, 0x0031, 0x0032, 0x0031, 0x0033, 0x0031, 0x0034, 0x0031, 0x0035, 0x0031, 0x0036, 0x0031, 0x0037, 0x0031, 0x0038, 0x0031, 0x0039, 0x0032, 0x0030, 0x0028, 0x0031, 0x0029, 0x0028, 0x0032, 0x0029, 0x0028, 0x0033, 0x0029, 0x0028, 0x0034, 0x0029, 0x0028, 0x0035, 0x0029, 0x0028, 0x0036, 0x0029, 0x0028, 0x0037, 0x0029, 0x0028, 0x0038, 0x0029, 0x0028, 0x0039, 0x0029, 0x0028, 0x0031, 0x0030, 0x0029, 0x0028, 0x0031, 0x0031, 0x0029, 0x0028, 0x0031, 0x0032, 0x0029 };
+unsigned short unac_data83[] = { 0x0028, 0x0031, 0x0033, 0x0029, 0x0028, 0x0031, 0x0034, 0x0029, 0x0028, 0x0031, 0x0035, 0x0029, 0x0028, 0x0031, 0x0036, 0x0029, 0x0028, 0x0031, 0x0037, 0x0029, 0x0028, 0x0031, 0x0038, 0x0029, 0x0028, 0x0031, 0x0039, 0x0029, 0x0028, 0x0032, 0x0030, 0x0029, 0x0031, 0x002E, 0x0032, 0x002E, 0x0033, 0x002E, 0x0034, 0x002E, 0x0035, 0x002E, 0x0036, 0x002E, 0x0037, 0x002E, 0x0038, 0x002E, 0x0039, 0x002E, 0x0031, 0x0030, 0x002E, 0x0031, 0x0031, 0x002E, 0x0031, 0x0032, 0x002E, 0x0031, 0x0033, 0x002E, 0x0031, 0x0034, 0x002E, 0x0031, 0x0035, 0x002E, 0x0031, 0x0036, 0x002E, 0x0031, 0x0037, 0x002E, 0x0031, 0x0038, 0x002E, 0x0031, 0x0039, 0x002E, 0x0032, 0x0030, 0x002E, 0x0028, 0x0061, 0x0029, 0x0028, 0x0062, 0x0029, 0x0028, 0x0063, 0x0029, 0x0028, 0x0064, 0x0029 };
+unsigned short unac_data84[] = { 0x0028, 0x0065, 0x0029, 0x0028, 0x0066, 0x0029, 0x0028, 0x0067, 0x0029, 0x0028, 0x0068, 0x0029, 0x0028, 0x0069, 0x0029, 0x0028, 0x006A, 0x0029, 0x0028, 0x006B, 0x0029, 0x0028, 0x006C, 0x0029, 0x0028, 0x006D, 0x0029, 0x0028, 0x006E, 0x0029, 0x0028, 0x006F, 0x0029, 0x0028, 0x0070, 0x0029, 0x0028, 0x0071, 0x0029, 0x0028, 0x0072, 0x0029, 0x0028, 0x0073, 0x0029, 0x0028, 0x0074, 0x0029, 0x0028, 0x0075, 0x0029, 0x0028, 0x0076, 0x0029, 0x0028, 0x0077, 0x0029, 0x0028, 0x0078, 0x0029, 0x0028, 0x0079, 0x0029, 0x0028, 0x007A, 0x0029, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A };
+unsigned short unac_data85[] = { 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070 };
+unsigned short unac_data86[] = { 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x0030, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data87[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x222B, 0x222B, 0x222B, 0x222B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data88[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x003A, 0x003A, 0x003D, 0x003D, 0x003D, 0x003D, 0x003D, 0x003D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data89[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2ADD, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data90[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x6BCD };
+unsigned short unac_data91[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x9F9F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data92[] = { 0x4E00, 0x4E28, 0x4E36, 0x4E3F, 0x4E59, 0x4E85, 0x4E8C, 0x4EA0, 0x4EBA, 0x513F, 0x5165, 0x516B, 0x5182, 0x5196, 0x51AB, 0x51E0, 0x51F5, 0x5200, 0x529B, 0x52F9, 0x5315, 0x531A, 0x5338, 0x5341, 0x535C, 0x5369, 0x5382, 0x53B6, 0x53C8, 0x53E3, 0x56D7, 0x571F };
+unsigned short unac_data93[] = { 0x58EB, 0x5902, 0x590A, 0x5915, 0x5927, 0x5973, 0x5B50, 0x5B80, 0x5BF8, 0x5C0F, 0x5C22, 0x5C38, 0x5C6E, 0x5C71, 0x5DDB, 0x5DE5, 0x5DF1, 0x5DFE, 0x5E72, 0x5E7A, 0x5E7F, 0x5EF4, 0x5EFE, 0x5F0B, 0x5F13, 0x5F50, 0x5F61, 0x5F73, 0x5FC3, 0x6208, 0x6236, 0x624B };
+unsigned short unac_data94[] = { 0x652F, 0x6534, 0x6587, 0x6597, 0x65A4, 0x65B9, 0x65E0, 0x65E5, 0x66F0, 0x6708, 0x6728, 0x6B20, 0x6B62, 0x6B79, 0x6BB3, 0x6BCB, 0x6BD4, 0x6BDB, 0x6C0F, 0x6C14, 0x6C34, 0x706B, 0x722A, 0x7236, 0x723B, 0x723F, 0x7247, 0x7259, 0x725B, 0x72AC, 0x7384, 0x7389 };
+unsigned short unac_data95[] = { 0x74DC, 0x74E6, 0x7518, 0x751F, 0x7528, 0x7530, 0x758B, 0x7592, 0x7676, 0x767D, 0x76AE, 0x76BF, 0x76EE, 0x77DB, 0x77E2, 0x77F3, 0x793A, 0x79B8, 0x79BE, 0x7A74, 0x7ACB, 0x7AF9, 0x7C73, 0x7CF8, 0x7F36, 0x7F51, 0x7F8A, 0x7FBD, 0x8001, 0x800C, 0x8012, 0x8033 };
+unsigned short unac_data96[] = { 0x807F, 0x8089, 0x81E3, 0x81EA, 0x81F3, 0x81FC, 0x820C, 0x821B, 0x821F, 0x826E, 0x8272, 0x8278, 0x864D, 0x866B, 0x8840, 0x884C, 0x8863, 0x897E, 0x898B, 0x89D2, 0x8A00, 0x8C37, 0x8C46, 0x8C55, 0x8C78, 0x8C9D, 0x8D64, 0x8D70, 0x8DB3, 0x8EAB, 0x8ECA, 0x8F9B };
+unsigned short unac_data97[] = { 0x8FB0, 0x8FB5, 0x9091, 0x9149, 0x91C6, 0x91CC, 0x91D1, 0x9577, 0x9580, 0x961C, 0x96B6, 0x96B9, 0x96E8, 0x9751, 0x975E, 0x9762, 0x9769, 0x97CB, 0x97ED, 0x97F3, 0x9801, 0x98A8, 0x98DB, 0x98DF, 0x9996, 0x9999, 0x99AC, 0x9AA8, 0x9AD8, 0x9ADF, 0x9B25, 0x9B2F };
+unsigned short unac_data98[] = { 0x9B32, 0x9B3C, 0x9B5A, 0x9CE5, 0x9E75, 0x9E7F, 0x9EA5, 0x9EBB, 0x9EC3, 0x9ECD, 0x9ED1, 0x9EF9, 0x9EFD, 0x9F0E, 0x9F13, 0x9F20, 0x9F3B, 0x9F4A, 0x9F52, 0x9F8D, 0x9F9C, 0x9FA0, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data99[] = { 0x0020, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data100[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x3012, 0xFFFF, 0x5341, 0x5344, 0x5345, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data101[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x304B, 0xFFFF, 0x304D, 0xFFFF, 0x304F, 0xFFFF, 0x3051, 0xFFFF, 0x3053, 0xFFFF, 0x3055, 0xFFFF, 0x3057, 0xFFFF, 0x3059, 0xFFFF, 0x305B, 0xFFFF, 0x305D, 0xFFFF };
+unsigned short unac_data102[] = { 0x305F, 0xFFFF, 0x3061, 0xFFFF, 0xFFFF, 0x3064, 0xFFFF, 0x3066, 0xFFFF, 0x3068, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x306F, 0x306F, 0xFFFF, 0x3072, 0x3072, 0xFFFF, 0x3075, 0x3075, 0xFFFF, 0x3078, 0x3078, 0xFFFF, 0x307B, 0x307B, 0xFFFF, 0xFFFF };
+unsigned short unac_data103[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x3046, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0020, 0x0020, 0xFFFF, 0x309D, 0x3088, 0x308A };
+unsigned short unac_data104[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x30AB, 0xFFFF, 0x30AD, 0xFFFF, 0x30AF, 0xFFFF, 0x30B1, 0xFFFF, 0x30B3, 0xFFFF, 0x30B5, 0xFFFF, 0x30B7, 0xFFFF, 0x30B9, 0xFFFF, 0x30BB, 0xFFFF, 0x30BD, 0xFFFF };
+unsigned short unac_data105[] = { 0x30BF, 0xFFFF, 0x30C1, 0xFFFF, 0xFFFF, 0x30C4, 0xFFFF, 0x30C6, 0xFFFF, 0x30C8, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x30CF, 0x30CF, 0xFFFF, 0x30D2, 0x30D2, 0xFFFF, 0x30D5, 0x30D5, 0xFFFF, 0x30D8, 0x30D8, 0xFFFF, 0x30DB, 0x30DB, 0xFFFF, 0xFFFF };
+unsigned short unac_data106[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x30A6, 0xFFFF, 0xFFFF, 0x30EF, 0x30F0, 0x30F1, 0x30F2, 0xFFFF, 0xFFFF, 0xFFFF, 0x30FD, 0x30B3, 0x30C8 };
+unsigned short unac_data107[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x1100, 0x1101, 0x11AA, 0x1102, 0x11AC, 0x11AD, 0x1103, 0x1104, 0x1105, 0x11B0, 0x11B1, 0x11B2, 0x11B3, 0x11B4, 0x11B5 };
+unsigned short unac_data108[] = { 0x111A, 0x1106, 0x1107, 0x1108, 0x1121, 0x1109, 0x110A, 0x110B, 0x110C, 0x110D, 0x110E, 0x110F, 0x1110, 0x1111, 0x1112, 0x1161, 0x1162, 0x1163, 0x1164, 0x1165, 0x1166, 0x1167, 0x1168, 0x1169, 0x116A, 0x116B, 0x116C, 0x116D, 0x116E, 0x116F, 0x1170, 0x1171 };
+unsigned short unac_data109[] = { 0x1172, 0x1173, 0x1174, 0x1175, 0x1160, 0x1114, 0x1115, 0x11C7, 0x11C8, 0x11CC, 0x11CE, 0x11D3, 0x11D7, 0x11D9, 0x111C, 0x11DD, 0x11DF, 0x111D, 0x111E, 0x1120, 0x1122, 0x1123, 0x1127, 0x1129, 0x112B, 0x112C, 0x112D, 0x112E, 0x112F, 0x1132, 0x1136, 0x1140 };
+unsigned short unac_data110[] = { 0x1147, 0x114C, 0x11F1, 0x11F2, 0x1157, 0x1158, 0x1159, 0x1184, 0x1185, 0x1188, 0x1191, 0x1192, 0x1194, 0x119E, 0x11A1, 0xFFFF, 0xFFFF, 0xFFFF, 0x4E00, 0x4E8C, 0x4E09, 0x56DB, 0x4E0A, 0x4E2D, 0x4E0B, 0x7532, 0x4E59, 0x4E19, 0x4E01, 0x5929, 0x5730, 0x4EBA };
+unsigned short unac_data111[] = { 0x0028, 0x1100, 0x0029, 0x0028, 0x1102, 0x0029, 0x0028, 0x1103, 0x0029, 0x0028, 0x1105, 0x0029, 0x0028, 0x1106, 0x0029, 0x0028, 0x1107, 0x0029, 0x0028, 0x1109, 0x0029, 0x0028, 0x110B, 0x0029, 0x0028, 0x110C, 0x0029, 0x0028, 0x110E, 0x0029, 0x0028, 0x110F, 0x0029, 0x0028, 0x1110, 0x0029, 0x0028, 0x1111, 0x0029, 0x0028, 0x1112, 0x0029, 0x0028, 0x1100, 0x1161, 0x0029, 0x0028, 0x1102, 0x1161, 0x0029, 0x0028, 0x1103, 0x1161, 0x0029, 0x0028, 0x1105, 0x1161, 0x0029, 0x0028, 0x1106, 0x1161, 0x0029, 0x0028, 0x1107, 0x1161, 0x0029, 0x0028, 0x1109, 0x1161, 0x0029, 0x0028, 0x110B, 0x1161, 0x0029, 0x0028, 0x110C, 0x1161, 0x0029, 0x0028, 0x110E, 0x1161, 0x0029, 0x0028, 0x110F, 0x1161, 0x0029, 0x0028, 0x1110, 0x1161, 0x0029, 0x0028, 0x1111, 0x1161, 0x0029, 0x0028, 0x1112, 0x1161, 0x0029, 0x0028, 0x110C, 0x116E, 0x0029, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data112[] = { 0x0028, 0x4E00, 0x0029, 0x0028, 0x4E8C, 0x0029, 0x0028, 0x4E09, 0x0029, 0x0028, 0x56DB, 0x0029, 0x0028, 0x4E94, 0x0029, 0x0028, 0x516D, 0x0029, 0x0028, 0x4E03, 0x0029, 0x0028, 0x516B, 0x0029, 0x0028, 0x4E5D, 0x0029, 0x0028, 0x5341, 0x0029, 0x0028, 0x6708, 0x0029, 0x0028, 0x706B, 0x0029, 0x0028, 0x6C34, 0x0029, 0x0028, 0x6728, 0x0029, 0x0028, 0x91D1, 0x0029, 0x0028, 0x571F, 0x0029, 0x0028, 0x65E5, 0x0029, 0x0028, 0x682A, 0x0029, 0x0028, 0x6709, 0x0029, 0x0028, 0x793E, 0x0029, 0x0028, 0x540D, 0x0029, 0x0028, 0x7279, 0x0029, 0x0028, 0x8CA1, 0x0029, 0x0028, 0x795D, 0x0029, 0x0028, 0x52B4, 0x0029, 0x0028, 0x4EE3, 0x0029, 0x0028, 0x547C, 0x0029, 0x0028, 0x5B66, 0x0029, 0x0028, 0x76E3, 0x0029, 0x0028, 0x4F01, 0x0029, 0x0028, 0x8CC7, 0x0029, 0x0028, 0x5354, 0x0029 };
+unsigned short unac_data113[] = { 0x0028, 0x796D, 0x0029, 0x0028, 0x4F11, 0x0029, 0x0028, 0x81EA, 0x0029, 0x0028, 0x81F3, 0x0029, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0032, 0x0031, 0x0032, 0x0032, 0x0032, 0x0033, 0x0032, 0x0034, 0x0032, 0x0035, 0x0032, 0x0036, 0x0032, 0x0037, 0x0032, 0x0038, 0x0032, 0x0039, 0x0033, 0x0030, 0x0033, 0x0031, 0x0033, 0x0032, 0x0033, 0x0033, 0x0033, 0x0034, 0x0033, 0x0035 };
+unsigned short unac_data114[] = { 0x1100, 0x1102, 0x1103, 0x1105, 0x1106, 0x1107, 0x1109, 0x110B, 0x110C, 0x110E, 0x110F, 0x1110, 0x1111, 0x1112, 0x1100, 0x1161, 0x1102, 0x1161, 0x1103, 0x1161, 0x1105, 0x1161, 0x1106, 0x1161, 0x1107, 0x1161, 0x1109, 0x1161, 0x110B, 0x1161, 0x110C, 0x1161, 0x110E, 0x1161, 0x110F, 0x1161, 0x1110, 0x1161, 0x1111, 0x1161, 0x1112, 0x1161, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data115[] = { 0x4E00, 0x4E8C, 0x4E09, 0x56DB, 0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D, 0x5341, 0x6708, 0x706B, 0x6C34, 0x6728, 0x91D1, 0x571F, 0x65E5, 0x682A, 0x6709, 0x793E, 0x540D, 0x7279, 0x8CA1, 0x795D, 0x52B4, 0x79D8, 0x7537, 0x5973, 0x9069, 0x512A, 0x5370, 0x6CE8 };
+unsigned short unac_data116[] = { 0x9805, 0x4F11, 0x5199, 0x6B63, 0x4E0A, 0x4E2D, 0x4E0B, 0x5DE6, 0x53F3, 0x533B, 0x5B97, 0x5B66, 0x76E3, 0x4F01, 0x8CC7, 0x5354, 0x591C, 0x0033, 0x0036, 0x0033, 0x0037, 0x0033, 0x0038, 0x0033, 0x0039, 0x0034, 0x0030, 0x0034, 0x0031, 0x0034, 0x0032, 0x0034, 0x0033, 0x0034, 0x0034, 0x0034, 0x0035, 0x0034, 0x0036, 0x0034, 0x0037, 0x0034, 0x0038, 0x0034, 0x0039, 0x0035, 0x0030 };
+unsigned short unac_data117[] = { 0x0031, 0x6708, 0x0032, 0x6708, 0x0033, 0x6708, 0x0034, 0x6708, 0x0035, 0x6708, 0x0036, 0x6708, 0x0037, 0x6708, 0x0038, 0x6708, 0x0039, 0x6708, 0x0031, 0x0030, 0x6708, 0x0031, 0x0031, 0x6708, 0x0031, 0x0032, 0x6708, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, 0x30BF };
+unsigned short unac_data118[] = { 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F0, 0x30F1, 0x30F2, 0xFFFF };
+unsigned short unac_data119[] = { 0x30A2, 0x30FC, 0x30C8, 0x30CF, 0x30A2, 0x30EB, 0x30D5, 0x30A1, 0x30A2, 0x30F3, 0x30A2, 0x30D8, 0x30A2, 0x30FC, 0x30EB, 0x30A4, 0x30CB, 0x30F3, 0x30AF, 0x30A4, 0x30F3, 0x30C1, 0x30A6, 0x30A9, 0x30F3, 0x30A8, 0x30B9, 0x30AF, 0x30FC, 0x30C8, 0x30A8, 0x30FC, 0x30AB, 0x30FC, 0x30AA, 0x30F3, 0x30B9, 0x30AA, 0x30FC, 0x30E0, 0x30AB, 0x30A4, 0x30EA, 0x30AB, 0x30E9, 0x30C3, 0x30C8, 0x30AB, 0x30ED, 0x30EA, 0x30FC, 0x30ED, 0x30F3, 0x30AB, 0x30F3, 0x30DE, 0x30AB, 0x30AD, 0x30AB, 0x30CB, 0x30FC, 0x30AD, 0x30AD, 0x30E5, 0x30EA, 0x30FC, 0x30EB, 0x30FC, 0x30AD, 0x30BF, 0x30AD, 0x30ED, 0x30AD, 0x30ED, 0x30E9, 0x30E0, 0x30AF, 0x30AD, 0x30ED, 0x30E1, 0x30FC, 0x30C8, 0x30EB, 0x30AD, 0x30ED, 0x30EF, 0x30C3, 0x30C8, 0x30E9, 0x30E0, 0x30AF, 0x30E9, 0x30E0, 0x30C8, 0x30F3, 0x30AF, 0x30AF, 0x30EB, 0x30A4, 0x30ED, 0x30BB, 0x30AF, 0x30ED, 0x30FC, 0x30CD, 0x30B1, 0x30FC, 0x30B9, 0x30B3, 0x30EB, 0x30CA, 0x30B3, 0x30FC, 0x30DB, 0x30B5, 0x30A4, 0x30AF, 0x30EB };
+unsigned short unac_data120[] = { 0x30B5, 0x30F3, 0x30C1, 0x30FC, 0x30E0, 0x30B7, 0x30EA, 0x30F3, 0x30AF, 0x30BB, 0x30F3, 0x30C1, 0x30BB, 0x30F3, 0x30C8, 0x30FC, 0x30B9, 0x30BF, 0x30B7, 0x30C6, 0x30EB, 0x30C8, 0x30C8, 0x30F3, 0x30CA, 0x30CE, 0x30CE, 0x30C3, 0x30C8, 0x30CF, 0x30A4, 0x30C4, 0x30FC, 0x30BB, 0x30F3, 0x30C8, 0x30CF, 0x30FC, 0x30C4, 0x30CF, 0x30FC, 0x30EC, 0x30EB, 0x30CF, 0x30A2, 0x30B9, 0x30C8, 0x30EB, 0x30D2, 0x30AF, 0x30EB, 0x30D2, 0x30B3, 0x30D2, 0x30EB, 0x30D2, 0x30D5, 0x30A1, 0x30E9, 0x30C3, 0x30C8, 0x30D5, 0x30A3, 0x30FC, 0x30C8, 0x30C3, 0x30B7, 0x30A7, 0x30EB, 0x30D5, 0x30D5, 0x30E9, 0x30F3, 0x30D8, 0x30AF, 0x30BF, 0x30FC, 0x30EB, 0x30BD, 0x30D8, 0x30CB, 0x30D2, 0x30D8, 0x30D8, 0x30EB, 0x30C4, 0x30F3, 0x30B9, 0x30D8, 0x30FC, 0x30D8, 0x30B7, 0x30FC, 0x30BF, 0x30D8, 0x30A4, 0x30F3, 0x30C8, 0x30DB, 0x30EB, 0x30C8, 0x30DB, 0x30DB, 0x30F3 };
+unsigned short unac_data121[] = { 0x30F3, 0x30DB, 0x30C8, 0x30DB, 0x30FC, 0x30EB, 0x30DB, 0x30FC, 0x30F3, 0x30DE, 0x30A4, 0x30AF, 0x30ED, 0x30DE, 0x30A4, 0x30EB, 0x30DE, 0x30C3, 0x30CF, 0x30DE, 0x30EB, 0x30AF, 0x30DE, 0x30F3, 0x30B7, 0x30E7, 0x30F3, 0x30DF, 0x30AF, 0x30ED, 0x30F3, 0x30DF, 0x30EA, 0x30DF, 0x30EA, 0x30FC, 0x30EB, 0x30CF, 0x30E1, 0x30AB, 0x30E1, 0x30C8, 0x30F3, 0x30AB, 0x30E1, 0x30FC, 0x30C8, 0x30EB, 0x30E4, 0x30FC, 0x30C8, 0x30E4, 0x30FC, 0x30EB, 0x30E6, 0x30A2, 0x30F3, 0x30EA, 0x30C3, 0x30C8, 0x30EB, 0x30EA, 0x30E9, 0x30EB, 0x30FC, 0x30D2, 0x30EB, 0x30FC, 0x30EB, 0x30D5, 0x30EC, 0x30E0, 0x30EC, 0x30F3, 0x30C8, 0x30F3, 0x30B1, 0x30EF, 0x30C3, 0x30C8, 0x0030, 0x70B9, 0x0031, 0x70B9, 0x0032, 0x70B9, 0x0033, 0x70B9, 0x0034, 0x70B9, 0x0035, 0x70B9, 0x0036, 0x70B9, 0x0037, 0x70B9 };
+unsigned short unac_data122[] = { 0x0038, 0x70B9, 0x0039, 0x70B9, 0x0031, 0x0030, 0x70B9, 0x0031, 0x0031, 0x70B9, 0x0031, 0x0032, 0x70B9, 0x0031, 0x0033, 0x70B9, 0x0031, 0x0034, 0x70B9, 0x0031, 0x0035, 0x70B9, 0x0031, 0x0036, 0x70B9, 0x0031, 0x0037, 0x70B9, 0x0031, 0x0038, 0x70B9, 0x0031, 0x0039, 0x70B9, 0x0032, 0x0030, 0x70B9, 0x0032, 0x0031, 0x70B9, 0x0032, 0x0032, 0x70B9, 0x0032, 0x0033, 0x70B9, 0x0032, 0x0034, 0x70B9, 0x0068, 0x0050, 0x0061, 0x0064, 0x0061, 0x0041, 0x0055, 0x0062, 0x0061, 0x0072, 0x006F, 0x0056, 0x0070, 0x0063, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x5E73, 0x6210, 0x662D, 0x548C, 0x5927, 0x6B63, 0x660E, 0x6CBB, 0x682A, 0x5F0F, 0x4F1A, 0x793E };
+unsigned short unac_data123[] = { 0x0070, 0x0041, 0x006E, 0x0041, 0x03BC, 0x0041, 0x006D, 0x0041, 0x006B, 0x0041, 0x004B, 0x0042, 0x004D, 0x0042, 0x0047, 0x0042, 0x0063, 0x0061, 0x006C, 0x006B, 0x0063, 0x0061, 0x006C, 0x0070, 0x0046, 0x006E, 0x0046, 0x03BC, 0x0046, 0x03BC, 0x0067, 0x006D, 0x0067, 0x006B, 0x0067, 0x0048, 0x007A, 0x006B, 0x0048, 0x007A, 0x004D, 0x0048, 0x007A, 0x0047, 0x0048, 0x007A, 0x0054, 0x0048, 0x007A, 0x03BC, 0x006C, 0x006D, 0x006C, 0x0064, 0x006C, 0x006B, 0x006C, 0x0066, 0x006D, 0x006E, 0x006D, 0x03BC, 0x006D, 0x006D, 0x006D, 0x0063, 0x006D, 0x006B, 0x006D, 0x006D, 0x006D, 0x0032 };
+unsigned short unac_data124[] = { 0x0063, 0x006D, 0x0032, 0x006D, 0x0032, 0x006B, 0x006D, 0x0032, 0x006D, 0x006D, 0x0033, 0x0063, 0x006D, 0x0033, 0x006D, 0x0033, 0x006B, 0x006D, 0x0033, 0x006D, 0x2215, 0x0073, 0x006D, 0x2215, 0x0073, 0x0032, 0x0050, 0x0061, 0x006B, 0x0050, 0x0061, 0x004D, 0x0050, 0x0061, 0x0047, 0x0050, 0x0061, 0x0072, 0x0061, 0x0064, 0x0072, 0x0061, 0x0064, 0x2215, 0x0073, 0x0072, 0x0061, 0x0064, 0x2215, 0x0073, 0x0032, 0x0070, 0x0073, 0x006E, 0x0073, 0x03BC, 0x0073, 0x006D, 0x0073, 0x0070, 0x0056, 0x006E, 0x0056, 0x03BC, 0x0056, 0x006D, 0x0056, 0x006B, 0x0056, 0x004D, 0x0056, 0x0070, 0x0057, 0x006E, 0x0057, 0x03BC, 0x0057, 0x006D, 0x0057, 0x006B, 0x0057, 0x004D, 0x0057 };
+unsigned short unac_data125[] = { 0x006B, 0x03A9, 0x004D, 0x03A9, 0x0061, 0x002E, 0x006D, 0x002E, 0x0042, 0x0071, 0x0063, 0x0063, 0x0063, 0x0064, 0x0043, 0x2215, 0x006B, 0x0067, 0x0043, 0x006F, 0x002E, 0x0064, 0x0042, 0x0047, 0x0079, 0x0068, 0x0061, 0x0048, 0x0050, 0x0069, 0x006E, 0x004B, 0x004B, 0x004B, 0x004D, 0x006B, 0x0074, 0x006C, 0x006D, 0x006C, 0x006E, 0x006C, 0x006F, 0x0067, 0x006C, 0x0078, 0x006D, 0x0062, 0x006D, 0x0069, 0x006C, 0x006D, 0x006F, 0x006C, 0x0050, 0x0048, 0x0070, 0x002E, 0x006D, 0x002E, 0x0050, 0x0050, 0x004D, 0x0050, 0x0052, 0x0073, 0x0072, 0x0053, 0x0076, 0x0057, 0x0062, 0xFFFF, 0xFFFF };
+unsigned short unac_data126[] = { 0x0031, 0x65E5, 0x0032, 0x65E5, 0x0033, 0x65E5, 0x0034, 0x65E5, 0x0035, 0x65E5, 0x0036, 0x65E5, 0x0037, 0x65E5, 0x0038, 0x65E5, 0x0039, 0x65E5, 0x0031, 0x0030, 0x65E5, 0x0031, 0x0031, 0x65E5, 0x0031, 0x0032, 0x65E5, 0x0031, 0x0033, 0x65E5, 0x0031, 0x0034, 0x65E5, 0x0031, 0x0035, 0x65E5, 0x0031, 0x0036, 0x65E5, 0x0031, 0x0037, 0x65E5, 0x0031, 0x0038, 0x65E5, 0x0031, 0x0039, 0x65E5, 0x0032, 0x0030, 0x65E5, 0x0032, 0x0031, 0x65E5, 0x0032, 0x0032, 0x65E5, 0x0032, 0x0033, 0x65E5, 0x0032, 0x0034, 0x65E5, 0x0032, 0x0035, 0x65E5, 0x0032, 0x0036, 0x65E5, 0x0032, 0x0037, 0x65E5, 0x0032, 0x0038, 0x65E5, 0x0032, 0x0039, 0x65E5, 0x0033, 0x0030, 0x65E5, 0x0033, 0x0031, 0x65E5, 0xFFFF };
+unsigned short unac_data127[] = { 0x8C48, 0x66F4, 0x8ECA, 0x8CC8, 0x6ED1, 0x4E32, 0x53E5, 0x9F9C, 0x9F9C, 0x5951, 0x91D1, 0x5587, 0x5948, 0x61F6, 0x7669, 0x7F85, 0x863F, 0x87BA, 0x88F8, 0x908F, 0x6A02, 0x6D1B, 0x70D9, 0x73DE, 0x843D, 0x916A, 0x99F1, 0x4E82, 0x5375, 0x6B04, 0x721B, 0x862D };
+unsigned short unac_data128[] = { 0x9E1E, 0x5D50, 0x6FEB, 0x85CD, 0x8964, 0x62C9, 0x81D8, 0x881F, 0x5ECA, 0x6717, 0x6D6A, 0x72FC, 0x90CE, 0x4F86, 0x51B7, 0x52DE, 0x64C4, 0x6AD3, 0x7210, 0x76E7, 0x8001, 0x8606, 0x865C, 0x8DEF, 0x9732, 0x9B6F, 0x9DFA, 0x788C, 0x797F, 0x7DA0, 0x83C9, 0x9304 };
+unsigned short unac_data129[] = { 0x9E7F, 0x8AD6, 0x58DF, 0x5F04, 0x7C60, 0x807E, 0x7262, 0x78CA, 0x8CC2, 0x96F7, 0x58D8, 0x5C62, 0x6A13, 0x6DDA, 0x6F0F, 0x7D2F, 0x7E37, 0x964B, 0x52D2, 0x808B, 0x51DC, 0x51CC, 0x7A1C, 0x7DBE, 0x83F1, 0x9675, 0x8B80, 0x62CF, 0x6A02, 0x8AFE, 0x4E39, 0x5BE7 };
+unsigned short unac_data130[] = { 0x6012, 0x7387, 0x7570, 0x5317, 0x78FB, 0x4FBF, 0x5FA9, 0x4E0D, 0x6CCC, 0x6578, 0x7D22, 0x53C3, 0x585E, 0x7701, 0x8449, 0x8AAA, 0x6BBA, 0x8FB0, 0x6C88, 0x62FE, 0x82E5, 0x63A0, 0x7565, 0x4EAE, 0x5169, 0x51C9, 0x6881, 0x7CE7, 0x826F, 0x8AD2, 0x91CF, 0x52F5 };
+unsigned short unac_data131[] = { 0x5442, 0x5973, 0x5EEC, 0x65C5, 0x6FFE, 0x792A, 0x95AD, 0x9A6A, 0x9E97, 0x9ECE, 0x529B, 0x66C6, 0x6B77, 0x8F62, 0x5E74, 0x6190, 0x6200, 0x649A, 0x6F23, 0x7149, 0x7489, 0x79CA, 0x7DF4, 0x806F, 0x8F26, 0x84EE, 0x9023, 0x934A, 0x5217, 0x52A3, 0x54BD, 0x70C8 };
+unsigned short unac_data132[] = { 0x88C2, 0x8AAA, 0x5EC9, 0x5FF5, 0x637B, 0x6BAE, 0x7C3E, 0x7375, 0x4EE4, 0x56F9, 0x5BE7, 0x5DBA, 0x601C, 0x73B2, 0x7469, 0x7F9A, 0x8046, 0x9234, 0x96F6, 0x9748, 0x9818, 0x4F8B, 0x79AE, 0x91B4, 0x96B8, 0x60E1, 0x4E86, 0x50DA, 0x5BEE, 0x5C3F, 0x6599, 0x6A02 };
+unsigned short unac_data133[] = { 0x71CE, 0x7642, 0x84FC, 0x907C, 0x9F8D, 0x6688, 0x962E, 0x5289, 0x677B, 0x67F3, 0x6D41, 0x6E9C, 0x7409, 0x7559, 0x786B, 0x7D10, 0x985E, 0x516D, 0x622E, 0x9678, 0x502B, 0x5D19, 0x6DEA, 0x8F2A, 0x5F8B, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540F, 0x5C65 };
+unsigned short unac_data134[] = { 0x6613, 0x674E, 0x68A8, 0x6CE5, 0x7406, 0x75E2, 0x7F79, 0x88CF, 0x88E1, 0x91CC, 0x96E2, 0x533F, 0x6EBA, 0x541D, 0x71D0, 0x7498, 0x85FA, 0x96A3, 0x9C57, 0x9E9F, 0x6797, 0x6DCB, 0x81E8, 0x7ACB, 0x7B20, 0x7C92, 0x72C0, 0x7099, 0x8B58, 0x4EC0, 0x8336, 0x523A };
+unsigned short unac_data135[] = { 0x5207, 0x5EA6, 0x62D3, 0x7CD6, 0x5B85, 0x6D1E, 0x66B4, 0x8F3B, 0x884C, 0x964D, 0x898B, 0x5ED3, 0x5140, 0x55C0, 0xFFFF, 0xFFFF, 0x585A, 0xFFFF, 0x6674, 0xFFFF, 0xFFFF, 0x51DE, 0x732A, 0x76CA, 0x793C, 0x795E, 0x7965, 0x798F, 0x9756, 0x7CBE, 0x7FBD, 0xFFFF };
+unsigned short unac_data136[] = { 0x8612, 0xFFFF, 0x8AF8, 0xFFFF, 0xFFFF, 0x9038, 0x90FD, 0xFFFF, 0xFFFF, 0xFFFF, 0x98EF, 0x98FC, 0x9928, 0x9DB4, 0xFFFF, 0xFFFF, 0x4FAE, 0x50E7, 0x514D, 0x52C9, 0x52E4, 0x5351, 0x559D, 0x5606, 0x5668, 0x5840, 0x58A8, 0x5C64, 0x5C6E, 0x6094, 0x6168, 0x618E };
+unsigned short unac_data137[] = { 0x61F2, 0x654F, 0x65E2, 0x6691, 0x6885, 0x6D77, 0x6E1A, 0x6F22, 0x716E, 0x722B, 0x7422, 0x7891, 0x793E, 0x7949, 0x7948, 0x7950, 0x7956, 0x795D, 0x798D, 0x798E, 0x7A40, 0x7A81, 0x7BC0, 0x7DF4, 0x7E09, 0x7E41, 0x7F72, 0x8005, 0x81ED, 0x8279, 0x8279, 0x8457 };
+unsigned short unac_data138[] = { 0x8910, 0x8996, 0x8B01, 0x8B39, 0x8CD3, 0x8D08, 0x8FB6, 0x9038, 0x96E3, 0x97FF, 0x983B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data139[] = { 0x0066, 0x0066, 0x0066, 0x0069, 0x0066, 0x006C, 0x0066, 0x0066, 0x0069, 0x0066, 0x0066, 0x006C, 0x0074, 0x0073, 0x0073, 0x0074, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0574, 0x0576, 0x0574, 0x0565, 0x0574, 0x056B, 0x057E, 0x0576, 0x0574, 0x056D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x05D9, 0xFFFF, 0x05F2 };
+unsigned short unac_data140[] = { 0x05E2, 0x05D0, 0x05D3, 0x05D4, 0x05DB, 0x05DC, 0x05DD, 0x05E8, 0x05EA, 0x002B, 0x05E9, 0x05E9, 0x05E9, 0x05E9, 0x05D0, 0x05D0, 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0xFFFF, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0xFFFF, 0x05DE, 0xFFFF };
+unsigned short unac_data141[] = { 0x05E0, 0x05E1, 0xFFFF, 0x05E3, 0x05E4, 0xFFFF, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x05D5, 0x05D1, 0x05DB, 0x05E4, 0x05D0, 0x05DC, 0x0671, 0x0671, 0x067B, 0x067B, 0x067B, 0x067B, 0x067E, 0x067E, 0x067E, 0x067E, 0x0680, 0x0680, 0x0680, 0x0680, 0x067A, 0x067A };
+unsigned short unac_data142[] = { 0x067A, 0x067A, 0x067F, 0x067F, 0x067F, 0x067F, 0x0679, 0x0679, 0x0679, 0x0679, 0x06A4, 0x06A4, 0x06A4, 0x06A4, 0x06A6, 0x06A6, 0x06A6, 0x06A6, 0x0684, 0x0684, 0x0684, 0x0684, 0x0683, 0x0683, 0x0683, 0x0683, 0x0686, 0x0686, 0x0686, 0x0686, 0x0687, 0x0687 };
+unsigned short unac_data143[] = { 0x0687, 0x0687, 0x068D, 0x068D, 0x068C, 0x068C, 0x068E, 0x068E, 0x0688, 0x0688, 0x0698, 0x0698, 0x0691, 0x0691, 0x06A9, 0x06A9, 0x06A9, 0x06A9, 0x06AF, 0x06AF, 0x06AF, 0x06AF, 0x06B3, 0x06B3, 0x06B3, 0x06B3, 0x06B1, 0x06B1, 0x06B1, 0x06B1, 0x06BA, 0x06BA };
+unsigned short unac_data144[] = { 0x06BB, 0x06BB, 0x06BB, 0x06BB, 0x06D5, 0x06D5, 0x06C1, 0x06C1, 0x06C1, 0x06C1, 0x06BE, 0x06BE, 0x06BE, 0x06BE, 0x06D2, 0x06D2, 0x06D2, 0x06D2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data145[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x06AD, 0x06AD, 0x06AD, 0x06AD, 0x06C7, 0x06C7, 0x06C6, 0x06C6, 0x06C8, 0x06C8, 0x06C7, 0x0674, 0x06CB, 0x06CB };
+unsigned short unac_data146[] = { 0x06C5, 0x06C5, 0x06C9, 0x06C9, 0x06D0, 0x06D0, 0x06D0, 0x06D0, 0x0649, 0x0649, 0x0627, 0x064A, 0x0627, 0x064A, 0x06D5, 0x064A, 0x06D5, 0x064A, 0x0648, 0x064A, 0x0648, 0x064A, 0x06C7, 0x064A, 0x06C7, 0x064A, 0x06C6, 0x064A, 0x06C6, 0x064A, 0x06C8, 0x064A, 0x06C8, 0x064A, 0x06D0, 0x064A, 0x06D0, 0x064A, 0x06D0, 0x064A, 0x0649, 0x064A, 0x0649, 0x064A, 0x0649, 0x064A, 0x06CC, 0x06CC, 0x06CC, 0x06CC };
+unsigned short unac_data147[] = { 0x062C, 0x064A, 0x062D, 0x064A, 0x0645, 0x064A, 0x0649, 0x064A, 0x064A, 0x064A, 0x0628, 0x062C, 0x0628, 0x062D, 0x0628, 0x062E, 0x0628, 0x0645, 0x0628, 0x0649, 0x0628, 0x064A, 0x062A, 0x062C, 0x062A, 0x062D, 0x062A, 0x062E, 0x062A, 0x0645, 0x062A, 0x0649, 0x062A, 0x064A, 0x062B, 0x062C, 0x062B, 0x0645, 0x062B, 0x0649, 0x062B, 0x064A, 0x062C, 0x062D, 0x062C, 0x0645, 0x062D, 0x062C, 0x062D, 0x0645, 0x062E, 0x062C, 0x062E, 0x062D, 0x062E, 0x0645, 0x0633, 0x062C, 0x0633, 0x062D, 0x0633, 0x062E, 0x0633, 0x0645 };
+unsigned short unac_data148[] = { 0x0635, 0x062D, 0x0635, 0x0645, 0x0636, 0x062C, 0x0636, 0x062D, 0x0636, 0x062E, 0x0636, 0x0645, 0x0637, 0x062D, 0x0637, 0x0645, 0x0638, 0x0645, 0x0639, 0x062C, 0x0639, 0x0645, 0x063A, 0x062C, 0x063A, 0x0645, 0x0641, 0x062C, 0x0641, 0x062D, 0x0641, 0x062E, 0x0641, 0x0645, 0x0641, 0x0649, 0x0641, 0x064A, 0x0642, 0x062D, 0x0642, 0x0645, 0x0642, 0x0649, 0x0642, 0x064A, 0x0643, 0x0627, 0x0643, 0x062C, 0x0643, 0x062D, 0x0643, 0x062E, 0x0643, 0x0644, 0x0643, 0x0645, 0x0643, 0x0649, 0x0643, 0x064A, 0x0644, 0x062C };
+unsigned short unac_data149[] = { 0x0644, 0x062D, 0x0644, 0x062E, 0x0644, 0x0645, 0x0644, 0x0649, 0x0644, 0x064A, 0x0645, 0x062C, 0x0645, 0x062D, 0x0645, 0x062E, 0x0645, 0x0645, 0x0645, 0x0649, 0x0645, 0x064A, 0x0646, 0x062C, 0x0646, 0x062D, 0x0646, 0x062E, 0x0646, 0x0645, 0x0646, 0x0649, 0x0646, 0x064A, 0x0647, 0x062C, 0x0647, 0x0645, 0x0647, 0x0649, 0x0647, 0x064A, 0x064A, 0x062C, 0x064A, 0x062D, 0x064A, 0x062E, 0x064A, 0x0645, 0x064A, 0x0649, 0x064A, 0x064A, 0x0630, 0x0631, 0x0649, 0x0020, 0x0020 };
+unsigned short unac_data150[] = { 0x0020, 0x0020, 0x0020, 0x0020, 0x0631, 0x064A, 0x0632, 0x064A, 0x0645, 0x064A, 0x0646, 0x064A, 0x0649, 0x064A, 0x064A, 0x064A, 0x0628, 0x0631, 0x0628, 0x0632, 0x0628, 0x0645, 0x0628, 0x0646, 0x0628, 0x0649, 0x0628, 0x064A, 0x062A, 0x0631, 0x062A, 0x0632, 0x062A, 0x0645, 0x062A, 0x0646, 0x062A, 0x0649, 0x062A, 0x064A, 0x062B, 0x0631, 0x062B, 0x0632, 0x062B, 0x0645, 0x062B, 0x0646, 0x062B, 0x0649, 0x062B, 0x064A, 0x0641, 0x0649, 0x0641, 0x064A, 0x0642, 0x0649, 0x0642, 0x064A };
+unsigned short unac_data151[] = { 0x0643, 0x0627, 0x0643, 0x0644, 0x0643, 0x0645, 0x0643, 0x0649, 0x0643, 0x064A, 0x0644, 0x0645, 0x0644, 0x0649, 0x0644, 0x064A, 0x0645, 0x0627, 0x0645, 0x0645, 0x0646, 0x0631, 0x0646, 0x0632, 0x0646, 0x0645, 0x0646, 0x0646, 0x0646, 0x0649, 0x0646, 0x064A, 0x0649, 0x064A, 0x0631, 0x064A, 0x0632, 0x064A, 0x0645, 0x064A, 0x0646, 0x064A, 0x0649, 0x064A, 0x064A, 0x062C, 0x064A, 0x062D, 0x064A, 0x062E, 0x064A, 0x0645, 0x064A, 0x0647, 0x064A, 0x0628, 0x062C, 0x0628, 0x062D, 0x0628, 0x062E, 0x0628, 0x0645 };
+unsigned short unac_data152[] = { 0x0628, 0x0647, 0x062A, 0x062C, 0x062A, 0x062D, 0x062A, 0x062E, 0x062A, 0x0645, 0x062A, 0x0647, 0x062B, 0x0645, 0x062C, 0x062D, 0x062C, 0x0645, 0x062D, 0x062C, 0x062D, 0x0645, 0x062E, 0x062C, 0x062E, 0x0645, 0x0633, 0x062C, 0x0633, 0x062D, 0x0633, 0x062E, 0x0633, 0x0645, 0x0635, 0x062D, 0x0635, 0x062E, 0x0635, 0x0645, 0x0636, 0x062C, 0x0636, 0x062D, 0x0636, 0x062E, 0x0636, 0x0645, 0x0637, 0x062D, 0x0638, 0x0645, 0x0639, 0x062C, 0x0639, 0x0645, 0x063A, 0x062C, 0x063A, 0x0645, 0x0641, 0x062C, 0x0641, 0x062D };
+unsigned short unac_data153[] = { 0x0641, 0x062E, 0x0641, 0x0645, 0x0642, 0x062D, 0x0642, 0x0645, 0x0643, 0x062C, 0x0643, 0x062D, 0x0643, 0x062E, 0x0643, 0x0644, 0x0643, 0x0645, 0x0644, 0x062C, 0x0644, 0x062D, 0x0644, 0x062E, 0x0644, 0x0645, 0x0644, 0x0647, 0x0645, 0x062C, 0x0645, 0x062D, 0x0645, 0x062E, 0x0645, 0x0645, 0x0646, 0x062C, 0x0646, 0x062D, 0x0646, 0x062E, 0x0646, 0x0645, 0x0646, 0x0647, 0x0647, 0x062C, 0x0647, 0x0645, 0x0647, 0x064A, 0x062C, 0x064A, 0x062D, 0x064A, 0x062E, 0x064A, 0x0645, 0x064A, 0x0647, 0x0645, 0x064A };
+unsigned short unac_data154[] = { 0x0647, 0x064A, 0x0628, 0x0645, 0x0628, 0x0647, 0x062A, 0x0645, 0x062A, 0x0647, 0x062B, 0x0645, 0x062B, 0x0647, 0x0633, 0x0645, 0x0633, 0x0647, 0x0634, 0x0645, 0x0634, 0x0647, 0x0643, 0x0644, 0x0643, 0x0645, 0x0644, 0x0645, 0x0646, 0x0645, 0x0646, 0x0647, 0x064A, 0x0645, 0x064A, 0x0647, 0x0640, 0x0640, 0x0640, 0x0637, 0x0649, 0x0637, 0x064A, 0x0639, 0x0649, 0x0639, 0x064A, 0x063A, 0x0649, 0x063A, 0x064A, 0x0633, 0x0649, 0x0633, 0x064A, 0x0634, 0x0649, 0x0634, 0x064A, 0x062D, 0x0649 };
+unsigned short unac_data155[] = { 0x062D, 0x064A, 0x062C, 0x0649, 0x062C, 0x064A, 0x062E, 0x0649, 0x062E, 0x064A, 0x0635, 0x0649, 0x0635, 0x064A, 0x0636, 0x0649, 0x0636, 0x064A, 0x0634, 0x062C, 0x0634, 0x062D, 0x0634, 0x062E, 0x0634, 0x0645, 0x0634, 0x0631, 0x0633, 0x0631, 0x0635, 0x0631, 0x0636, 0x0631, 0x0637, 0x0649, 0x0637, 0x064A, 0x0639, 0x0649, 0x0639, 0x064A, 0x063A, 0x0649, 0x063A, 0x064A, 0x0633, 0x0649, 0x0633, 0x064A, 0x0634, 0x0649, 0x0634, 0x064A, 0x062D, 0x0649, 0x062D, 0x064A, 0x062C, 0x0649, 0x062C, 0x064A, 0x062E, 0x0649 };
+unsigned short unac_data156[] = { 0x062E, 0x064A, 0x0635, 0x0649, 0x0635, 0x064A, 0x0636, 0x0649, 0x0636, 0x064A, 0x0634, 0x062C, 0x0634, 0x062D, 0x0634, 0x062E, 0x0634, 0x0645, 0x0634, 0x0631, 0x0633, 0x0631, 0x0635, 0x0631, 0x0636, 0x0631, 0x0634, 0x062C, 0x0634, 0x062D, 0x0634, 0x062E, 0x0634, 0x0645, 0x0633, 0x0647, 0x0634, 0x0647, 0x0637, 0x0645, 0x0633, 0x062C, 0x0633, 0x062D, 0x0633, 0x062E, 0x0634, 0x062C, 0x0634, 0x062D, 0x0634, 0x062E, 0x0637, 0x0645, 0x0638, 0x0645, 0x0627, 0x0627, 0xFFFF, 0xFFFF };
+unsigned short unac_data157[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x062A, 0x062C, 0x0645, 0x062A, 0x062D, 0x062C, 0x062A, 0x062D, 0x062C, 0x062A, 0x062D, 0x0645, 0x062A, 0x062E, 0x0645, 0x062A, 0x0645, 0x062C, 0x062A, 0x0645, 0x062D, 0x062A, 0x0645, 0x062E, 0x062C, 0x0645, 0x062D, 0x062C, 0x0645, 0x062D, 0x062D, 0x0645, 0x064A, 0x062D, 0x0645, 0x0649, 0x0633, 0x062D, 0x062C, 0x0633, 0x062C, 0x062D, 0x0633, 0x062C, 0x0649, 0x0633, 0x0645, 0x062D };
+unsigned short unac_data158[] = { 0x0633, 0x0645, 0x062D, 0x0633, 0x0645, 0x062C, 0x0633, 0x0645, 0x0645, 0x0633, 0x0645, 0x0645, 0x0635, 0x062D, 0x062D, 0x0635, 0x062D, 0x062D, 0x0635, 0x0645, 0x0645, 0x0634, 0x062D, 0x0645, 0x0634, 0x062D, 0x0645, 0x0634, 0x062C, 0x064A, 0x0634, 0x0645, 0x062E, 0x0634, 0x0645, 0x062E, 0x0634, 0x0645, 0x0645, 0x0634, 0x0645, 0x0645, 0x0636, 0x062D, 0x0649, 0x0636, 0x062E, 0x0645, 0x0636, 0x062E, 0x0645, 0x0637, 0x0645, 0x062D, 0x0637, 0x0645, 0x062D, 0x0637, 0x0645, 0x0645, 0x0637, 0x0645, 0x064A, 0x0639, 0x062C, 0x0645, 0x0639, 0x0645, 0x0645, 0x0639, 0x0645, 0x0645, 0x0639, 0x0645, 0x0649, 0x063A, 0x0645, 0x0645, 0x063A, 0x0645, 0x064A, 0x063A, 0x0645, 0x0649, 0x0641, 0x062E, 0x0645, 0x0641, 0x062E, 0x0645, 0x0642, 0x0645, 0x062D, 0x0642, 0x0645, 0x0645 };
+unsigned short unac_data159[] = { 0x0644, 0x062D, 0x0645, 0x0644, 0x062D, 0x064A, 0x0644, 0x062D, 0x0649, 0x0644, 0x062C, 0x062C, 0x0644, 0x062C, 0x062C, 0x0644, 0x062E, 0x0645, 0x0644, 0x062E, 0x0645, 0x0644, 0x0645, 0x062D, 0x0644, 0x0645, 0x062D, 0x0645, 0x062D, 0x062C, 0x0645, 0x062D, 0x0645, 0x0645, 0x062D, 0x064A, 0x0645, 0x062C, 0x062D, 0x0645, 0x062C, 0x0645, 0x0645, 0x062E, 0x062C, 0x0645, 0x062E, 0x0645, 0xFFFF, 0xFFFF, 0x0645, 0x062C, 0x062E, 0x0647, 0x0645, 0x062C, 0x0647, 0x0645, 0x0645, 0x0646, 0x062D, 0x0645, 0x0646, 0x062D, 0x0649, 0x0646, 0x062C, 0x0645, 0x0646, 0x062C, 0x0645, 0x0646, 0x062C, 0x0649, 0x0646, 0x0645, 0x064A, 0x0646, 0x0645, 0x0649, 0x064A, 0x0645, 0x0645, 0x064A, 0x0645, 0x0645, 0x0628, 0x062E, 0x064A, 0x062A, 0x062C, 0x064A };
+unsigned short unac_data160[] = { 0x062A, 0x062C, 0x0649, 0x062A, 0x062E, 0x064A, 0x062A, 0x062E, 0x0649, 0x062A, 0x0645, 0x064A, 0x062A, 0x0645, 0x0649, 0x062C, 0x0645, 0x064A, 0x062C, 0x062D, 0x0649, 0x062C, 0x0645, 0x0649, 0x0633, 0x062E, 0x0649, 0x0635, 0x062D, 0x064A, 0x0634, 0x062D, 0x064A, 0x0636, 0x062D, 0x064A, 0x0644, 0x062C, 0x064A, 0x0644, 0x0645, 0x064A, 0x064A, 0x062D, 0x064A, 0x064A, 0x062C, 0x064A, 0x064A, 0x0645, 0x064A, 0x0645, 0x0645, 0x064A, 0x0642, 0x0645, 0x064A, 0x0646, 0x062D, 0x064A, 0x0642, 0x0645, 0x062D, 0x0644, 0x062D, 0x0645, 0x0639, 0x0645, 0x064A, 0x0643, 0x0645, 0x064A, 0x0646, 0x062C, 0x062D, 0x0645, 0x062E, 0x064A, 0x0644, 0x062C, 0x0645, 0x0643, 0x0645, 0x0645, 0x0644, 0x062C, 0x0645, 0x0646, 0x062C, 0x062D, 0x062C, 0x062D, 0x064A, 0x062D, 0x062C, 0x064A };
+unsigned short unac_data161[] = { 0x0645, 0x062C, 0x064A, 0x0641, 0x0645, 0x064A, 0x0628, 0x062D, 0x064A, 0x0643, 0x0645, 0x0645, 0x0639, 0x062C, 0x0645, 0x0635, 0x0645, 0x0645, 0x0633, 0x062E, 0x064A, 0x0646, 0x062C, 0x064A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data162[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0635, 0x0644, 0x06D2, 0x0642, 0x0644, 0x06D2, 0x0627, 0x0644, 0x0644, 0x0647, 0x0627, 0x0643, 0x0628, 0x0631, 0x0645, 0x062D, 0x0645, 0x062F, 0x0635, 0x0644, 0x0639, 0x0645, 0x0631, 0x0633, 0x0648, 0x0644, 0x0639, 0x0644, 0x064A, 0x0647, 0x0648, 0x0633, 0x0644, 0x0645, 0x0635, 0x0644, 0x0649, 0x0635, 0x0644, 0x0649, 0x0020, 0x0627, 0x0644, 0x0644, 0x0647, 0x0020, 0x0639, 0x0644, 0x064A, 0x0647, 0x0020, 0x0648, 0x0633, 0x0644, 0x0645, 0x062C, 0x0644, 0x0020, 0x062C, 0x0644, 0x0627, 0x0644, 0x0647, 0x0631, 0x06CC, 0x0627, 0x0644, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data163[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x002E, 0x002E, 0x2014, 0x2013, 0x005F, 0x005F, 0x0028, 0x0029, 0x007B, 0x007D, 0x3014, 0x3015, 0x3010, 0x3011, 0x300A, 0x300B, 0x3008 };
+unsigned short unac_data164[] = { 0x3009, 0x300C, 0x300D, 0x300E, 0x300F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0020, 0x0020, 0x0020, 0x0020, 0x005F, 0x005F, 0x005F, 0x002C, 0x3001, 0x002E, 0xFFFF, 0x003B, 0x003A, 0x003F, 0x0021, 0x2014, 0x0028, 0x0029, 0x007B, 0x007D, 0x3014, 0x3015, 0x0023 };
+unsigned short unac_data165[] = { 0x0026, 0x002A, 0x002B, 0x002D, 0x003C, 0x003E, 0x003D, 0xFFFF, 0x005C, 0x0024, 0x0025, 0x0040, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0020, 0x0640, 0x0020, 0xFFFF, 0x0020, 0xFFFF, 0x0020, 0x0640, 0x0020, 0x0640, 0x0020, 0x0640, 0x0020, 0x0640, 0x0020, 0x0640 };
+unsigned short unac_data166[] = { 0x0621, 0x0627, 0x0627, 0x0627, 0x0627, 0x0648, 0x0648, 0x0627, 0x0627, 0x064A, 0x064A, 0x064A, 0x064A, 0x0627, 0x0627, 0x0628, 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062A, 0x062A, 0x062A, 0x062A, 0x062B, 0x062B, 0x062B, 0x062B, 0x062C, 0x062C, 0x062C };
+unsigned short unac_data167[] = { 0x062C, 0x062D, 0x062D, 0x062D, 0x062D, 0x062E, 0x062E, 0x062E, 0x062E, 0x062F, 0x062F, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632, 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634, 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636 };
+unsigned short unac_data168[] = { 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638, 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063A, 0x063A, 0x063A, 0x063A, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642, 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644 };
+unsigned short unac_data169[] = { 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646, 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649, 0x0649, 0x064A, 0x064A, 0x064A, 0x064A, 0x0644, 0x0627, 0x0644, 0x0627, 0x0644, 0x0627, 0x0644, 0x0627, 0x0644, 0x0627, 0x0644, 0x0627, 0x0644, 0x0627, 0x0644, 0x0627, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data170[] = { 0xFFFF, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F };
+unsigned short unac_data171[] = { 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F };
+unsigned short unac_data172[] = { 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x2985 };
+unsigned short unac_data173[] = { 0x2986, 0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1, 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3, 0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD };
+unsigned short unac_data174[] = { 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3, 0xFFFF, 0xFFFF };
+unsigned short unac_data175[] = { 0x1160, 0x1100, 0x1101, 0x11AA, 0x1102, 0x11AC, 0x11AD, 0x1103, 0x1104, 0x1105, 0x11B0, 0x11B1, 0x11B2, 0x11B3, 0x11B4, 0x11B5, 0x111A, 0x1106, 0x1107, 0x1108, 0x1121, 0x1109, 0x110A, 0x110B, 0x110C, 0x110D, 0x110E, 0x110F, 0x1110, 0x1111, 0x1112, 0xFFFF };
+unsigned short unac_data176[] = { 0xFFFF, 0xFFFF, 0x1161, 0x1162, 0x1163, 0x1164, 0x1165, 0x1166, 0xFFFF, 0xFFFF, 0x1167, 0x1168, 0x1169, 0x116A, 0x116B, 0x116C, 0xFFFF, 0xFFFF, 0x116D, 0x116E, 0x116F, 0x1170, 0x1171, 0x1172, 0xFFFF, 0xFFFF, 0x1173, 0x1174, 0x1175, 0xFFFF, 0xFFFF, 0xFFFF };
+unsigned short unac_data177[] = { 0x00A2, 0x00A3, 0x00AC, 0x0020, 0x00A6, 0x00A5, 0x20A9, 0xFFFF, 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25A0, 0x25CB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
+
+unsigned short* unac_data_table[UNAC_BLOCK_COUNT] = {
+unac_data0,
+unac_data1,
+unac_data2,
+unac_data3,
+unac_data4,
+unac_data5,
+unac_data6,
+unac_data7,
+unac_data8,
+unac_data9,
+unac_data10,
+unac_data11,
+unac_data12,
+unac_data13,
+unac_data14,
+unac_data15,
+unac_data16,
+unac_data17,
+unac_data18,
+unac_data19,
+unac_data20,
+unac_data21,
+unac_data22,
+unac_data23,
+unac_data24,
+unac_data25,
+unac_data26,
+unac_data27,
+unac_data28,
+unac_data29,
+unac_data30,
+unac_data31,
+unac_data32,
+unac_data33,
+unac_data34,
+unac_data35,
+unac_data36,
+unac_data37,
+unac_data38,
+unac_data39,
+unac_data40,
+unac_data41,
+unac_data42,
+unac_data43,
+unac_data44,
+unac_data45,
+unac_data46,
+unac_data47,
+unac_data48,
+unac_data49,
+unac_data50,
+unac_data51,
+unac_data52,
+unac_data53,
+unac_data54,
+unac_data55,
+unac_data56,
+unac_data57,
+unac_data58,
+unac_data59,
+unac_data60,
+unac_data61,
+unac_data62,
+unac_data63,
+unac_data64,
+unac_data65,
+unac_data66,
+unac_data67,
+unac_data68,
+unac_data69,
+unac_data70,
+unac_data71,
+unac_data72,
+unac_data73,
+unac_data74,
+unac_data75,
+unac_data76,
+unac_data77,
+unac_data78,
+unac_data79,
+unac_data80,
+unac_data81,
+unac_data82,
+unac_data83,
+unac_data84,
+unac_data85,
+unac_data86,
+unac_data87,
+unac_data88,
+unac_data89,
+unac_data90,
+unac_data91,
+unac_data92,
+unac_data93,
+unac_data94,
+unac_data95,
+unac_data96,
+unac_data97,
+unac_data98,
+unac_data99,
+unac_data100,
+unac_data101,
+unac_data102,
+unac_data103,
+unac_data104,
+unac_data105,
+unac_data106,
+unac_data107,
+unac_data108,
+unac_data109,
+unac_data110,
+unac_data111,
+unac_data112,
+unac_data113,
+unac_data114,
+unac_data115,
+unac_data116,
+unac_data117,
+unac_data118,
+unac_data119,
+unac_data120,
+unac_data121,
+unac_data122,
+unac_data123,
+unac_data124,
+unac_data125,
+unac_data126,
+unac_data127,
+unac_data128,
+unac_data129,
+unac_data130,
+unac_data131,
+unac_data132,
+unac_data133,
+unac_data134,
+unac_data135,
+unac_data136,
+unac_data137,
+unac_data138,
+unac_data139,
+unac_data140,
+unac_data141,
+unac_data142,
+unac_data143,
+unac_data144,
+unac_data145,
+unac_data146,
+unac_data147,
+unac_data148,
+unac_data149,
+unac_data150,
+unac_data151,
+unac_data152,
+unac_data153,
+unac_data154,
+unac_data155,
+unac_data156,
+unac_data157,
+unac_data158,
+unac_data159,
+unac_data160,
+unac_data161,
+unac_data162,
+unac_data163,
+unac_data164,
+unac_data165,
+unac_data166,
+unac_data167,
+unac_data168,
+unac_data169,
+unac_data170,
+unac_data171,
+unac_data172,
+unac_data173,
+unac_data174,
+unac_data175,
+unac_data176,
+unac_data177
+};
+/* Generated by builder. Do not modify. End tables */
+
+/*
+ * Debug level. See unac.h for a detailed discussion of the
+ * values.
+ */
+static int debug_level = UNAC_DEBUG_NONE;
+
+#ifdef UNAC_DEBUG_AVAILABLE
+
+/*
+ * Default debug function, printing on stderr.
+ */
+static void debug_doprint_default(const char* message, void* data)
+{
+  fprintf(stderr, "%s", message);
+}
+
+/*
+ * Default doprint handler is debug_doprint.
+ */
+static unac_debug_print_t debug_doprint = debug_doprint_default;
+/*
+ * Default app data is null.
+ */
+static void* debug_appdata = (void*)0;
+
+/*
+ * Generate a debug message (arguments ala printf) and
+ * send it to the doprint handler.
+ */
+#define DEBUG debug_print("%s:%d: ", __FILE__, __LINE__), debug_print
+#define DEBUG_APPEND debug_print
+static void debug_print(const char* message, ...)
+{
+#define UNAC_MAXIMUM_MESSAGE_SIZE 512
+  /*
+   * UNAC_MAXIMUM_MESSAGE_SIZE is supposedly enough but I
+   * do trust some vsnprintf implementations to be bugous.
+   */
+  char unac_message_buffer[UNAC_MAXIMUM_MESSAGE_SIZE+1] = { '\0' };
+  va_list args;
+  va_start(args, message);
+  if(vsnprintf(unac_message_buffer, UNAC_MAXIMUM_MESSAGE_SIZE, message, args) < 0) {
+    char tmp[UNAC_MAXIMUM_MESSAGE_SIZE];
+    sprintf(tmp, "[message larger than %d, truncated]", UNAC_MAXIMUM_MESSAGE_SIZE);
+    debug_doprint(tmp, debug_appdata);
+  }
+  va_end(args);
+  unac_message_buffer[UNAC_MAXIMUM_MESSAGE_SIZE] = '\0';
+
+  debug_doprint(unac_message_buffer, debug_appdata);
+}
+
+void unac_debug_callback(int level, unac_debug_print_t function, void* data)
+{
+  debug_level = level;
+  if(function)
+    debug_doprint = function;
+  debug_appdata = data;
+}
+
+#else /* UNAC_DEBUG_AVAILABLE */
+#define DEBUG 
+#define DEBUG_APPEND
+#endif /* UNAC_DEBUG_AVAILABLE */
+
+
+/*
+ * If UTF-16BE exists, use it. If not, use UTF-16 and hope it is
+ * encoded in big endian. This fallback is a iconv related
+ * compatibility hack introduced in some GNU/Linux distributions that
+ * did not know UTF-16BE.
+ */
+static const char* utf16be()
+{
+  iconv_t cd;
+  static char* name = 0;
+
+  if(name == 0) {
+    if((cd = iconv_open("UTF-16BE", "UTF-16BE")) == (iconv_t)-1) {
+      if(debug_level == UNAC_DEBUG_LOW) DEBUG("could not find UTF-16BE (see iconv -l), using UTF-16. If UTF-16 happens to be encoded in little endian, be prepared for an horrible mess.");
+      name = "UTF-16";
+    } else {
+      iconv_close(cd);
+      name = "UTF-16BE";
+    }
+  }
+
+  return name;
+}
+
+int unac_string_utf16(const char* in, size_t in_length,
+		      char** outp, size_t* out_lengthp)
+{
+  char* out;
+  int out_size;
+  int out_length;
+  int i;
+
+  out_size = in_length > 0 ? in_length : 1024;
+  if(*outp) {
+    out = *outp;
+    /* +1 for null */
+    out = realloc(out, out_size + 1);
+  } else {
+    /* +1 for null */
+    out = malloc(out_size + 1);
+    if(out == 0) return -1;
+  }
+  out_length = 0;
+
+  for(i = 0; i < in_length; i += 2) {
+    unsigned short c;
+    unsigned short* p;
+    int l;
+    int k;
+    c = (in[i] << 8) | (in[i + 1] & 0xff);
+    /*
+     * Lookup the tables for decomposition information
+     */
+    unac_char_utf16(c, p, l);
+    /*
+     * Explain what's done in great detail
+     */
+    if(debug_level == UNAC_DEBUG_HIGH) {
+      unsigned short index = unac_indexes[(c) >> UNAC_BLOCK_SHIFT];
+      unsigned char position = (c) & UNAC_BLOCK_MASK;
+      DEBUG("unac_data%d[%d] & unac_positions[%d][%d]: ", index, unac_positions[index][position], index, position+1);
+      DEBUG_APPEND("0x%04x => ", (c));
+      if(l == 0) {
+	DEBUG_APPEND("untouched\n");
+      } else {
+	int i;
+	for(i = 0; i < l; i++)
+	  DEBUG_APPEND("0x%04x ", p[i]);
+	DEBUG_APPEND("\n");
+      }
+    }
+    /*
+     * Make sure there is enough space to hold the decomposition
+     */
+    if(out_length + ((l + 1) * 2) > out_size) {
+      out_size += ((l + 1) * 2) + 1024;
+      out = realloc(out, out_size);
+      if(out == 0) {
+	if(debug_level == UNAC_DEBUG_LOW)
+	  DEBUG("realloc %d bytes failed\n", out_size);
+	return -1;
+      }
+    }
+    if(l > 0) {
+      /*
+       * If there is a decomposition, insert it in the output 
+       * string.
+       */
+      for(k = 0; k < l; k++) {
+	out[out_length++] = (p[k] >> 8) & 0xff;
+	out[out_length++] = (p[k] & 0xff);
+      }
+    } else {
+      /*
+       * If there is no decomposition leave it unchanged
+       */
+      out[out_length++] = in[i];
+      out[out_length++] = in[i + 1];
+    }
+  }
+
+  *outp = out;
+  *out_lengthp = out_length;
+  (*outp)[*out_lengthp] = '\0';
+
+  return 0;
+}
+
+#define MAXOUT 1024
+
+static int convert(const char* from, const char* to,
+		   const char* in, size_t in_length,
+		   char** outp, size_t* out_lengthp);
+
+/*
+ * Convert buffer <in> containing string encoded in charset <from> into
+ * a string in charset <to> and return it in buffer <outp>. The <outp>
+ * points to a malloced string large enough to hold the conversion result.
+ * It is the responsibility of the caller to free this array.
+ * The out string is always null terminated.
+ */
+static int convert(const char* from, const char* to,
+		   const char* in, size_t in_length,
+		   char** outp, size_t* out_lengthp)
+{
+  iconv_t cd;
+  char* out;
+  size_t out_remain;
+  size_t out_size;
+  char* out_base;
+  int from_utf16 = !strcmp(utf16be(), from);
+  const char space[] = { 0x00, 0x20 };
+
+  out_size = in_length > 0 ? (in_length * 2) : 1024;
+  if(*outp) {
+    out = *outp;
+    /* +1 for null */
+    out = realloc(out, out_size + 1);
+  } else {
+    /* +1 for null */
+    out = malloc(out_size + 1);
+    if(out == 0) return -1;
+  }
+  out_remain = out_size;
+  out_base = out;
+
+  if((cd = iconv_open(to, from)) == (iconv_t)-1) {
+    return -1;
+  }
+  do {
+    if(iconv(cd, (ICONV_CONST char **) &in, &in_length, &out, &out_remain) == (size_t)-1) {
+      switch(errno) {
+      case EILSEQ:
+	/*
+	 * If an illegal sequence is found in the context of unac_string
+	 * it means the unaccented version of a character contains
+	 * a sequence that cannot be mapped back to the original charset.
+	 * For instance, the 1/4 character in ISO-8859-1 is decomposed
+	 * in three characters including the FRACTION SLASH (2044) which
+	 * have no equivalent in the ISO-8859-1 map. One can argue that
+	 * the conversions tables should map it to the regular / character
+	 * or that a <compat> entry should be associated with it. 
+	 *
+	 * To cope with this situation, convert silently transform all
+	 * illegal sequences (EILSEQ) into a SPACE character 0x0020.
+	 *
+	 * In the general conversion case this behaviour is not desirable.
+	 * However, it is not the responsibility of this program to cope
+	 * with inconsistencies of the Unicode description and a bug report
+	 * should be submited to Unicode so that they can fix the problem.
+	 * 
+	 */
+	if(from_utf16) {
+	  const char* tmp = space;
+	  size_t tmp_length = 2;
+	  if(iconv(cd, (ICONV_CONST char **) &tmp, &tmp_length, &out, &out_remain) == (size_t)-1) {
+	    if(errno == E2BIG)
+	      /* fall thru to the E2BIG case below */;
+	    else
+	      return -1;
+	  } else {
+	    /* The offending character was replaced by a SPACE, skip it. */
+	    in += 2;
+	    in_length -= 2;
+	    /* And continue conversion. */
+	    break;
+	  }
+	} else {
+	  return -1;
+	}
+      case E2BIG:
+	{
+	  /*
+	 * The output does not fit in the current out buffer, enlarge it.
+	 */
+	  int length = out - out_base;
+	  out_size *= 2;
+	  /* +1 for null */
+	  out_base = realloc(out_base, out_size + 1);
+	  if(out_base == 0) return -1;
+	  out = out_base + length;
+	  out_remain = out_size - length;
+	}
+	break;
+      default:
+	return -1;
+	break;
+      }
+    }
+  } while(in_length > 0);
+  iconv_close(cd);
+
+  *outp = out_base;
+  *out_lengthp = out - out_base;
+  (*outp)[*out_lengthp] = '\0';
+
+  return 0;
+}
+
+int unac_string(const char* charset,
+		const char* in, size_t in_length,
+		char** outp, size_t* out_lengthp)
+{
+  /*
+   * When converting an empty string, skip everything but alloc the
+   * buffer if NULL pointer.
+   */
+  if(in_length <= 0) {
+    if(!*outp)
+      *outp = malloc(32);
+    (*outp)[0] = '\0';
+    *out_lengthp = 0;
+  } else {
+    char* utf16 = 0;
+    int utf16_length = 0;
+    char* utf16_unaccented = 0;
+    int utf16_unaccented_length = 0;
+  
+    if(convert(charset, utf16be(), in, in_length, &utf16, &utf16_length) < 0) {
+      return -1;
+    }
+
+    unac_string_utf16(utf16, utf16_length, &utf16_unaccented, &utf16_unaccented_length);
+    free(utf16);
+
+    if(convert(utf16be(), charset, utf16_unaccented, utf16_unaccented_length, outp, out_lengthp) < 0) {
+      return -1;
+    }
+    free(utf16_unaccented);
+  }
+
+  return 0;
+}
+
+
+const char* unac_version(void)
+{
+  return UNAC_VERSION;
+}
+
Index: /indexers/branches/3.03a/packages/unac/unac.h
===================================================================
--- /indexers/branches/3.03a/packages/unac/unac.h	(revision 14757)
+++ /indexers/branches/3.03a/packages/unac/unac.h	(revision 14757)
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Loic Dachary <loic@senga.org>
+ *
+ * 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 of the License, 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 program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Provides functions to strip accents from a string in all the
+ * charset supported by iconv(3).
+ *
+ * See the unac(3) manual page for more information.
+ *
+ */
+
+#ifndef _unac_h
+#define _unac_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Generated by builder. Do not modify. Start defines */
+#define UNAC_BLOCK_SHIFT 5
+#define UNAC_BLOCK_MASK ((1 << UNAC_BLOCK_SHIFT) - 1)
+#define UNAC_BLOCK_SIZE (1 << UNAC_BLOCK_SHIFT)
+#define UNAC_BLOCK_COUNT 178
+#define UNAC_INDEXES_SIZE (0x10000 >> UNAC_BLOCK_SHIFT)
+/* Generated by builder. Do not modify. End defines */
+
+/*
+ * Return the unaccented equivalent of the UTF-16 character <c>
+ * in the pointer <p>. The length of the unsigned short array pointed
+ * by <p> is returned in the <l> argument.
+ * The C++ prototype of this macro would be:
+ *
+ * void unac_char(const unsigned short c, unsigned short*& p, int& l)
+ *
+ * See unac(3) in IMPLEMENTATION NOTES for more information about the
+ * tables (unac_data_table, unac_positions) layout.
+ */ 
+#define unac_char_utf16(c,p,l) \
+  { \
+    unsigned short index = unac_indexes[(c) >> UNAC_BLOCK_SHIFT]; \
+    unsigned char position = (c) & UNAC_BLOCK_MASK; \
+    (p) = &(unac_data_table[index][unac_positions[index][position]]); \
+    (l) = unac_positions[index][position + 1] - unac_positions[index][position]; \
+    if((l) == 1 && *(p) == 0xFFFF) { \
+      (p) = 0; \
+      (l) = 0; \
+    } \
+  }
+
+/*
+ * Return the unaccented equivalent of the UTF-16 string <in> of
+ * length <in_length> in the pointer <out>. The length of the UTF-16
+ * string returned in <out> is stored in <out_length>. If the pointer
+ * *out is null, a new string is allocated using malloc(3). If the
+ * pointer *out is not null, the available length must also be given
+ * in the *out_length argument.  The pointer passed to *out must have
+ * been allocated by malloc(3) and may be reallocated by realloc(3) if
+ * needs be. It is the responsibility of the caller to free the
+ * pointer returned in *out.  The return value is 0 on success and -1
+ * on error, in which case the errno variable is set to the
+ * corresponding error code.
+ */
+int unac_string_utf16(const char* in, size_t in_length,
+		char** out, size_t* out_length);
+
+/*
+ * The semantic of this function is stricly equal to the function
+ * unac_string_utf16. The <charset> argument applies to the content of the
+ * input string. It is converted to UTF-16 using iconv(3) before calling
+ * the unac_string function and the result is converted from UTF-16 to
+ * the specified <charset> before returning it in the <out> pointer.
+ * For efficiency purpose it is recommended that the caller uses
+ * unac_string and iconv(3) to save buffer allocations overhead. 
+ * The return value is 0 on success and -1 on error, in which case
+ * the errno variable is set to the corresponding error code.
+ */
+int unac_string(const char* charset,
+		const char* in, size_t in_length,
+		char** out, size_t* out_length);
+
+/*
+ * Return unac version number.
+ */
+const char* unac_version(void);
+
+#define UNAC_DEBUG_NONE	0x00
+#define UNAC_DEBUG_LOW	0x01
+#define UNAC_DEBUG_HIGH 0x02
+
+#ifdef HAVE_VSNPRINTF
+#define UNAC_DEBUG_AVAILABLE 1
+/*
+ * Set the unac debug level. <l> is one of:
+ * UNAC_DEBUG_NONE for no debug messages at all
+ * UNAC_DEBUG_LOW for minimal information
+ * UNAC_DEBUG_HIGH for extremely verbose information,
+ *                 only usable when translating a few short strings.
+ *
+ * unac_debug with anything but UNAC_DEBUG_NONE is not
+ * thread safe.
+ */
+#define unac_debug(l) unac_debug_callback((l), 0, (void*)0);
+
+/*
+ * Set the debug level and define a printing function callback.
+ * The <level> debug level is the same as in unac_debug. The
+ * <function> is in charge of dealing with the debug messages,
+ * presumably to print them to the user. The <data> is an opaque
+ * pointer that is passed along to <function>, should it
+ * need to manage a persistent context.
+ *
+ * The prototype of <function> allows two arguments. The first
+ * is the debug message (const char*), the second is the opaque
+ * pointer given as <data> argument to unac_debug_callback.
+ *
+ * If <function> is NULL, messages are printed on the standard
+ * error output using fprintf(stderr...).
+ * 
+ * unac_debug_callback with anything but UNAC_DEBUG_NONE is not
+ * thread safe.
+ *
+ */
+typedef void (*unac_debug_print_t)(const char* message, void* data);
+void unac_debug_callback(int level, unac_debug_print_t function, void* data);
+#endif /* HAVE_VSNPRINTF */
+
+/* Generated by builder. Do not modify. Start declarations */
+extern unsigned short unac_indexes[UNAC_INDEXES_SIZE];
+extern unsigned char unac_positions[UNAC_BLOCK_COUNT][UNAC_BLOCK_SIZE + 1];
+extern unsigned short* unac_data_table[UNAC_BLOCK_COUNT];
+extern unsigned short unac_data0[];
+extern unsigned short unac_data1[];
+extern unsigned short unac_data2[];
+extern unsigned short unac_data3[];
+extern unsigned short unac_data4[];
+extern unsigned short unac_data5[];
+extern unsigned short unac_data6[];
+extern unsigned short unac_data7[];
+extern unsigned short unac_data8[];
+extern unsigned short unac_data9[];
+extern unsigned short unac_data10[];
+extern unsigned short unac_data11[];
+extern unsigned short unac_data12[];
+extern unsigned short unac_data13[];
+extern unsigned short unac_data14[];
+extern unsigned short unac_data15[];
+extern unsigned short unac_data16[];
+extern unsigned short unac_data17[];
+extern unsigned short unac_data18[];
+extern unsigned short unac_data19[];
+extern unsigned short unac_data20[];
+extern unsigned short unac_data21[];
+extern unsigned short unac_data22[];
+extern unsigned short unac_data23[];
+extern unsigned short unac_data24[];
+extern unsigned short unac_data25[];
+extern unsigned short unac_data26[];
+extern unsigned short unac_data27[];
+extern unsigned short unac_data28[];
+extern unsigned short unac_data29[];
+extern unsigned short unac_data30[];
+extern unsigned short unac_data31[];
+extern unsigned short unac_data32[];
+extern unsigned short unac_data33[];
+extern unsigned short unac_data34[];
+extern unsigned short unac_data35[];
+extern unsigned short unac_data36[];
+extern unsigned short unac_data37[];
+extern unsigned short unac_data38[];
+extern unsigned short unac_data39[];
+extern unsigned short unac_data40[];
+extern unsigned short unac_data41[];
+extern unsigned short unac_data42[];
+extern unsigned short unac_data43[];
+extern unsigned short unac_data44[];
+extern unsigned short unac_data45[];
+extern unsigned short unac_data46[];
+extern unsigned short unac_data47[];
+extern unsigned short unac_data48[];
+extern unsigned short unac_data49[];
+extern unsigned short unac_data50[];
+extern unsigned short unac_data51[];
+extern unsigned short unac_data52[];
+extern unsigned short unac_data53[];
+extern unsigned short unac_data54[];
+extern unsigned short unac_data55[];
+extern unsigned short unac_data56[];
+extern unsigned short unac_data57[];
+extern unsigned short unac_data58[];
+extern unsigned short unac_data59[];
+extern unsigned short unac_data60[];
+extern unsigned short unac_data61[];
+extern unsigned short unac_data62[];
+extern unsigned short unac_data63[];
+extern unsigned short unac_data64[];
+extern unsigned short unac_data65[];
+extern unsigned short unac_data66[];
+extern unsigned short unac_data67[];
+extern unsigned short unac_data68[];
+extern unsigned short unac_data69[];
+extern unsigned short unac_data70[];
+extern unsigned short unac_data71[];
+extern unsigned short unac_data72[];
+extern unsigned short unac_data73[];
+extern unsigned short unac_data74[];
+extern unsigned short unac_data75[];
+extern unsigned short unac_data76[];
+extern unsigned short unac_data77[];
+extern unsigned short unac_data78[];
+extern unsigned short unac_data79[];
+extern unsigned short unac_data80[];
+extern unsigned short unac_data81[];
+extern unsigned short unac_data82[];
+extern unsigned short unac_data83[];
+extern unsigned short unac_data84[];
+extern unsigned short unac_data85[];
+extern unsigned short unac_data86[];
+extern unsigned short unac_data87[];
+extern unsigned short unac_data88[];
+extern unsigned short unac_data89[];
+extern unsigned short unac_data90[];
+extern unsigned short unac_data91[];
+extern unsigned short unac_data92[];
+extern unsigned short unac_data93[];
+extern unsigned short unac_data94[];
+extern unsigned short unac_data95[];
+extern unsigned short unac_data96[];
+extern unsigned short unac_data97[];
+extern unsigned short unac_data98[];
+extern unsigned short unac_data99[];
+extern unsigned short unac_data100[];
+extern unsigned short unac_data101[];
+extern unsigned short unac_data102[];
+extern unsigned short unac_data103[];
+extern unsigned short unac_data104[];
+extern unsigned short unac_data105[];
+extern unsigned short unac_data106[];
+extern unsigned short unac_data107[];
+extern unsigned short unac_data108[];
+extern unsigned short unac_data109[];
+extern unsigned short unac_data110[];
+extern unsigned short unac_data111[];
+extern unsigned short unac_data112[];
+extern unsigned short unac_data113[];
+extern unsigned short unac_data114[];
+extern unsigned short unac_data115[];
+extern unsigned short unac_data116[];
+extern unsigned short unac_data117[];
+extern unsigned short unac_data118[];
+extern unsigned short unac_data119[];
+extern unsigned short unac_data120[];
+extern unsigned short unac_data121[];
+extern unsigned short unac_data122[];
+extern unsigned short unac_data123[];
+extern unsigned short unac_data124[];
+extern unsigned short unac_data125[];
+extern unsigned short unac_data126[];
+extern unsigned short unac_data127[];
+extern unsigned short unac_data128[];
+extern unsigned short unac_data129[];
+extern unsigned short unac_data130[];
+extern unsigned short unac_data131[];
+extern unsigned short unac_data132[];
+extern unsigned short unac_data133[];
+extern unsigned short unac_data134[];
+extern unsigned short unac_data135[];
+extern unsigned short unac_data136[];
+extern unsigned short unac_data137[];
+extern unsigned short unac_data138[];
+extern unsigned short unac_data139[];
+extern unsigned short unac_data140[];
+extern unsigned short unac_data141[];
+extern unsigned short unac_data142[];
+extern unsigned short unac_data143[];
+extern unsigned short unac_data144[];
+extern unsigned short unac_data145[];
+extern unsigned short unac_data146[];
+extern unsigned short unac_data147[];
+extern unsigned short unac_data148[];
+extern unsigned short unac_data149[];
+extern unsigned short unac_data150[];
+extern unsigned short unac_data151[];
+extern unsigned short unac_data152[];
+extern unsigned short unac_data153[];
+extern unsigned short unac_data154[];
+extern unsigned short unac_data155[];
+extern unsigned short unac_data156[];
+extern unsigned short unac_data157[];
+extern unsigned short unac_data158[];
+extern unsigned short unac_data159[];
+extern unsigned short unac_data160[];
+extern unsigned short unac_data161[];
+extern unsigned short unac_data162[];
+extern unsigned short unac_data163[];
+extern unsigned short unac_data164[];
+extern unsigned short unac_data165[];
+extern unsigned short unac_data166[];
+extern unsigned short unac_data167[];
+extern unsigned short unac_data168[];
+extern unsigned short unac_data169[];
+extern unsigned short unac_data170[];
+extern unsigned short unac_data171[];
+extern unsigned short unac_data172[];
+extern unsigned short unac_data173[];
+extern unsigned short unac_data174[];
+extern unsigned short unac_data175[];
+extern unsigned short unac_data176[];
+extern unsigned short unac_data177[];
+/* Generated by builder. Do not modify. End declarations */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _unac_h */
Index: /indexers/branches/3.03a/packages/unac/win32.mak
===================================================================
--- /indexers/branches/3.03a/packages/unac/win32.mak	(revision 14757)
+++ /indexers/branches/3.03a/packages/unac/win32.mak	(revision 14757)
@@ -0,0 +1,59 @@
+# UNAC
+
+CC = cl
+AR = lib
+
+DLL = 0
+DLLDEBUG = 0
+GSDL_VC4 = 0
+
+INCLUDES = -I. -DUNAC_VERSION=\"1.7.0\"
+!IF $(GSDL_VC4)
+CPPFLAGS = -GX
+!ELSE
+CPPFLAGS = -EHsc
+!ENDIF
+
+!IF $(DLL)
+CPPFLAGS = $(CPPFLAGS) -MD 
+!ELSE
+!IF ($(DLLDEBUG))
+CPPFLAGS = $(CPPFLAGS) -MDd
+!ENDIF
+!ENDIF
+
+
+COMPILE = $(CC) -nologo -c $(CPPFLAGS) $(DEFS) $(INCLUDES)
+LINK = $(CC) -nologo $(LDFLAGS)
+
+.SUFFIXES:
+.SUFFIXES: .c .obj
+.c.obj:
+	$(COMPILE) $<
+
+ANSI2KNR = 
+o = .obj
+e = .exe
+
+LIBS = $(ICONVLIB)
+
+HEADERS = unac.h
+
+SOURCES = unac.c 
+
+OBJECTS = unac$o 
+
+DEFS = 
+
+all: libunac.lib
+
+libunac.lib: $(OBJECTS)
+	if EXIST libunac.lib del libunac.lib
+	$(AR) -nologo /out:libunac.lib $(OBJECTS)
+
+install: all
+
+clean:
+	del *.obj libunac.lib
+
+
Index: /indexers/branches/3.03a/winMake.bat
===================================================================
--- /indexers/branches/3.03a/winMake.bat	(revision 14757)
+++ /indexers/branches/3.03a/winMake.bat	(revision 14757)
@@ -0,0 +1,69 @@
+@echo off
+
+set MAKE=nmake
+set MAKE_OPTIONS=/f
+
+if ""%1"" == """" goto all
+if ""%1"" == ""all"" goto go
+if ""%1"" == ""install"" goto go
+if ""%1"" == ""clean"" goto clean
+
+:unknown
+	echo Error: Unrecognized argument %1.
+	goto done
+
+:clean
+	del bin\*
+
+:go
+	if ""%2"" == ""javaonly"" goto java
+	if ""%2"" == ""nojava"" goto nojava
+
+:all
+	mkdir bin
+	cd packages\unac
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..\..
+
+	cd mg
+	call winMake.bat %1 
+	cd ..
+
+	cd mgpp
+	call winMake.bat %1 
+	cd ..
+	
+	cd lucene-gs
+	call winMake.bat %1
+	cd ..
+	goto done
+
+:java
+	cd mg
+	call winMake.bat %1 javaonly
+	cd ..
+
+	cd mgpp
+	call winMake.bat %1 javaonly
+	cd ..
+	
+	cd lucene-gs
+	call winMake.bat %1 
+	cd ..
+	goto done
+
+:nojava
+	cd packages\unac
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..\..
+
+	cd mg
+	call winMake.bat %1 nojava
+	cd ..
+
+	cd mgpp
+	call winMake.bat %1 nojava
+	cd ..
+	goto done
+
+:done
