summaryrefslogtreecommitdiffstats
path: root/contrib/gperf/src
diff options
context:
space:
mode:
authorkris <kris@FreeBSD.org>2000-03-25 07:45:29 +0000
committerkris <kris@FreeBSD.org>2000-03-25 07:45:29 +0000
commit533744c77137b94ed05e2ca445ba97d71c79ee5f (patch)
treefa102ad70fa8d5585900bf7e1872826b467f5d2e /contrib/gperf/src
parent6cfe3ae61b383acc12d75bc595be2ab185d5586c (diff)
downloadFreeBSD-src-533744c77137b94ed05e2ca445ba97d71c79ee5f.zip
FreeBSD-src-533744c77137b94ed05e2ca445ba97d71c79ee5f.tar.gz
Virgin import of gperf v2.7
Diffstat (limited to 'contrib/gperf/src')
-rw-r--r--contrib/gperf/src/Makefile.in143
-rw-r--r--contrib/gperf/src/bool-array.cc49
-rw-r--r--contrib/gperf/src/bool-array.h66
-rw-r--r--contrib/gperf/src/bool-array.icc85
-rw-r--r--contrib/gperf/src/config.h.in19
-rwxr-xr-xcontrib/gperf/src/configure1573
-rw-r--r--contrib/gperf/src/configure.in71
-rw-r--r--contrib/gperf/src/gen-perf.cc342
-rw-r--r--contrib/gperf/src/gen-perf.h50
-rw-r--r--contrib/gperf/src/hash-table.cc91
-rw-r--r--contrib/gperf/src/hash-table.h42
-rw-r--r--contrib/gperf/src/iterator.cc88
-rw-r--r--contrib/gperf/src/iterator.h28
-rw-r--r--contrib/gperf/src/key-list.cc1957
-rw-r--r--contrib/gperf/src/key-list.h96
-rw-r--r--contrib/gperf/src/list-node.cc101
-rw-r--r--contrib/gperf/src/list-node.h45
-rw-r--r--contrib/gperf/src/main.cc72
-rw-r--r--contrib/gperf/src/new.cc87
-rw-r--r--contrib/gperf/src/options.cc668
-rw-r--r--contrib/gperf/src/options.h226
-rw-r--r--contrib/gperf/src/options.icc175
-rw-r--r--contrib/gperf/src/read-line.cc97
-rw-r--r--contrib/gperf/src/read-line.h53
-rw-r--r--contrib/gperf/src/read-line.icc47
-rw-r--r--contrib/gperf/src/trace.cc35
-rw-r--r--contrib/gperf/src/trace.h40
-rw-r--r--contrib/gperf/src/vectors.cc25
-rw-r--r--contrib/gperf/src/vectors.h37
-rw-r--r--contrib/gperf/src/version.cc22
-rw-r--r--contrib/gperf/src/version.h23
31 files changed, 6330 insertions, 123 deletions
diff --git a/contrib/gperf/src/Makefile.in b/contrib/gperf/src/Makefile.in
new file mode 100644
index 0000000..ec1e682
--- /dev/null
+++ b/contrib/gperf/src/Makefile.in
@@ -0,0 +1,143 @@
+# Makefile for gperf/src
+
+# Copyright (C) 1989, 1992, 1993, 1998 Free Software Foundation, Inc.
+# written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+#
+# This file is part of GNU GPERF.
+#
+# GNU GPERF is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+#
+# GNU GPERF is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU GPERF; see the file COPYING. If not, write to the Free
+# Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+
+#### Start of system configuration section. ####
+
+# Directories used by "make":
+srcdir = @srcdir@
+
+# Directories used by "make install":
+prefix = @prefix@
+local_prefix = /usr/local
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+
+# Programs used by "make":
+# C compiler
+CC = @CC@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+# C++ compiler
+CXX = @CXX@
+CXXFLAGS = @CXXFLAGS@
+CXXCPP = @CXXCPP@
+# Other
+MV = mv
+LN = ln
+RM = rm -f
+@SET_MAKE@
+
+# Programs used by "make install":
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+#### End of system configuration section. ####
+
+SHELL = /bin/sh
+
+VPATH = $(srcdir)
+
+OBJECTS = new.o options.o iterator.o main.o gen-perf.o key-list.o list-node.o \
+ hash-table.o bool-array.o read-line.o trace.o vectors.o version.o
+LIBS = ../lib/libgp.a -lm
+CPPFLAGS = -I. -I$(srcdir)/../lib
+
+TARGETPROG = gperf
+
+all : $(TARGETPROG)
+
+$(TARGETPROG): $(OBJECTS)
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS)
+
+# Don't use implicit rules, since AIX "make" and OSF/1 "make" don't always
+# expand $< correctly in this context.
+#
+#%.o : %.c
+# $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+#
+#%.o : %.cc
+# $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
+
+# Dependencies.
+CONFIG_H = config.h
+VERSION_H = version.h
+VECTORS_H = vectors.h
+TRACE_H = trace.h
+READ_LINE_H = read-line.h read-line.icc $(TRACE_H)
+OPTIONS_H = options.h options.icc $(TRACE_H)
+LIST_NODE_H = list-node.h $(VECTORS_H)
+KEY_LIST_H = key-list.h $(LIST_NODE_H) $(VECTORS_H) $(READ_LINE_H)
+ITERATOR_H = iterator.h
+HASH_TABLE_H = hash-table.h $(LIST_NODE_H)
+BOOL_ARRAY_H = bool-array.h bool-array.icc $(TRACE_H) $(OPTIONS_H)
+GEN_PERF_H = gen-perf.h $(KEY_LIST_H) $(BOOL_ARRAY_H)
+
+bool-array.o : bool-array.cc $(BOOL_ARRAY_H) $(OPTIONS_H) $(TRACE_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/bool-array.cc
+gen-perf.o : gen-perf.cc $(GEN_PERF_H) $(OPTIONS_H) $(TRACE_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/gen-perf.cc
+hash-table.o : hash-table.cc $(HASH_TABLE_H) $(OPTIONS_H) $(TRACE_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/hash-table.cc
+iterator.o : iterator.cc $(ITERATOR_H) $(TRACE_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/iterator.cc
+key-list.o : key-list.cc $(KEY_LIST_H) $(OPTIONS_H) $(READ_LINE_H) $(HASH_TABLE_H) $(TRACE_H) $(VERSION_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/key-list.cc
+list-node.o : list-node.cc $(LIST_NODE_H) $(OPTIONS_H) $(TRACE_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/list-node.cc
+main.o : main.cc $(OPTIONS_H) $(GEN_PERF_H) $(TRACE_H) $(CONFIG_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/main.cc
+new.o : new.cc $(TRACE_H) $(CONFIG_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/new.cc
+options.o : options.cc $(OPTIONS_H) $(ITERATOR_H) $(TRACE_H) $(VECTORS_H) $(VERSION_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/options.cc
+read-line.o : read-line.cc $(READ_LINE_H) $(OPTIONS_H) $(TRACE_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/read-line.cc
+trace.o : trace.cc $(TRACE_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/trace.cc
+vectors.o : vectors.cc $(VECTORS_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/vectors.cc
+version.o : version.cc $(VERSION_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/version.cc
+
+install : all force
+ if [ ! -d $(bindir) ] ; then mkdir $(bindir) ; fi
+ $(INSTALL_PROGRAM) $(TARGETPROG) $(bindir)/$(TARGETPROG)
+
+installdirs : force
+ if [ ! -d $(bindir) ] ; then mkdir $(bindir) ; fi
+
+uninstall : force
+ $(RM) $(bindir)/$(TARGETPROG)
+
+check : all
+
+mostlyclean : clean
+
+clean : force
+ $(RM) *~ *.s *.o *.a $(TARGETPROG) core
+
+distclean : clean
+ $(RM) config.status config.log config.cache Makefile config.h
+
+maintainer-clean : distclean
+
+force :
diff --git a/contrib/gperf/src/bool-array.cc b/contrib/gperf/src/bool-array.cc
new file mode 100644
index 0000000..0774b2d
--- /dev/null
+++ b/contrib/gperf/src/bool-array.cc
@@ -0,0 +1,49 @@
+/* Fast lookup table abstraction implemented as an Iteration Number Array
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "bool-array.h"
+
+#include <stdio.h>
+#include <string.h>
+#include "options.h"
+#include "trace.h"
+
+STORAGE_TYPE * Bool_Array::storage_array;
+STORAGE_TYPE Bool_Array::iteration_number;
+unsigned int Bool_Array::size;
+
+/* Prints out debugging diagnostics. */
+
+Bool_Array::~Bool_Array (void)
+{
+ T (Trace t ("Bool_Array::~Bool_Array");)
+ if (option[DEBUG])
+ fprintf (stderr, "\ndumping boolean array information\n"
+ "size = %d\niteration number = %d\nend of array dump\n",
+ size, iteration_number);
+}
+
+#ifndef __OPTIMIZE__
+
+#define INLINE /* not inline */
+#include "bool-array.icc"
+#undef INLINE
+
+#endif /* not defined __OPTIMIZE__ */
diff --git a/contrib/gperf/src/bool-array.h b/contrib/gperf/src/bool-array.h
new file mode 100644
index 0000000..8330fcd
--- /dev/null
+++ b/contrib/gperf/src/bool-array.h
@@ -0,0 +1,66 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Simple lookup table abstraction implemented as an Iteration Number Array.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Define and implement a simple boolean array abstraction,
+ uses an Iteration Numbering implementation to save on initialization time. */
+
+#ifndef bool_array_h
+#define bool_array_h 1
+
+#include "trace.h"
+
+#ifdef LO_CAL
+/* If we are on a memory diet then we'll only make these use a limited
+ amount of storage space. */
+typedef unsigned short STORAGE_TYPE;
+#else
+typedef unsigned int STORAGE_TYPE;
+#endif
+
+class Bool_Array
+{
+private:
+ static STORAGE_TYPE *storage_array; /* Initialization of the index space. */
+ static STORAGE_TYPE iteration_number; /* Keep track of the current iteration. */
+ static unsigned int size; /* Keep track of array size. */
+
+public:
+ Bool_Array (void);
+ ~Bool_Array (void);
+ static void init (STORAGE_TYPE *buffer, unsigned int s);
+ static int find (int hash_value);
+ static void reset (void);
+};
+
+#ifdef __OPTIMIZE__ /* efficiency hack! */
+
+#include <stdio.h>
+#include <string.h>
+#include "options.h"
+#define INLINE inline
+#include "bool-array.icc"
+#undef INLINE
+
+#endif
+
+#endif
diff --git a/contrib/gperf/src/bool-array.icc b/contrib/gperf/src/bool-array.icc
new file mode 100644
index 0000000..6de6f23
--- /dev/null
+++ b/contrib/gperf/src/bool-array.icc
@@ -0,0 +1,85 @@
+/* Inline Functions for bool-array.{h,cc}.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+// This needs:
+//#include <stdio.h>
+//#include <string.h>
+//#include "options.h"
+//#include "trace.h"
+
+INLINE
+Bool_Array::Bool_Array (void)
+{
+ T (Trace t ("Bool_Array::Bool_Array");)
+ storage_array = 0;
+ iteration_number = size = 0;
+}
+
+INLINE void
+Bool_Array::init (STORAGE_TYPE *buffer, unsigned int s)
+{
+ T (Trace t ("Bool_Array::init");)
+ size = s;
+ iteration_number = 1;
+ storage_array = buffer;
+ memset (storage_array, 0, s * sizeof (*storage_array));
+ if (option[DEBUG])
+ fprintf (stderr, "\nbool array size = %d, total bytes = %d\n",
+ size, (unsigned int) (size * sizeof (*storage_array)));
+}
+
+INLINE int
+Bool_Array::find (int index)
+{
+ T (Trace t ("Bool_Array::find");)
+ if (storage_array[index] == iteration_number)
+ return 1;
+ else
+ {
+ storage_array[index] = iteration_number;
+ return 0;
+ }
+}
+
+INLINE void
+Bool_Array::reset (void)
+{
+ T (Trace t ("Bool_Array::reset");)
+ /* If we wrap around it's time to zero things out again! However, this only
+ occurs once about every 2^31 or 2^15 iterations, so it should probably
+ never happen! */
+
+ if (++iteration_number == 0)
+ {
+ if (option[DEBUG])
+ {
+ fprintf (stderr, "(re-initializing bool_array)...");
+ fflush (stderr);
+ }
+ iteration_number = 1;
+ memset (storage_array, 0, size * sizeof (*storage_array));
+ if (option[DEBUG])
+ {
+ fprintf (stderr, "done\n");
+ fflush (stderr);
+ }
+ }
+}
diff --git a/contrib/gperf/src/config.h.in b/contrib/gperf/src/config.h.in
new file mode 100644
index 0000000..4d3d762
--- /dev/null
+++ b/contrib/gperf/src/config.h.in
@@ -0,0 +1,19 @@
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if the C++ compiler supports "throw ()" declarations. */
+#undef HAVE_THROW_DECL
+
+/* Define if you have the getrlimit function. */
+#undef HAVE_GETRLIMIT
+
+/* Define if you have the setrlimit function. */
+#undef HAVE_SETRLIMIT
+
+/* Define if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_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
diff --git a/contrib/gperf/src/configure b/contrib/gperf/src/configure
new file mode 100755
index 0000000..d3d1091
--- /dev/null
+++ b/contrib/gperf/src/configure
@@ -0,0 +1,1573 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+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'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+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
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # 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 ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$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" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) 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)
+ # 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 << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --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
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$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)
+ 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 ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ 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 "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# 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
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=gen-perf.cc
+
+# 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_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ 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 "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# 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 "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:524: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 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 conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:553: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+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 $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:582: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ ac_prog_rejected=no
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+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 $# -gt 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
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:630: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext <<EOF
+#line 640 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+if { (eval echo configure:644: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:664: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:669: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:678: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+ ac_test_CFLAGS="${CFLAGS+set}"
+ ac_save_CFLAGS="$CFLAGS"
+ CFLAGS=
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:693: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+ if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+ elif test $ac_cv_prog_cc_g = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-O2"
+ fi
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+ echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:721: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 736 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:742: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 753 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:759: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+ for ac_prog in $CCC c++ g++ gcc CC cxx cc++
+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 $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:786: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CXX="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CXX="$ac_cv_prog_CXX"
+if test -n "$CXX"; then
+ echo "$ac_t""$CXX" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CXX" && break
+done
+test -n "$CXX" || CXX="gcc"
+
+
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:817: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+cat > conftest.$ac_ext <<EOF
+#line 827 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+if { (eval echo configure:831: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ ac_cv_prog_cxx_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cxx_cross=no
+ else
+ ac_cv_prog_cxx_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cxx_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6
+if test $ac_cv_prog_cxx_works = no; then
+ { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:857: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
+echo "configure:862: checking whether we are using GNU C++" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.C <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:871: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gxx=yes
+else
+ ac_cv_prog_gxx=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gxx" 1>&6
+
+if test $ac_cv_prog_gxx = yes; then
+ GXX=yes
+ ac_test_CXXFLAGS="${CXXFLAGS+set}"
+ ac_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS=
+ echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
+echo "configure:886: checking whether ${CXX-g++} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.cc
+if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then
+ ac_cv_prog_cxx_g=yes
+else
+ ac_cv_prog_cxx_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6
+ if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS="$ac_save_CXXFLAGS"
+ elif test $ac_cv_prog_cxx_g = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-O2"
+ fi
+else
+ GXX=
+ test "${CXXFLAGS+set}" = set || CXXFLAGS="-g"
+fi
+
+ echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6
+echo "configure:914: checking how to run the C++ preprocessor" >&5
+if test -z "$CXXCPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+ CXXCPP="${CXX-g++} -E"
+ cat > conftest.$ac_ext <<EOF
+#line 927 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:932: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CXXCPP=/lib/cpp
+fi
+rm -f conftest*
+ ac_cv_prog_CXXCPP="$CXXCPP"
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+fi
+fi
+CXXCPP="$ac_cv_prog_CXXCPP"
+echo "$ac_t""$CXXCPP" 1>&6
+
+ # 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
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:967: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'cl_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ for ac_prog in ginstall installbsd scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ else
+ if test $ac_prog = installbsd &&
+ grep src/bos $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX installbsd doesn't work without option "-g".
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_ifs"
+ # As a last resort, use cp.
+ test -z "$cl_cv_path_install" && cl_cv_path_install="cp"
+
+fi
+ INSTALL="$cl_cv_path_install"
+fi
+echo "$ac_t""$INSTALL" 1>&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)'
+if test -z "$INSTALL_DATA"; then
+ case "$INSTALL" in
+ cp | */cp ) INSTALL_DATA='$(INSTALL)' ;;
+ * ) INSTALL_DATA='$(INSTALL) -m 644' ;;
+ esac
+fi
+
+ echo $ac_n "checking for working throw()""... $ac_c" 1>&6
+echo "configure:1020: checking for working throw()" >&5
+if eval "test \"`echo '$''{'gp_cxx_throw_decl'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+cat > conftest.$ac_ext <<EOF
+#line 1034 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+void operator delete (void* ptr) throw() {}
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1042: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gp_cxx_throw_decl=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gp_cxx_throw_decl=no
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+fi
+
+echo "$ac_t""$gp_cxx_throw_decl" 1>&6
+if test $gp_cxx_throw_decl = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_THROW_DECL 1
+EOF
+
+fi
+for ac_hdr in unistd.h sys/time.h sys/resource.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1073: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1078 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1083: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ if test $ac_cv_header_sys_resource_h = yes; then
+for ac_func in getrlimit
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1113: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1118 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* 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();
+
+int main() {
+
+/* 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
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ if test $ac_cv_func_getrlimit = yes; then
+for ac_func in setrlimit
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1169: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1174 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* 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();
+
+int main() {
+
+/* 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
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1197: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ fi
+fi
+trap '' 1 2 15
+cat > confcache <<\EOF
+# 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. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# 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) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@CXX@%$CXX%g
+s%@CXXCPP@%$CXXCPP%g
+s%@INSTALL@%$INSTALL%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# 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_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # 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" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# 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='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. 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.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# 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.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/contrib/gperf/src/configure.in b/contrib/gperf/src/configure.in
new file mode 100644
index 0000000..68d267c
--- /dev/null
+++ b/contrib/gperf/src/configure.in
@@ -0,0 +1,71 @@
+dnl autoconf configuration for gperf/src
+
+dnl Copyright (C) 1998 Free Software Foundation, Inc.
+dnl written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+dnl
+dnl This file is part of GNU GPERF.
+dnl
+dnl GNU GPERF 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 1, or (at your option)
+dnl any later version.
+dnl
+dnl GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the
+dnl Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+dnl MA 02111-1307, USA.
+
+AC_INIT(gen-perf.cc)
+AC_CONFIG_HEADER(config.h)
+AC_PROG_MAKE_SET
+dnl
+dnl checks for programs
+dnl
+AC_PROG_CC
+ dnl sets variable CC
+AC_PROG_CPP
+ dnl sets variable CPP
+AC_PROG_CXX
+ dnl sets variable CXX
+AC_PROG_CXXCPP
+ dnl sets variable CXXCPP
+CL_PROG_INSTALL
+ dnl sets variables INSTALL, INSTALL_DATA, INSTALL_PROGRAM
+dnl
+dnl checks for compiler characteristics
+dnl
+AC_MSG_CHECKING([for working throw()])
+AC_CACHE_VAL(gp_cxx_throw_decl,[
+AC_LANG_SAVE()
+AC_LANG_CPLUSPLUS()
+AC_TRY_COMPILE([#include <stdlib.h>
+void operator delete (void* ptr) throw() {}], [],
+gp_cxx_throw_decl=yes, gp_cxx_throw_decl=no)
+AC_LANG_RESTORE()
+])
+AC_MSG_RESULT([$]gp_cxx_throw_decl)
+if test [$]gp_cxx_throw_decl = yes; then
+ AC_DEFINE(HAVE_THROW_DECL)
+fi
+dnl
+dnl checks for functions and declarations
+dnl
+AC_CHECK_HEADERS(unistd.h sys/time.h sys/resource.h)
+ dnl DEFs HAVE_UNISTD_H, HAVE_SYS_TIME_H, HAVE_SYS_RESOURCE_H
+if test $ac_cv_header_sys_resource_h = yes; then
+AC_CHECK_FUNCS(getrlimit)
+ dnl DEFS HAVE_GETRLIMIT
+if test $ac_cv_func_getrlimit = yes; then
+AC_CHECK_FUNCS(setrlimit)
+ dnl DEFS HAVE_SETRLIMIT
+fi
+fi
+dnl
+dnl That's it.
+dnl
+AC_OUTPUT(Makefile)
diff --git a/contrib/gperf/src/gen-perf.cc b/contrib/gperf/src/gen-perf.cc
new file mode 100644
index 0000000..0d0ad41
--- /dev/null
+++ b/contrib/gperf/src/gen-perf.cc
@@ -0,0 +1,342 @@
+/* Provides high-level routines to manipulate the keywork list
+ structures the code generation output.
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include <stdio.h>
+#include <stdlib.h> /* declares rand(), srand() */
+#include <time.h> /* declares time() */
+#include "options.h"
+#include "gen-perf.h"
+#include "trace.h"
+
+/* Efficiently returns the least power of two greater than or equal to X! */
+#define POW(X) ((!X)?1:(X-=1,X|=X>>1,X|=X>>2,X|=X>>4,X|=X>>8,X|=X>>16,(++X)))
+
+/* Reads input keys, possibly applies the reordering heuristic, sets the
+ maximum associated value size (rounded up to the nearest power of 2),
+ may initialize the associated values array, and determines the maximum
+ hash table size. Note: using the random numbers is often helpful,
+ though not as deterministic, of course! */
+
+Gen_Perf::Gen_Perf (void)
+{
+ T (Trace t ("Gen_Perf::Gen_Perf");)
+ int asso_value_max;
+ int non_linked_length;
+
+ Key_List::read_keys ();
+ if (option[ORDER])
+ reorder ();
+ asso_value_max = option.get_asso_max ();
+ non_linked_length = Key_List::keyword_list_length ();
+ num_done = 1;
+ fewest_collisions = 0;
+ if (asso_value_max == 0)
+ asso_value_max = non_linked_length;
+ else if (asso_value_max > 0)
+ asso_value_max *= non_linked_length;
+ else /* if (asso_value_max < 0) */
+ asso_value_max = non_linked_length / -asso_value_max;
+ option.set_asso_max (POW (asso_value_max));
+
+ if (option[RANDOM])
+ {
+ srand ((long) time (0));
+
+ for (int i = 0; i < ALPHA_SIZE; i++)
+ asso_values[i] = (rand () & asso_value_max - 1);
+ }
+ else
+ {
+ int asso_value = option.initial_value ();
+
+ if (asso_value) /* Initialize array if user requests non-zero default. */
+ for (int i = ALPHA_SIZE - 1; i >= 0; i--)
+ asso_values[i] = asso_value & option.get_asso_max () - 1;
+ }
+ max_hash_value = Key_List::max_key_length () + option.get_asso_max () *
+ option.get_max_keysig_size ();
+
+ if (option[DEBUG])
+ fprintf (stderr, "total non-linked keys = %d\nmaximum associated value is %d"
+ "\nmaximum size of generated hash table is %d\n",
+ non_linked_length, asso_value_max, max_hash_value);
+}
+
+/* Merge two disjoint hash key multisets to form the ordered disjoint union of the sets.
+ (In a multiset, an element can occur multiple times).
+ Precondition: both set_1 and set_2 must be ordered. Returns the length
+ of the combined set. */
+
+inline int
+Gen_Perf::compute_disjoint_union (const char *set_1, const char *set_2, char *set_3)
+{
+ T (Trace t ("Gen_Perf::compute_disjoint_union");)
+ char *base = set_3;
+
+ while (*set_1 && *set_2)
+ if (*set_1 == *set_2)
+ set_1++, set_2++;
+ else
+ {
+ *set_3 = *set_1 < *set_2 ? *set_1++ : *set_2++;
+ if (set_3 == base || *set_3 != *(set_3-1)) set_3++;
+ }
+
+ while (*set_1)
+ {
+ *set_3 = *set_1++;
+ if (set_3 == base || *set_3 != *(set_3-1)) set_3++;
+ }
+
+ while (*set_2)
+ {
+ *set_3 = *set_2++;
+ if (set_3 == base || *set_3 != *(set_3-1)) set_3++;
+ }
+ *set_3 = '\0';
+ return set_3 - base;
+}
+
+/* Sort the UNION_SET in increasing frequency of occurrence.
+ This speeds up later processing since we may assume the resulting
+ set (Set_3, in this case), is ordered. Uses insertion sort, since
+ the UNION_SET is typically short. */
+
+inline void
+Gen_Perf::sort_set (char *union_set, int len)
+{
+ T (Trace t ("Gen_Perf::sort_set");)
+ int i, j;
+
+ for (i = 0, j = len - 1; i < j; i++)
+ {
+ int curr;
+ char tmp;
+
+ for (curr = i + 1, tmp = union_set[curr];
+ curr > 0 && occurrences[(unsigned char)tmp] < occurrences[(unsigned char)(union_set[curr-1])];
+ curr--)
+ union_set[curr] = union_set[curr - 1];
+
+ union_set[curr] = tmp;
+ }
+}
+
+/* Generate a key set's hash value. */
+
+inline int
+Gen_Perf::hash (List_Node *key_node)
+{
+ T (Trace t ("Gen_Perf::hash");)
+ int sum = option[NOLENGTH] ? 0 : key_node->length;
+
+ for (const char *ptr = key_node->char_set; *ptr; ptr++)
+ sum += asso_values[(unsigned char)(*ptr)];
+
+ return key_node->hash_value = sum;
+}
+
+/* Find out how character value change affects successfully hashed items.
+ Returns FALSE if no other hash values are affected, else returns TRUE.
+ Note that because Option.Get_Asso_Max is a power of two we can guarantee
+ that all legal Asso_Values are visited without repetition since
+ Option.Get_Jump was forced to be an odd value! */
+
+inline int
+Gen_Perf::affects_prev (char c, List_Node *curr)
+{
+ T (Trace t ("Gen_Perf::affects_prev");)
+ int original_char = asso_values[(unsigned char)c];
+ int total_iterations = !option[FAST]
+ ? option.get_asso_max () : option.get_iterations () ? option.get_iterations () : keyword_list_length ();
+
+ /* Try all legal associated values. */
+
+ for (int i = total_iterations - 1; i >= 0; i--)
+ {
+ int collisions = 0;
+
+ asso_values[(unsigned char)c] =
+ (asso_values[(unsigned char)c] + (option.get_jump () ? option.get_jump () : rand ()))
+ & (option.get_asso_max () - 1);
+
+ /* Iteration Number array is a win, O(1) intialization time! */
+ reset ();
+
+ /* See how this asso_value change affects previous keywords. If
+ it does better than before we'll take it! */
+
+ for (List_Node *ptr = head;
+ !Bool_Array::find (hash (ptr)) || ++collisions < fewest_collisions;
+ ptr = ptr->next)
+ if (ptr == curr)
+ {
+ fewest_collisions = collisions;
+ if (option[DEBUG])
+ fprintf (stderr, "- resolved after %d iterations", total_iterations - i);
+ return 0;
+ }
+ }
+
+ /* Restore original values, no more tries. */
+ asso_values[(unsigned char)c] = original_char;
+ /* If we're this far it's time to try the next character.... */
+ return 1;
+}
+
+/* Change a character value, try least-used characters first. */
+
+void
+Gen_Perf::change (List_Node *prior, List_Node *curr)
+{
+ T (Trace t ("Gen_Perf::change");)
+ static char *union_set;
+
+ if (!union_set)
+ union_set = new char [2 * option.get_max_keysig_size () + 1];
+
+ if (option[DEBUG])
+ {
+ fprintf (stderr, "collision on keyword #%d, prior = \"%s\", curr = \"%s\" hash = %d\n",
+ num_done, prior->key, curr->key, curr->hash_value);
+ fflush (stderr);
+ }
+ sort_set (union_set, compute_disjoint_union (prior->char_set, curr->char_set, union_set));
+
+ /* Try changing some values, if change doesn't alter other values continue normal action. */
+ fewest_collisions++;
+
+ for (char *temp = union_set; *temp; temp++)
+ if (!affects_prev (*temp, curr))
+ {
+ if (option[DEBUG])
+ {
+ fprintf (stderr, " by changing asso_value['%c'] (char #%d) to %d\n",
+ *temp, temp - union_set + 1, asso_values[(unsigned char)(*temp)]);
+ fflush (stderr);
+ }
+ return; /* Good, doesn't affect previous hash values, we'll take it. */
+ }
+
+ for (List_Node *ptr = head; ptr != curr; ptr = ptr->next)
+ hash (ptr);
+
+ hash (curr);
+
+ if (option[DEBUG])
+ {
+ fprintf (stderr, "** collision not resolved after %d iterations, %d duplicates remain, continuing...\n",
+ !option[FAST] ? option.get_asso_max () : option.get_iterations () ? option.get_iterations () : keyword_list_length (),
+ fewest_collisions + total_duplicates);
+ fflush (stderr);
+ }
+}
+
+/* Does the hard stuff....
+ Initializes the Iteration Number array, and attempts to find a perfect
+ function that will hash all the key words without getting any
+ duplications. This is made much easier since we aren't attempting
+ to generate *minimum* functions, only perfect ones.
+ If we can't generate a perfect function in one pass *and* the user
+ hasn't enabled the DUP option, we'll inform the user to try the
+ randomization option, use -D, or choose alternative key positions.
+ The alternatives (e.g., back-tracking) are too time-consuming, i.e,
+ exponential in the number of keys. */
+
+int
+Gen_Perf::operator() (void)
+{
+ T (Trace t ("Gen_Perf::operator()");)
+#if LARGE_STACK_ARRAYS
+ STORAGE_TYPE buffer[max_hash_value + 1];
+#else
+ // Note: we don't use new, because that invokes a custom operator new.
+ STORAGE_TYPE *buffer
+ = (STORAGE_TYPE*) malloc (sizeof(STORAGE_TYPE) * (max_hash_value + 1));
+ if (buffer == NULL)
+ abort ();
+#endif
+
+ Bool_Array::init (buffer, max_hash_value + 1);
+
+ List_Node *curr;
+ for (curr = head; curr; curr = curr->next)
+ {
+ hash (curr);
+
+ for (List_Node *ptr = head; ptr != curr; ptr = ptr->next)
+ if (ptr->hash_value == curr->hash_value)
+ {
+ change (ptr, curr);
+ break;
+ }
+ num_done++;
+ }
+
+ /* Make one final check, just to make sure nothing weird happened.... */
+
+ Bool_Array::reset ();
+
+ for (curr = head; curr; curr = curr->next)
+ if (Bool_Array::find (hash (curr)))
+ if (option[DUP]) /* Keep track of this number... */
+ total_duplicates++;
+ else /* Yow, big problems. we're outta here! */
+ {
+ fprintf (stderr, "\nInternal error, duplicate value %d:\n"
+ "try options -D or -r, or use new key positions.\n\n", hash (curr));
+#if !LARGE_STACK_ARRAYS
+ free ((char *) buffer);
+#endif
+ return 1;
+ }
+
+ /* Sorts the key word list by hash value, and then outputs the list.
+ The generated hash table code is only output if the early stage of
+ processing turned out O.K. */
+
+ sort ();
+ output ();
+#if !LARGE_STACK_ARRAYS
+ free ((char *) buffer);
+#endif
+ return 0;
+}
+
+/* Prints out some diagnostics upon completion. */
+
+Gen_Perf::~Gen_Perf (void)
+{
+ T (Trace t ("Gen_Perf::~Gen_Perf");)
+ if (option[DEBUG])
+ {
+ fprintf (stderr, "\ndumping occurrence and associated values tables\n");
+
+ for (int i = 0; i < ALPHA_SIZE; i++)
+ if (occurrences[i])
+ fprintf (stderr, "asso_values[%c] = %6d, occurrences[%c] = %6d\n",
+ i, asso_values[i], i, occurrences[i]);
+
+ fprintf (stderr, "end table dumping\n");
+
+ }
+}
+
diff --git a/contrib/gperf/src/gen-perf.h b/contrib/gperf/src/gen-perf.h
new file mode 100644
index 0000000..09b8727
--- /dev/null
+++ b/contrib/gperf/src/gen-perf.h
@@ -0,0 +1,50 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Provides high-level routines to manipulate the keyword list
+ structures the code generation output.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#ifndef gen_perf_h
+#define gen_perf_h 1
+
+#include "key-list.h"
+#include "bool-array.h"
+
+class Gen_Perf : private Key_List, private Bool_Array
+{
+private:
+ int max_hash_value; /* Maximum possible hash value. */
+ int fewest_collisions; /* Records fewest # of collisions for asso value. */
+ int num_done; /* Number of keywords processed without a collision. */
+
+ void change (List_Node *prior, List_Node *curr);
+ int affects_prev (char c, List_Node *curr);
+ static int hash (List_Node *key_node);
+ static int compute_disjoint_union (const char *set_1, const char *set_2, char *set_3);
+ static void sort_set (char *union_set, int len);
+
+public:
+ Gen_Perf (void);
+ ~Gen_Perf (void);
+ int operator () (void);
+};
+
+#endif
diff --git a/contrib/gperf/src/hash-table.cc b/contrib/gperf/src/hash-table.cc
new file mode 100644
index 0000000..db8d6dd
--- /dev/null
+++ b/contrib/gperf/src/hash-table.cc
@@ -0,0 +1,91 @@
+/* Hash table for checking keyword links. Implemented using double hashing.
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "hash-table.h"
+
+#include <stdio.h>
+#include <string.h> /* declares memset(), strcmp() */
+#include <hash.h>
+#include "options.h"
+#include "trace.h"
+
+#define NIL(TYPE) (TYPE *)0
+
+/* The size of the hash table is always the smallest power of 2 >= the size
+ indicated by the user. This allows several optimizations, including
+ the use of double hashing and elimination of the mod instruction.
+ Note that the size had better be larger than the number of items
+ in the hash table, else there's trouble!!! Note that the memory
+ for the hash table is allocated *outside* the intialization routine.
+ This compromises information hiding somewhat, but greatly reduces
+ memory fragmentation, since we can now use alloca! */
+
+Hash_Table::Hash_Table (List_Node **table_ptr, int s):
+ table (table_ptr), size (s), collisions (0)
+{
+ T (Trace t ("Hash_Table::Hash_Table");)
+ memset ((char *) table, 0, size * sizeof (*table));
+}
+
+Hash_Table::~Hash_Table (void)
+{
+ T (Trace t ("Hash_Table::~Hash_Table");)
+ if (option[DEBUG])
+ {
+ int field_width = option.get_max_keysig_size ();
+
+ fprintf (stderr,
+ "\ndumping the hash table\n"
+ "total available table slots = %d, total bytes = %d, total collisions = %d\n"
+ "location, %*s, keyword\n",
+ size, size * (int) sizeof (*table), collisions,
+ field_width, "keysig");
+
+ for (int i = size - 1; i >= 0; i--)
+ if (table[i])
+ fprintf (stderr, "%8d, %*s, %s\n",
+ i, field_width, table[i]->char_set, table[i]->key);
+
+ fprintf (stderr, "\nend dumping hash table\n\n");
+ }
+}
+
+/* If the ITEM is already in the hash table return the item found
+ in the table. Otherwise inserts the ITEM, and returns FALSE.
+ Uses double hashing. */
+
+List_Node *
+Hash_Table::operator() (List_Node *item, int ignore_length)
+{
+ T (Trace t ("Hash_Table::operator()");)
+ unsigned hash_val = hashpjw (item->char_set);
+ int probe = hash_val & size - 1;
+ int increment = (hash_val ^ item->length | 1) & size - 1;
+
+ while (table[probe]
+ && (strcmp (table[probe]->char_set, item->char_set)
+ || (!ignore_length && table[probe]->length != item->length)))
+ {
+ collisions++;
+ probe = probe + increment & size - 1;
+ }
+
+ return table[probe] ? table[probe] : (table[probe] = item, NIL (List_Node));
+}
diff --git a/contrib/gperf/src/hash-table.h b/contrib/gperf/src/hash-table.h
new file mode 100644
index 0000000..7d23999
--- /dev/null
+++ b/contrib/gperf/src/hash-table.h
@@ -0,0 +1,42 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Hash table used to check for duplicate keyword entries.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#ifndef hash_table_h
+#define hash_table_h 1
+
+#include "list-node.h"
+
+class Hash_Table
+{
+private:
+ List_Node **table; /* Vector of pointers to linked lists of List_Node's. */
+ int size; /* Size of the vector. */
+ int collisions; /* Find out how well our double hashing is working! */
+
+public:
+ Hash_Table (List_Node **t, int s);
+ ~Hash_Table (void);
+ List_Node *operator () (List_Node *item, int ignore_length);
+};
+
+#endif
diff --git a/contrib/gperf/src/iterator.cc b/contrib/gperf/src/iterator.cc
new file mode 100644
index 0000000..dd9d27e
--- /dev/null
+++ b/contrib/gperf/src/iterator.cc
@@ -0,0 +1,88 @@
+/* Provides an Iterator for keyword characters.
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "iterator.h"
+
+#include <stream.h>
+#include <ctype.h>
+#include "trace.h"
+
+/* Constructor for Iterator. */
+
+Iterator::Iterator (const char *s, int lo, int hi, int word_end, int bad_val, int key_end)
+{
+ T (Trace t ("Iterator::Iterator");)
+ end = key_end;
+ error_value = bad_val;
+ end_word = word_end;
+ str = s;
+ hi_bound = hi;
+ lo_bound = lo;
+}
+
+/* Provide an Iterator, returning the ``next'' value from
+ the list of valid values given in the constructor. */
+
+int
+Iterator::operator() (void)
+{
+ T (Trace t ("Iterator::operator()");)
+/* Variables to record the Iterator's status when handling ranges, e.g., 3-12. */
+
+ static int size;
+ static int curr_value;
+ static int upper_bound;
+
+ if (size)
+ {
+ if (++curr_value >= upper_bound)
+ size = 0;
+ return curr_value;
+ }
+ else
+ {
+ while (*str)
+ switch (*str)
+ {
+ default: return error_value;
+ case ',': str++; break;
+ case '$': str++; return end_word;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ for (curr_value = 0; isdigit ((unsigned char)(*str)); str++)
+ curr_value = curr_value * 10 + (*str - '0');
+
+ if (*str == '-')
+ {
+
+ for (size = 1, upper_bound = 0;
+ isdigit ((unsigned char)(*++str));
+ upper_bound = upper_bound * 10 + (*str - '0'));
+
+ if (upper_bound <= curr_value || upper_bound > hi_bound)
+ return error_value;
+ }
+ return curr_value >= lo_bound && curr_value <= hi_bound
+ ? curr_value : error_value;
+ }
+
+ return end;
+ }
+}
diff --git a/contrib/gperf/src/iterator.h b/contrib/gperf/src/iterator.h
index 06dcffd..d5138ab 100644
--- a/contrib/gperf/src/iterator.h
+++ b/contrib/gperf/src/iterator.h
@@ -1,6 +1,8 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
/* Provides an Iterator for keyword characters.
- Copyright (C) 1989 Free Software Foundation, Inc.
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
written by Douglas C. Schmidt (schmidt@ics.uci.edu)
This file is part of GNU GPERF.
@@ -16,8 +18,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU GPERF; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Provides an Iterator that expands and decodes a control string containing digits
and ranges, returning an integer every time the generator function is called.
@@ -28,20 +30,22 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
No errors are handled in these routines, they are passed back to the
calling routines via a user-supplied Error_Value */
-#ifndef _iterator_h
-#define _iterator_h
-#include "prototype.h"
+#ifndef iterator_h
+#define iterator_h 1
-typedef struct iterator
+class Iterator
{
- char *str; /* A pointer to the string provided by the user. */
+private:
+ const char *str; /* A pointer to the string provided by the user. */
int end; /* Value returned after last key is processed. */
int end_word; /* A value marking the abstract ``end of word'' ( usually '$'). */
int error_value; /* Error value returned when input is syntactically erroneous. */
int hi_bound; /* Greatest possible value, inclusive. */
int lo_bound; /* Smallest possible value, inclusive. */
-} ITERATOR;
-extern void iterator_init P ((char *s, int lo, int hi, int word_end, int bad_val, int key_end));
-extern int next P ((void));
-#endif /* _iterator_h */
+public:
+ Iterator (const char *s, int lo, int hi, int word_end, int bad_val, int key_end);
+ int operator () (void);
+};
+
+#endif
diff --git a/contrib/gperf/src/key-list.cc b/contrib/gperf/src/key-list.cc
new file mode 100644
index 0000000..38341f3
--- /dev/null
+++ b/contrib/gperf/src/key-list.cc
@@ -0,0 +1,1957 @@
+/* Routines for building, ordering, and printing the keyword list.
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include <stdio.h>
+#include <string.h> /* declares strncpy(), strchr() */
+#include <stdlib.h> /* declares malloc(), free(), abs(), exit(), abort() */
+#include <assert.h> /* defines assert() */
+#include <limits.h> /* defines SCHAR_MAX etc. */
+#include "options.h"
+#include "read-line.h"
+#include "hash-table.h"
+#include "key-list.h"
+#include "trace.h"
+#include "version.h"
+
+/* Make the hash table 8 times larger than the number of keyword entries. */
+static const int TABLE_MULTIPLE = 10;
+
+/* Efficiently returns the least power of two greater than or equal to X! */
+#define POW(X) ((!X)?1:(X-=1,X|=X>>1,X|=X>>2,X|=X>>4,X|=X>>8,X|=X>>16,(++X)))
+
+int Key_List::determined[MAX_ALPHA_SIZE];
+
+/* Destructor dumps diagnostics during debugging. */
+
+Key_List::~Key_List (void)
+{
+ T (Trace t ("Key_List::~Key_List");)
+ if (option[DEBUG])
+ {
+ fprintf (stderr, "\nDumping key list information:\ntotal non-static linked keywords = %d"
+ "\ntotal keywords = %d\ntotal duplicates = %d\nmaximum key length = %d\n",
+ list_len, total_keys, total_duplicates, max_key_len);
+ dump ();
+ fprintf (stderr, "End dumping list.\n\n");
+ }
+}
+
+/* Gathers the input stream into a buffer until one of two things occur:
+
+ 1. We read a '%' followed by a '%'
+ 2. We read a '%' followed by a '}'
+
+ The first symbolizes the beginning of the keyword list proper,
+ The second symbolizes the end of the C source code to be generated
+ verbatim in the output file.
+
+ I assume that the keys are separated from the optional preceding struct
+ declaration by a consecutive % followed by either % or } starting in
+ the first column. The code below uses an expandible buffer to scan off
+ and return a pointer to all the code (if any) appearing before the delimiter. */
+
+const char *
+Key_List::get_special_input (char delimiter)
+{
+ T (Trace t ("Key_List::get_special_input");)
+ int size = 80;
+ char *buf = new char[size];
+ int c, i;
+
+ for (i = 0; (c = getchar ()) != EOF; i++)
+ {
+ if (c == '%')
+ {
+ if ((c = getchar ()) == delimiter)
+ {
+
+ while ((c = getchar ()) != '\n')
+ ; /* discard newline */
+
+ if (i == 0)
+ return "";
+ else
+ {
+ buf[delimiter == '%' && buf[i - 2] == ';' ? i - 2 : i - 1] = '\0';
+ return buf;
+ }
+ }
+ else
+ buf[i++] = '%';
+ }
+ else if (i >= size) /* Yikes, time to grow the buffer! */
+ {
+ char *temp = new char[size *= 2];
+ int j;
+
+ for (j = 0; j < i; j++)
+ temp[j] = buf[j];
+
+ buf = temp;
+ }
+ buf[i] = c;
+ }
+
+ return 0; /* Problem here. */
+}
+
+/* Stores any C text that must be included verbatim into the
+ generated code output. */
+
+const char *
+Key_List::save_include_src (void)
+{
+ T (Trace t ("Key_List::save_include_src");)
+ int c;
+
+ if ((c = getchar ()) != '%')
+ ungetc (c, stdin);
+ else if ((c = getchar ()) != '{')
+ {
+ fprintf (stderr, "internal error, %c != '{' on line %d in file %s", c, __LINE__, __FILE__);
+ exit (1);
+ }
+ else
+ return get_special_input ('}');
+ return "";
+}
+
+/* Determines from the input file whether the user wants to build a table
+ from a user-defined struct, or whether the user is content to simply
+ use the default array of keys. */
+
+const char *
+Key_List::get_array_type (void)
+{
+ T (Trace t ("Key_List::get_array_type");)
+ return get_special_input ('%');
+}
+
+/* strcspn - find length of initial segment of S consisting entirely
+ of characters not from REJECT (borrowed from Henry Spencer's
+ ANSI string package, when GNU libc comes out I'll replace this...). */
+
+#ifndef strcspn
+inline int
+Key_List::strcspn (const char *s, const char *reject)
+{
+ T (Trace t ("Key_List::strcspn");)
+ const char *scan;
+ const char *rej_scan;
+ int count = 0;
+
+ for (scan = s; *scan; scan++)
+ {
+
+ for (rej_scan = reject; *rej_scan; rej_scan++)
+ if (*scan == *rej_scan)
+ return count;
+
+ count++;
+ }
+
+ return count;
+}
+#endif
+
+/* Sets up the Return_Type, the Struct_Tag type and the Array_Type
+ based upon various user Options. */
+
+void
+Key_List::set_output_types (void)
+{
+ T (Trace t ("Key_List::set_output_types");)
+ if (option[TYPE])
+ {
+ array_type = get_array_type ();
+ if (!array_type)
+ /* Something's wrong, but we'll catch it later on, in read_keys()... */
+ return;
+ /* Yow, we've got a user-defined type... */
+ int i = strcspn (array_type, "{\n\0");
+ /* Remove trailing whitespace. */
+ while (i > 0 && strchr (" \t", array_type[i-1]))
+ i--;
+ int struct_tag_length = i;
+
+ /* Set `struct_tag' to a naked "struct something". */
+ char *structtag = new char[struct_tag_length + 1];
+ strncpy (structtag, array_type, struct_tag_length);
+ structtag[struct_tag_length] = '\0';
+ struct_tag = structtag;
+
+ /* The return type of the lookup function is "struct something *".
+ No "const" here, because if !option[CONST], some user code might want
+ to modify the structure. */
+ char *rettype = new char[struct_tag_length + 3];
+ strncpy (rettype, array_type, struct_tag_length);
+ rettype[struct_tag_length] = ' ';
+ rettype[struct_tag_length + 1] = '*';
+ rettype[struct_tag_length + 2] = '\0';
+ return_type = rettype;
+ }
+}
+
+/* Reads in all keys from standard input and creates a linked list pointed
+ to by Head. This list is then quickly checked for ``links,'' i.e.,
+ unhashable elements possessing identical key sets and lengths. */
+
+void
+Key_List::read_keys (void)
+{
+ T (Trace t ("Key_List::read_keys");)
+ char *ptr;
+
+ include_src = save_include_src ();
+ set_output_types ();
+
+ /* Oops, problem with the input file. */
+ if (! (ptr = Read_Line::get_line ()))
+ {
+ fprintf (stderr, "No words in input file, did you forget to prepend %s or use -t accidentally?\n", "%%");
+ exit (1);
+ }
+
+ /* Read in all the keywords from the input file. */
+ else
+ {
+ const char *delimiter = option.get_delimiter ();
+ List_Node *temp, *trail = 0;
+
+ head = new List_Node (ptr, strcspn (ptr, delimiter));
+
+ for (temp = head;
+ (ptr = Read_Line::get_line ()) && strcmp (ptr, "%%");
+ temp = temp->next)
+ {
+ temp->next = new List_Node (ptr, strcspn (ptr, delimiter));
+ total_keys++;
+ }
+
+ /* See if any additional C code is included at end of this file. */
+ if (ptr)
+ additional_code = 1;
+
+ /* Hash table this number of times larger than keyword number. */
+ int table_size = (list_len = total_keys) * TABLE_MULTIPLE;
+
+#if LARGE_STACK_ARRAYS
+ /* By allocating the memory here we save on dynamic allocation overhead.
+ Table must be a power of 2 for the hash function scheme to work. */
+ List_Node *table[POW (table_size)];
+#else
+ // Note: we don't use new, because that invokes a custom operator new.
+ int malloc_size = POW (table_size) * sizeof(List_Node*);
+ if (malloc_size == 0) malloc_size = 1;
+ List_Node **table = (List_Node**)malloc(malloc_size);
+ if (table == NULL)
+ abort ();
+#endif
+
+ /* Make large hash table for efficiency. */
+ Hash_Table found_link (table, table_size);
+
+ /* Test whether there are any links and also set the maximum length of
+ an identifier in the keyword list. */
+
+ for (temp = head; temp; temp = temp->next)
+ {
+ List_Node *ptr = found_link (temp, option[NOLENGTH]);
+
+ /* Check for links. We deal with these by building an equivalence class
+ of all duplicate values (i.e., links) so that only 1 keyword is
+ representative of the entire collection. This *greatly* simplifies
+ processing during later stages of the program. */
+
+ if (ptr)
+ {
+ total_duplicates++;
+ list_len--;
+ trail->next = temp->next;
+ temp->link = ptr->link;
+ ptr->link = temp;
+
+ /* Complain if user hasn't enabled the duplicate option. */
+ if (!option[DUP] || option[DEBUG])
+ fprintf (stderr, "Key link: \"%s\" = \"%s\", with key set \"%s\".\n",
+ temp->key, ptr->key, temp->char_set);
+ }
+ else
+ trail = temp;
+
+ /* Update minimum and maximum keyword length, if needed. */
+ if (max_key_len < temp->length)
+ max_key_len = temp->length;
+ if (min_key_len > temp->length)
+ min_key_len = temp->length;
+ }
+
+#if !LARGE_STACK_ARRAYS
+ free ((char *) table);
+#endif
+
+ /* Exit program if links exists and option[DUP] not set, since we can't continue */
+ if (total_duplicates)
+ {
+ if (option[DUP])
+ fprintf (stderr, "%d input keys have identical hash values, examine output carefully...\n",
+ total_duplicates);
+ else
+ {
+ fprintf (stderr, "%d input keys have identical hash values,\ntry different key positions or use option -D.\n",
+ total_duplicates);
+ exit (1);
+ }
+ }
+ if (option[ALLCHARS])
+ option.set_keysig_size (max_key_len);
+ }
+}
+
+/* Recursively merges two sorted lists together to form one sorted list. The
+ ordering criteria is by frequency of occurrence of elements in the key set
+ or by the hash value. This is a kludge, but permits nice sharing of
+ almost identical code without incurring the overhead of a function
+ call comparison. */
+
+List_Node *
+Key_List::merge (List_Node *list1, List_Node *list2)
+{
+ T (Trace t ("Key_List::merge");)
+ List_Node *result;
+ List_Node **resultp = &result;
+ for (;;)
+ {
+ if (!list1)
+ {
+ *resultp = list2;
+ break;
+ }
+ if (!list2)
+ {
+ *resultp = list1;
+ break;
+ }
+ if (occurrence_sort && list1->occurrence < list2->occurrence
+ || hash_sort && list1->hash_value > list2->hash_value)
+ {
+ *resultp = list2;
+ resultp = &list2->next; list2 = list1; list1 = *resultp;
+ }
+ else
+ {
+ *resultp = list1;
+ resultp = &list1->next; list1 = *resultp;
+ }
+ }
+ return result;
+}
+
+/* Applies the merge sort algorithm to recursively sort the key list by
+ frequency of occurrence of elements in the key set. */
+
+List_Node *
+Key_List::merge_sort (List_Node *head)
+{
+ T (Trace t ("Key_List::merge_sort");)
+ if (!head || !head->next)
+ return head;
+ else
+ {
+ List_Node *middle = head;
+ List_Node *temp = head->next->next;
+
+ while (temp)
+ {
+ temp = temp->next;
+ middle = middle->next;
+ if (temp)
+ temp = temp->next;
+ }
+
+ temp = middle->next;
+ middle->next = 0;
+ return merge (merge_sort (head), merge_sort (temp));
+ }
+}
+
+/* Returns the frequency of occurrence of elements in the key set. */
+
+inline int
+Key_List::get_occurrence (List_Node *ptr)
+{
+ T (Trace t ("Key_List::get_occurrence");)
+ int value = 0;
+
+ for (const char *temp = ptr->char_set; *temp; temp++)
+ value += occurrences[(unsigned char)(*temp)];
+
+ return value;
+}
+
+/* Enables the index location of all key set elements that are now
+ determined. */
+
+inline void
+Key_List::set_determined (List_Node *ptr)
+{
+ T (Trace t ("Key_List::set_determined");)
+ for (const char *temp = ptr->char_set; *temp; temp++)
+ determined[(unsigned char)(*temp)] = 1;
+}
+
+/* Returns TRUE if PTR's key set is already completely determined. */
+
+inline int
+Key_List::already_determined (List_Node *ptr)
+{
+ T (Trace t ("Key_List::already_determined");)
+ int is_determined = 1;
+
+ for (const char *temp = ptr->char_set; is_determined && *temp; temp++)
+ is_determined = determined[(unsigned char)(*temp)];
+
+ return is_determined;
+}
+
+/* Reorders the table by first sorting the list so that frequently occuring
+ keys appear first, and then the list is reorded so that keys whose values
+ are already determined will be placed towards the front of the list. This
+ helps prune the search time by handling inevitable collisions early in the
+ search process. See Cichelli's paper from Jan 1980 JACM for details.... */
+
+void
+Key_List::reorder (void)
+{
+ T (Trace t ("Key_List::reorder");)
+ List_Node *ptr;
+ for (ptr = head; ptr; ptr = ptr->next)
+ ptr->occurrence = get_occurrence (ptr);
+
+ hash_sort = 0;
+ occurrence_sort = 1;
+
+ for (ptr = head = merge_sort (head); ptr->next; ptr = ptr->next)
+ {
+ set_determined (ptr);
+
+ if (already_determined (ptr->next))
+ continue;
+ else
+ {
+ List_Node *trail_ptr = ptr->next;
+ List_Node *run_ptr = trail_ptr->next;
+
+ for (; run_ptr; run_ptr = trail_ptr->next)
+ {
+
+ if (already_determined (run_ptr))
+ {
+ trail_ptr->next = run_ptr->next;
+ run_ptr->next = ptr->next;
+ ptr = ptr->next = run_ptr;
+ }
+ else
+ trail_ptr = run_ptr;
+ }
+ }
+ }
+}
+
+/* ============================ Output routines ============================ */
+
+/* The "const " qualifier. */
+static const char *const_always;
+
+/* The "const " qualifier, for read-only arrays. */
+static const char *const_readonly_array;
+
+/* The "const " qualifier, for the array type. */
+static const char *const_for_struct;
+
+/* Returns the smallest unsigned C type capable of holding integers up to N. */
+
+static const char *
+smallest_integral_type (int n)
+{
+ if (n <= UCHAR_MAX) return "unsigned char";
+ if (n <= USHRT_MAX) return "unsigned short";
+ return "unsigned int";
+}
+
+/* Returns the smallest signed C type capable of holding integers
+ from MIN to MAX. */
+
+static const char *
+smallest_integral_type (int min, int max)
+{
+ if (option[ANSIC] | option[CPLUSPLUS])
+ if (min >= SCHAR_MIN && max <= SCHAR_MAX) return "signed char";
+ if (min >= SHRT_MIN && max <= SHRT_MAX) return "short";
+ return "int";
+}
+
+/* A cast from `char' to a valid array index. */
+static const char *char_to_index;
+
+/* ------------------------------------------------------------------------- */
+
+/* Computes the maximum and minimum hash values. Since the
+ list is already sorted by hash value all we need to do is
+ find the final item! */
+
+void
+Key_List::compute_min_max (void)
+{
+ T (Trace t ("Key_List::compute_min_max");)
+ List_Node *temp;
+ for (temp = head; temp->next; temp = temp->next)
+ ;
+
+ min_hash_value = head->hash_value;
+ max_hash_value = temp->hash_value;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Returns the number of different hash values. */
+
+int
+Key_List::num_hash_values (void)
+{
+ T (Trace t ("Key_List::num_hash_values");)
+ int count = 1;
+ List_Node *temp;
+ int value;
+
+ for (temp = head, value = temp->hash_value; temp->next; )
+ {
+ temp = temp->next;
+ if (value != temp->hash_value)
+ {
+ value = temp->hash_value;
+ count++;
+ }
+ }
+ return count;
+}
+
+/* -------------------- Output_Constants and subclasses -------------------- */
+
+/* This class outputs an enumeration defining some constants. */
+
+struct Output_Constants
+{
+ virtual void output_start () = 0;
+ virtual void output_item (const char *name, int value) = 0;
+ virtual void output_end () = 0;
+ Output_Constants () {}
+ virtual ~Output_Constants () {}
+};
+
+/* This class outputs an enumeration in #define syntax. */
+
+struct Output_Defines : public Output_Constants
+{
+ virtual void output_start ();
+ virtual void output_item (const char *name, int value);
+ virtual void output_end ();
+ Output_Defines () {}
+ virtual ~Output_Defines () {}
+};
+
+void Output_Defines::output_start ()
+{
+ T (Trace t ("Output_Defines::output_start");)
+ printf ("\n");
+}
+
+void Output_Defines::output_item (const char *name, int value)
+{
+ T (Trace t ("Output_Defines::output_item");)
+ printf ("#define %s %d\n", name, value);
+}
+
+void Output_Defines::output_end ()
+{
+ T (Trace t ("Output_Defines::output_end");)
+}
+
+/* This class outputs an enumeration using `enum'. */
+
+struct Output_Enum : public Output_Constants
+{
+ virtual void output_start ();
+ virtual void output_item (const char *name, int value);
+ virtual void output_end ();
+ Output_Enum (const char *indent) : indentation (indent) {}
+ virtual ~Output_Enum () {}
+private:
+ const char *indentation;
+ int pending_comma;
+};
+
+void Output_Enum::output_start ()
+{
+ T (Trace t ("Output_Enum::output_start");)
+ printf ("%senum\n"
+ "%s {\n",
+ indentation, indentation);
+ pending_comma = 0;
+}
+
+void Output_Enum::output_item (const char *name, int value)
+{
+ T (Trace t ("Output_Enum::output_item");)
+ if (pending_comma)
+ printf (",\n");
+ printf ("%s %s = %d", indentation, name, value);
+ pending_comma = 1;
+}
+
+void Output_Enum::output_end ()
+{
+ T (Trace t ("Output_Enum::output_end");)
+ if (pending_comma)
+ printf ("\n");
+ printf ("%s };\n\n", indentation);
+}
+
+/* Outputs the maximum and minimum hash values etc. */
+
+void
+Key_List::output_constants (struct Output_Constants& style)
+{
+ T (Trace t ("Key_List::output_constants");)
+
+ style.output_start ();
+ style.output_item ("TOTAL_KEYWORDS", total_keys);
+ style.output_item ("MIN_WORD_LENGTH", min_key_len);
+ style.output_item ("MAX_WORD_LENGTH", max_key_len);
+ style.output_item ("MIN_HASH_VALUE", min_hash_value);
+ style.output_item ("MAX_HASH_VALUE", max_hash_value);
+ style.output_end ();
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Outputs a keyword, as a string: enclosed in double quotes, escaping
+ backslashes and double quote characters. */
+
+static void
+output_string (const char *key)
+{
+ T (Trace t ("output_string");)
+ char c;
+
+ putchar ('"');
+ while (c = *key++, c != '\0')
+ {
+ if (c == '"' || c == '\\')
+ putchar ('\\');
+ putchar (c);
+ }
+ putchar ('"');
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Outputs a type and a const specifier.
+ The output is terminated with a space. */
+
+static void
+output_const_type (const char *const_string, const char *type_string)
+{
+ if (type_string[strlen(type_string)-1] == '*')
+ printf ("%s %s", type_string, const_string);
+ else
+ printf ("%s%s ", const_string, type_string);
+}
+
+/* ----------------------- Output_Expr and subclasses ----------------------- */
+
+/* This class outputs a general expression. */
+
+struct Output_Expr
+{
+ virtual void output_expr () const = 0;
+ Output_Expr () {}
+ virtual ~Output_Expr () {}
+};
+
+/* This class outputs an expression formed by a single string. */
+
+struct Output_Expr1 : public Output_Expr
+{
+ virtual void output_expr () const;
+ Output_Expr1 (const char *piece1) : p1 (piece1) {}
+ virtual ~Output_Expr1 () {}
+private:
+ const char *p1;
+};
+
+void Output_Expr1::output_expr () const
+{
+ T (Trace t ("Output_Expr1::output_expr");)
+ printf ("%s", p1);
+}
+
+#if 0 /* unused */
+
+/* This class outputs an expression formed by the concatenation of two
+ strings. */
+
+struct Output_Expr2 : public Output_Expr
+{
+ virtual void output_expr () const;
+ Output_Expr2 (const char *piece1, const char *piece2)
+ : p1 (piece1), p2 (piece2) {}
+ virtual ~Output_Expr2 () {}
+private:
+ const char *p1;
+ const char *p2;
+};
+
+void Output_Expr2::output_expr () const
+{
+ T (Trace t ("Output_Expr2::output_expr");)
+ printf ("%s%s", p1, p2);
+}
+
+#endif
+
+/* --------------------- Output_Compare and subclasses --------------------- */
+
+/* This class outputs a comparison expression. */
+
+struct Output_Compare
+{
+ virtual void output_comparison (const Output_Expr& expr1,
+ const Output_Expr& expr2) const = 0;
+ Output_Compare () {}
+ virtual ~Output_Compare () {}
+};
+
+/* This class outputs a comparison using strcmp. */
+
+struct Output_Compare_Strcmp : public Output_Compare
+{
+ virtual void output_comparison (const Output_Expr& expr1,
+ const Output_Expr& expr2) const;
+ Output_Compare_Strcmp () {}
+ virtual ~Output_Compare_Strcmp () {}
+};
+
+void Output_Compare_Strcmp::output_comparison (const Output_Expr& expr1,
+ const Output_Expr& expr2) const
+{
+ T (Trace t ("Output_Compare_Strcmp::output_comparison");)
+ printf ("*");
+ expr1.output_expr ();
+ printf (" == *");
+ expr2.output_expr ();
+ printf (" && !strcmp (");
+ expr1.output_expr ();
+ printf (" + 1, ");
+ expr2.output_expr ();
+ printf (" + 1)");
+}
+
+/* This class outputs a comparison using strncmp.
+ Note that the length of expr1 will be available through the local variable
+ `len'. */
+
+struct Output_Compare_Strncmp : public Output_Compare
+{
+ virtual void output_comparison (const Output_Expr& expr1,
+ const Output_Expr& expr2) const;
+ Output_Compare_Strncmp () {}
+ virtual ~Output_Compare_Strncmp () {}
+};
+
+void Output_Compare_Strncmp::output_comparison (const Output_Expr& expr1,
+ const Output_Expr& expr2) const
+{
+ T (Trace t ("Output_Compare_Strncmp::output_comparison");)
+ printf ("*");
+ expr1.output_expr ();
+ printf (" == *");
+ expr2.output_expr ();
+ printf (" && !strncmp (");
+ expr1.output_expr ();
+ printf (" + 1, ");
+ expr2.output_expr ();
+ printf (" + 1, len - 1)");
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Generates C code for the hash function that returns the
+ proper encoding for each key word. */
+
+void
+Key_List::output_hash_function (void)
+{
+ T (Trace t ("Key_List::output_hash_function");)
+ const int max_column = 10;
+ int field_width;
+
+ /* Calculate maximum number of digits required for MAX_HASH_VALUE. */
+ field_width = 2;
+ for (int trunc = max_hash_value; (trunc /= 10) > 0;)
+ field_width++;
+
+ /* Output the function's head. */
+ if (option[CPLUSPLUS])
+ printf ("inline ");
+ else if (option[KRC] | option[C] | option[ANSIC])
+ printf ("#ifdef __GNUC__\n"
+ "__inline\n"
+ "#endif\n");
+
+ if (option[KRC] | option[C] | option[ANSIC])
+ printf ("static ");
+ printf ("unsigned int\n");
+ if (option[CPLUSPLUS])
+ printf ("%s::", option.get_class_name ());
+ printf ("%s ", option.get_hash_name ());
+ printf (option[KRC] ?
+ "(str, len)\n"
+ " register char *str;\n"
+ " register unsigned int len;\n" :
+ option[C] ?
+ "(str, len)\n"
+ " register const char *str;\n"
+ " register unsigned int len;\n" :
+ option[ANSIC] | option[CPLUSPLUS] ?
+ "(register const char *str, register unsigned int len)\n" :
+ "");
+
+ /* Note that when the hash function is called, it has already been verified
+ that min_key_len <= len <= max_key_len. */
+
+ /* Output the function's body. */
+ printf ("{\n");
+
+ /* First the asso_values array. */
+ printf (" static %s%s asso_values[] =\n"
+ " {",
+ const_readonly_array,
+ smallest_integral_type (max_hash_value + 1));
+
+ for (int count = 0; count < ALPHA_SIZE; count++)
+ {
+ if (count > 0)
+ printf (",");
+ if (!(count % max_column))
+ printf ("\n ");
+ printf ("%*d", field_width,
+ occurrences[count] ? asso_values[count] : max_hash_value + 1);
+ }
+
+ printf ("\n"
+ " };\n");
+
+ /* Optimize special case of ``-k 1,$'' */
+ if (option[DEFAULTCHARS])
+ printf (" return %sasso_values[%sstr[len - 1]] + asso_values[%sstr[0]];\n",
+ option[NOLENGTH] ? "" : "len + ",
+ char_to_index, char_to_index);
+ else
+ {
+ int key_pos;
+
+ option.reset ();
+
+ /* Get first (also highest) key position. */
+ key_pos = option.get ();
+
+ if (!option[ALLCHARS] && (key_pos == WORD_END || key_pos <= min_key_len))
+ {
+ /* We can perform additional optimizations here:
+ Write it out as a single expression. Note that the values
+ are added as `int's even though the asso_values array may
+ contain `unsigned char's or `unsigned short's. */
+
+ printf (" return %s",
+ option[NOLENGTH] ? "" : "len + ");
+
+ for (; key_pos != WORD_END; )
+ {
+ printf ("asso_values[%sstr[%d]]", char_to_index, key_pos - 1);
+ if ((key_pos = option.get ()) != EOS)
+ printf (" + ");
+ else
+ break;
+ }
+
+ if (key_pos == WORD_END)
+ printf ("asso_values[%sstr[len - 1]]", char_to_index);
+
+ printf (";\n");
+ }
+ else
+ {
+ /* We've got to use the correct, but brute force, technique. */
+ printf (" register int hval = %s;\n\n"
+ " switch (%s)\n"
+ " {\n"
+ " default:\n",
+ option[NOLENGTH] ? "0" : "len",
+ option[NOLENGTH] ? "len" : "hval");
+
+ /* User wants *all* characters considered in hash. */
+ if (option[ALLCHARS])
+ {
+ for (int i = max_key_len; i > 0; i--)
+ printf (" case %d:\n"
+ " hval += asso_values[%sstr[%d]];\n",
+ i, char_to_index, i - 1);
+
+ printf (" break;\n"
+ " }\n"
+ " return hval;\n");
+ }
+ else /* do the hard part... */
+ {
+ while (key_pos != WORD_END && key_pos > max_key_len)
+ if ((key_pos = option.get ()) == EOS)
+ break;
+
+ if (key_pos != EOS && key_pos != WORD_END)
+ {
+ int i = key_pos;
+ do
+ {
+ for ( ; i >= key_pos; i--)
+ printf (" case %d:\n", i);
+
+ printf (" hval += asso_values[%sstr[%d]];\n",
+ char_to_index, key_pos - 1);
+
+ key_pos = option.get ();
+ }
+ while (key_pos != EOS && key_pos != WORD_END);
+
+ for ( ; i >= min_key_len; i--)
+ printf (" case %d:\n", i);
+ }
+
+ printf (" break;\n"
+ " }\n"
+ " return hval");
+ if (key_pos == WORD_END)
+ printf (" + asso_values[%sstr[len - 1]]", char_to_index);
+ printf (";\n");
+ }
+ }
+ }
+ printf ("}\n\n");
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Prints out a table of keyword lengths, for use with the
+ comparison code in generated function ``in_word_set''. */
+
+void
+Key_List::output_keylength_table (void)
+{
+ T (Trace t ("Key_List::output_keylength_table");)
+ const int columns = 14;
+ int index;
+ int column;
+ const char *indent = option[GLOBAL] ? "" : " ";
+ List_Node *temp;
+
+ printf ("%sstatic %s%s lengthtable[] =\n%s {",
+ indent, const_readonly_array,
+ smallest_integral_type (max_key_len),
+ indent);
+
+ /* Generate an array of lengths, similar to output_keyword_table. */
+
+ column = 0;
+ for (temp = head, index = 0; temp; temp = temp->next)
+ {
+ if (option[SWITCH] && !option[TYPE]
+ && !(temp->link
+ || (temp->next && temp->hash_value == temp->next->hash_value)))
+ continue;
+
+ if (index < temp->hash_value && !option[SWITCH] && !option[DUP])
+ {
+ /* Some blank entries. */
+ for ( ; index < temp->hash_value; index++)
+ {
+ if (index > 0)
+ printf (",");
+ if ((column++ % columns) == 0)
+ printf ("\n%s ", indent);
+ printf ("%3d", 0);
+ }
+ }
+
+ if (index > 0)
+ printf (",");
+ if ((column++ % columns) == 0)
+ printf("\n%s ", indent);
+ printf ("%3d", temp->length);
+
+ /* Deal with links specially. */
+ if (temp->link) // implies option[DUP]
+ for (List_Node *links = temp->link; links; links = links->link)
+ {
+ ++index;
+ printf (",");
+ if ((column++ % columns) == 0)
+ printf("\n%s ", indent);
+ printf ("%3d", links->length);
+ }
+
+ index++;
+ }
+
+ printf ("\n%s };\n", indent);
+ if (option[GLOBAL])
+ printf ("\n");
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+output_keyword_entry (List_Node *temp, const char *indent)
+{
+ printf ("%s ", indent);
+ if (option[TYPE])
+ printf ("{");
+ output_string (temp->key);
+ if (option[TYPE])
+ printf (",%s}", temp->rest);
+ if (option[DEBUG])
+ printf (" /* hash value = %d, index = %d */",
+ temp->hash_value, temp->index);
+}
+
+static void
+output_keyword_blank_entries (int count, const char *indent)
+{
+ const int columns = 9;
+ int column = 0;
+ for (int i = 0; i < count; i++)
+ {
+ if ((column % columns) == 0)
+ {
+ if (i > 0)
+ printf (",\n");
+ printf ("%s ", indent);
+ }
+ else
+ {
+ if (i > 0)
+ printf (", ");
+ }
+ if (option[TYPE])
+ printf ("{\"\"}");
+ else
+ printf ("\"\"");
+ column++;
+ }
+}
+
+/* Prints out the array containing the key words for the hash function. */
+
+void
+Key_List::output_keyword_table (void)
+{
+ T (Trace t ("Key_List::output_keyword_table");)
+ const char *indent = option[GLOBAL] ? "" : " ";
+ int index;
+ List_Node *temp;
+
+ printf ("%sstatic ",
+ indent);
+ output_const_type (const_readonly_array, struct_tag);
+ printf ("%s[] =\n"
+ "%s {\n",
+ option.get_wordlist_name (),
+ indent);
+
+ /* Generate an array of reserved words at appropriate locations. */
+
+ for (temp = head, index = 0; temp; temp = temp->next)
+ {
+ if (option[SWITCH] && !option[TYPE]
+ && !(temp->link
+ || (temp->next && temp->hash_value == temp->next->hash_value)))
+ continue;
+
+ if (index > 0)
+ printf (",\n");
+
+ if (index < temp->hash_value && !option[SWITCH] && !option[DUP])
+ {
+ /* Some blank entries. */
+ output_keyword_blank_entries (temp->hash_value - index, indent);
+ printf (",\n");
+ index = temp->hash_value;
+ }
+
+ temp->index = index;
+
+ output_keyword_entry (temp, indent);
+
+ /* Deal with links specially. */
+ if (temp->link) // implies option[DUP]
+ for (List_Node *links = temp->link; links; links = links->link)
+ {
+ links->index = ++index;
+ printf (",\n");
+ output_keyword_entry (links, indent);
+ }
+
+ index++;
+ }
+ if (index > 0)
+ printf ("\n");
+
+ printf ("%s };\n\n", indent);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Generates the large, sparse table that maps hash values into
+ the smaller, contiguous range of the keyword table. */
+
+void
+Key_List::output_lookup_array (void)
+{
+ T (Trace t ("Key_List::output_lookup_array");)
+ if (option[DUP])
+ {
+ const int DEFAULT_VALUE = -1;
+
+ /* Because of the way output_keyword_table works, every duplicate set is
+ stored contiguously in the wordlist array. */
+ struct duplicate_entry
+ {
+ int hash_value; /* Hash value for this particular duplicate set. */
+ int index; /* Index into the main keyword storage array. */
+ int count; /* Number of consecutive duplicates at this index. */
+ };
+
+#if LARGE_STACK_ARRAYS
+ duplicate_entry duplicates[total_duplicates];
+ int lookup_array[max_hash_value + 1 + 2*total_duplicates];
+#else
+ // Note: we don't use new, because that invokes a custom operator new.
+ duplicate_entry *duplicates = (duplicate_entry *)
+ malloc (total_duplicates * sizeof(duplicate_entry) + 1);
+ int *lookup_array = (int *)
+ malloc ((max_hash_value + 1 + 2*total_duplicates) * sizeof(int));
+ if (duplicates == NULL || lookup_array == NULL)
+ abort();
+#endif
+ int lookup_array_size = max_hash_value + 1;
+ duplicate_entry *dup_ptr = &duplicates[0];
+ int *lookup_ptr = &lookup_array[max_hash_value + 1 + 2*total_duplicates];
+
+ while (lookup_ptr > lookup_array)
+ *--lookup_ptr = DEFAULT_VALUE;
+
+ /* Now dup_ptr = &duplicates[0] and lookup_ptr = &lookup_array[0]. */
+
+ for (List_Node *temp = head; temp; temp = temp->next)
+ {
+ int hash_value = temp->hash_value;
+ lookup_array[hash_value] = temp->index;
+ if (option[DEBUG])
+ fprintf (stderr, "keyword = %s, index = %d\n",
+ temp->key, temp->index);
+ if (temp->link
+ || (temp->next && hash_value == temp->next->hash_value))
+ {
+ /* Start a duplicate entry. */
+ dup_ptr->hash_value = hash_value;
+ dup_ptr->index = temp->index;
+ dup_ptr->count = 1;
+
+ for (;;)
+ {
+ for (List_Node *ptr = temp->link; ptr; ptr = ptr->link)
+ {
+ dup_ptr->count++;
+ if (option[DEBUG])
+ fprintf (stderr,
+ "static linked keyword = %s, index = %d\n",
+ ptr->key, ptr->index);
+ }
+
+ if (!(temp->next && hash_value == temp->next->hash_value))
+ break;
+
+ temp = temp->next;
+
+ dup_ptr->count++;
+ if (option[DEBUG])
+ fprintf (stderr, "dynamic linked keyword = %s, index = %d\n",
+ temp->key, temp->index);
+ }
+ assert (dup_ptr->count >= 2);
+ dup_ptr++;
+ }
+ }
+
+ while (dup_ptr > duplicates)
+ {
+ dup_ptr--;
+
+ if (option[DEBUG])
+ fprintf (stderr,
+ "dup_ptr[%d]: hash_value = %d, index = %d, count = %d\n",
+ dup_ptr - duplicates,
+ dup_ptr->hash_value, dup_ptr->index, dup_ptr->count);
+
+ int i;
+ /* Start searching for available space towards the right part
+ of the lookup array. */
+ for (i = dup_ptr->hash_value; i < lookup_array_size-1; i++)
+ if (lookup_array[i] == DEFAULT_VALUE
+ && lookup_array[i + 1] == DEFAULT_VALUE)
+ goto found_i;
+ /* If we didn't find it to the right look to the left instead... */
+ for (i = dup_ptr->hash_value-1; i >= 0; i--)
+ if (lookup_array[i] == DEFAULT_VALUE
+ && lookup_array[i + 1] == DEFAULT_VALUE)
+ goto found_i;
+ /* Append to the end of lookup_array. */
+ i = lookup_array_size;
+ lookup_array_size += 2;
+ found_i:
+ /* Put in an indirection from dup_ptr->hash_value to i.
+ At i and i+1 store dup_ptr->index and dup_ptr->count. */
+ assert (lookup_array[dup_ptr->hash_value] == dup_ptr->index);
+ lookup_array[dup_ptr->hash_value] = - 1 - total_keys - i;
+ lookup_array[i] = - total_keys + dup_ptr->index;
+ lookup_array[i + 1] = - dup_ptr->count;
+ /* All these three values are <= -2, distinct from DEFAULT_VALUE. */
+ }
+
+ /* The values of the lookup array are now known. */
+
+ int min = INT_MAX;
+ int max = INT_MIN;
+ lookup_ptr = lookup_array + lookup_array_size;
+ while (lookup_ptr > lookup_array)
+ {
+ int val = *--lookup_ptr;
+ if (min > val)
+ min = val;
+ if (max < val)
+ max = val;
+ }
+
+ const char *indent = option[GLOBAL] ? "" : " ";
+ printf ("%sstatic %s%s lookup[] =\n"
+ "%s {",
+ indent, const_readonly_array, smallest_integral_type (min, max),
+ indent);
+
+ int field_width;
+ /* Calculate maximum number of digits required for MIN..MAX. */
+ {
+ field_width = 2;
+ for (int trunc = max; (trunc /= 10) > 0;)
+ field_width++;
+ }
+ if (min < 0)
+ {
+ int neg_field_width = 2;
+ for (int trunc = -min; (trunc /= 10) > 0;)
+ neg_field_width++;
+ neg_field_width++; /* account for the minus sign */
+ if (field_width < neg_field_width)
+ field_width = neg_field_width;
+ }
+
+ const int columns = 42 / field_width;
+ int column;
+
+ column = 0;
+ for (int i = 0; i < lookup_array_size; i++)
+ {
+ if (i > 0)
+ printf (",");
+ if ((column++ % columns) == 0)
+ printf("\n%s ", indent);
+ printf ("%*d", field_width, lookup_array[i]);
+ }
+ printf ("\n%s };\n\n", indent);
+
+#if !LARGE_STACK_ARRAYS
+ free ((char *) duplicates);
+ free ((char *) lookup_array);
+#endif
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Generate all the tables needed for the lookup function. */
+
+void
+Key_List::output_lookup_tables (void)
+{
+ T (Trace t ("Key_List::output_lookup_tables");)
+
+ if (option[SWITCH])
+ {
+ /* Use the switch in place of lookup table. */
+ if (option[LENTABLE] && (option[DUP] && total_duplicates > 0))
+ output_keylength_table ();
+ if (option[TYPE] || (option[DUP] && total_duplicates > 0))
+ output_keyword_table ();
+ }
+ else
+ {
+ /* Use the lookup table, in place of switch. */
+ if (option[LENTABLE])
+ output_keylength_table ();
+ output_keyword_table ();
+ output_lookup_array ();
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Output a single switch case (including duplicates). Advance list. */
+
+static List_Node *
+output_switch_case (List_Node *list, int indent, int *jumps_away)
+{
+ T (Trace t ("output_switch_case");)
+
+ if (option[DEBUG])
+ printf ("%*s/* hash value = %4d, keyword = \"%s\" */\n",
+ indent, "", list->hash_value, list->key);
+
+ if (option[DUP]
+ && (list->link
+ || (list->next && list->hash_value == list->next->hash_value)))
+ {
+ if (option[LENTABLE])
+ printf ("%*slengthptr = &lengthtable[%d]\n",
+ indent, "", list->index);
+ printf ("%*swordptr = &%s[%d];\n",
+ indent, "", option.get_wordlist_name (), list->index);
+
+ int count = 0;
+ for (List_Node *temp = list; ; temp = temp->next)
+ {
+ for (List_Node *links = temp; links; links = links->link)
+ count++;
+ if (!(temp->next && temp->hash_value == temp->next->hash_value))
+ break;
+ }
+
+ printf ("%*swordendptr = wordptr + %d;\n"
+ "%*sgoto multicompare;\n",
+ indent, "", count,
+ indent, "");
+ *jumps_away = 1;
+ }
+ else
+ {
+ if (option[LENTABLE])
+ {
+ printf ("%*sif (len == %d)\n"
+ "%*s {\n",
+ indent, "", list->length,
+ indent, "");
+ indent += 4;
+ }
+ printf ("%*sresword = ",
+ indent, "");
+ if (option[TYPE])
+ printf ("&%s[%d]", option.get_wordlist_name (), list->index);
+ else
+ output_string (list->key);
+ printf (";\n");
+ printf ("%*sgoto compare;\n",
+ indent, "");
+ if (option[LENTABLE])
+ {
+ indent -= 4;
+ printf ("%*s }\n",
+ indent, "");
+ }
+ else
+ *jumps_away = 1;
+ }
+
+ while (list->next && list->hash_value == list->next->hash_value)
+ list = list->next;
+ list = list->next;
+ return list;
+}
+
+/* Output a total of size cases, grouped into num_switches switch statements,
+ where 0 < num_switches <= size. */
+
+static void
+output_switches (List_Node *list, int num_switches, int size, int min_hash_value, int max_hash_value, int indent)
+{
+ T (Trace t ("output_switches");)
+
+ if (option[DEBUG])
+ printf ("%*s/* know %d <= key <= %d, contains %d cases */\n",
+ indent, "", min_hash_value, max_hash_value, size);
+
+ if (num_switches > 1)
+ {
+ int part1 = num_switches / 2;
+ int part2 = num_switches - part1;
+ int size1 = (int)((double)size / (double)num_switches * (double)part1 + 0.5);
+ int size2 = size - size1;
+
+ List_Node *temp = list;
+ for (int count = size1; count > 0; count--)
+ {
+ while (temp->hash_value == temp->next->hash_value)
+ temp = temp->next;
+ temp = temp->next;
+ }
+
+ printf ("%*sif (key < %d)\n"
+ "%*s {\n",
+ indent, "", temp->hash_value,
+ indent, "");
+
+ output_switches (list, part1, size1, min_hash_value, temp->hash_value-1, indent+4);
+
+ printf ("%*s }\n"
+ "%*selse\n"
+ "%*s {\n",
+ indent, "", indent, "", indent, "");
+
+ output_switches (temp, part2, size2, temp->hash_value, max_hash_value, indent+4);
+
+ printf ("%*s }\n",
+ indent, "");
+ }
+ else
+ {
+ /* Output a single switch. */
+ int lowest_case_value = list->hash_value;
+ if (size == 1)
+ {
+ int jumps_away = 0;
+ assert (min_hash_value <= lowest_case_value);
+ assert (lowest_case_value <= max_hash_value);
+ if (min_hash_value == max_hash_value)
+ output_switch_case (list, indent, &jumps_away);
+ else
+ {
+ printf ("%*sif (key == %d)\n"
+ "%*s {\n",
+ indent, "", lowest_case_value,
+ indent, "");
+ output_switch_case (list, indent+4, &jumps_away);
+ printf ("%*s }\n",
+ indent, "");
+ }
+ }
+ else
+ {
+ if (lowest_case_value == 0)
+ printf ("%*sswitch (key)\n", indent, "");
+ else
+ printf ("%*sswitch (key - %d)\n", indent, "", lowest_case_value);
+ printf ("%*s {\n",
+ indent, "");
+ for (; size > 0; size--)
+ {
+ int jumps_away = 0;
+ printf ("%*s case %d:\n",
+ indent, "", list->hash_value - lowest_case_value);
+ list = output_switch_case (list, indent+6, &jumps_away);
+ if (!jumps_away)
+ printf ("%*s break;\n",
+ indent, "");
+ }
+ printf ("%*s }\n",
+ indent, "");
+ }
+ }
+}
+
+/* Generates C code to perform the keyword lookup. */
+
+void
+Key_List::output_lookup_function_body (const Output_Compare& comparison)
+{
+ T (Trace t ("Key_List::output_lookup_function_body");)
+
+ printf (" if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)\n"
+ " {\n"
+ " register int key = %s (str, len);\n\n",
+ option.get_hash_name ());
+
+ if (option[SWITCH])
+ {
+ int switch_size = num_hash_values ();
+ int num_switches = option.get_total_switches ();
+ if (num_switches > switch_size)
+ num_switches = switch_size;
+
+ printf (" if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)\n"
+ " {\n");
+ if (option[DUP])
+ {
+ if (option[LENTABLE])
+ printf (" register %s%s *lengthptr;\n",
+ const_always, smallest_integral_type (max_key_len));
+ printf (" register ");
+ output_const_type (const_readonly_array, struct_tag);
+ printf ("*wordptr;\n");
+ printf (" register ");
+ output_const_type (const_readonly_array, struct_tag);
+ printf ("*wordendptr;\n");
+ }
+ if (option[TYPE])
+ {
+ printf (" register ");
+ output_const_type (const_readonly_array, struct_tag);
+ printf ("*resword;\n\n");
+ }
+ else
+ printf (" register %sresword;\n\n",
+ struct_tag);
+
+ output_switches (head, num_switches, switch_size, min_hash_value, max_hash_value, 10);
+
+ if (option[DUP])
+ {
+ int indent = 8;
+ printf ("%*s return 0;\n"
+ "%*smulticompare:\n"
+ "%*s while (wordptr < wordendptr)\n"
+ "%*s {\n",
+ indent, "", indent, "", indent, "", indent, "");
+ if (option[LENTABLE])
+ {
+ printf ("%*s if (len == *lengthptr)\n"
+ "%*s {\n",
+ indent, "", indent, "");
+ indent += 4;
+ }
+ printf ("%*s register %schar *s = ",
+ indent, "", const_always);
+ if (option[TYPE])
+ printf ("wordptr->%s", option.get_key_name ());
+ else
+ printf ("*wordptr");
+ printf (";\n\n"
+ "%*s if (",
+ indent, "");
+ comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s"));
+ printf (")\n"
+ "%*s return %s;\n",
+ indent, "",
+ option[TYPE] ? "wordptr" : "s");
+ if (option[LENTABLE])
+ {
+ indent -= 4;
+ printf ("%*s }\n",
+ indent, "");
+ }
+ if (option[LENTABLE])
+ printf ("%*s lengthptr++;\n",
+ indent, "");
+ printf ("%*s wordptr++;\n"
+ "%*s }\n",
+ indent, "", indent, "");
+ }
+ printf (" return 0;\n"
+ " compare:\n");
+ if (option[TYPE])
+ {
+ printf (" {\n"
+ " register %schar *s = resword->%s;\n\n"
+ " if (",
+ const_always, option.get_key_name ());
+ comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s"));
+ printf (")\n"
+ " return resword;\n"
+ " }\n");
+ }
+ else
+ {
+ printf (" if (");
+ comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("resword"));
+ printf (")\n"
+ " return resword;\n");
+ }
+ printf (" }\n");
+ }
+ else
+ {
+ printf (" if (key <= MAX_HASH_VALUE && key >= 0)\n");
+
+ if (option[DUP])
+ {
+ int indent = 8;
+ printf ("%*s{\n"
+ "%*s register int index = lookup[key];\n\n"
+ "%*s if (index >= 0)\n",
+ indent, "", indent, "", indent, "");
+ if (option[LENTABLE])
+ {
+ printf ("%*s {\n"
+ "%*s if (len == lengthtable[index])\n",
+ indent, "", indent, "");
+ indent += 4;
+ }
+ printf ("%*s {\n"
+ "%*s register %schar *s = %s[index]",
+ indent, "",
+ indent, "", const_always, option.get_wordlist_name ());
+ if (option[TYPE])
+ printf (".%s", option.get_key_name ());
+ printf (";\n\n"
+ "%*s if (",
+ indent, "");
+ comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s"));
+ printf (")\n"
+ "%*s return ",
+ indent, "");
+ if (option[TYPE])
+ printf ("&%s[index]", option.get_wordlist_name ());
+ else
+ printf ("s");
+ printf (";\n"
+ "%*s }\n",
+ indent, "");
+ if (option[LENTABLE])
+ {
+ indent -= 4;
+ printf ("%*s }\n", indent, "");
+ }
+ printf ("%*s else if (index < -TOTAL_KEYWORDS)\n"
+ "%*s {\n"
+ "%*s register int offset = - 1 - TOTAL_KEYWORDS - index;\n",
+ indent, "", indent, "", indent, "");
+ if (option[LENTABLE])
+ printf ("%*s register %s%s *lengthptr = &lengthtable[TOTAL_KEYWORDS + lookup[offset]];\n",
+ indent, "", const_always, smallest_integral_type (max_key_len));
+ printf ("%*s register ",
+ indent, "");
+ output_const_type (const_readonly_array, struct_tag);
+ printf ("*wordptr = &%s[TOTAL_KEYWORDS + lookup[offset]];\n",
+ option.get_wordlist_name ());
+ printf ("%*s register ",
+ indent, "");
+ output_const_type (const_readonly_array, struct_tag);
+ printf ("*wordendptr = wordptr + -lookup[offset + 1];\n\n");
+ printf ("%*s while (wordptr < wordendptr)\n"
+ "%*s {\n",
+ indent, "", indent, "");
+ if (option[LENTABLE])
+ {
+ printf ("%*s if (len == *lengthptr)\n"
+ "%*s {\n",
+ indent, "", indent, "");
+ indent += 4;
+ }
+ printf ("%*s register %schar *s = ",
+ indent, "", const_always);
+ if (option[TYPE])
+ printf ("wordptr->%s", option.get_key_name ());
+ else
+ printf ("*wordptr");
+ printf (";\n\n"
+ "%*s if (",
+ indent, "");
+ comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s"));
+ printf (")\n"
+ "%*s return %s;\n",
+ indent, "",
+ option[TYPE] ? "wordptr" : "s");
+ if (option[LENTABLE])
+ {
+ indent -= 4;
+ printf ("%*s }\n",
+ indent, "");
+ }
+ if (option[LENTABLE])
+ printf ("%*s lengthptr++;\n",
+ indent, "");
+ printf ("%*s wordptr++;\n"
+ "%*s }\n"
+ "%*s }\n"
+ "%*s}\n",
+ indent, "", indent, "", indent, "", indent, "");
+ }
+ else
+ {
+ int indent = 8;
+ if (option[LENTABLE])
+ {
+ printf ("%*sif (len == lengthtable[key])\n",
+ indent, "");
+ indent += 2;
+ }
+
+ printf ("%*s{\n"
+ "%*s register %schar *s = %s[key]",
+ indent, "",
+ indent, "", const_always, option.get_wordlist_name ());
+
+ if (option[TYPE])
+ printf (".%s", option.get_key_name ());
+
+ printf (";\n\n"
+ "%*s if (",
+ indent, "");
+ comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s"));
+ printf (")\n"
+ "%*s return ",
+ indent, "");
+ if (option[TYPE])
+ printf ("&%s[key]", option.get_wordlist_name ());
+ else
+ printf ("s");
+ printf (";\n"
+ "%*s}\n",
+ indent, "");
+ }
+ }
+ printf (" }\n"
+ " return 0;\n");
+}
+
+/* Generates C code for the lookup function. */
+
+void
+Key_List::output_lookup_function (void)
+{
+ T (Trace t ("Key_List::output_lookup_function");)
+
+ /* Output the function's head. */
+ if (option[KRC] | option[C] | option[ANSIC])
+ printf ("#ifdef __GNUC__\n"
+ "__inline\n"
+ "#endif\n");
+
+ printf ("%s%s\n",
+ const_for_struct, return_type);
+ if (option[CPLUSPLUS])
+ printf ("%s::", option.get_class_name ());
+ printf ("%s ", option.get_function_name ());
+ printf (option[KRC] ?
+ "(str, len)\n"
+ " register char *str;\n"
+ " register unsigned int len;\n" :
+ option[C] ?
+ "(str, len)\n"
+ " register const char *str;\n"
+ " register unsigned int len;\n" :
+ option[ANSIC] | option[CPLUSPLUS] ?
+ "(register const char *str, register unsigned int len)\n" :
+ "");
+
+ /* Output the function's body. */
+ printf ("{\n");
+
+ if (option[ENUM] && !option[GLOBAL])
+ {
+ Output_Enum style (" ");
+ output_constants (style);
+ }
+
+ if (!option[GLOBAL])
+ output_lookup_tables ();
+
+ if (option[COMP])
+ output_lookup_function_body (Output_Compare_Strncmp ());
+ else
+ output_lookup_function_body (Output_Compare_Strcmp ());
+
+ printf ("}\n");
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Generates the hash function and the key word recognizer function
+ based upon the user's Options. */
+
+void
+Key_List::output (void)
+{
+ T (Trace t ("Key_List::output");)
+
+ compute_min_max ();
+
+ if (option[C] | option[ANSIC] | option[CPLUSPLUS])
+ {
+ const_always = "const ";
+ const_readonly_array = (option[CONST] ? "const " : "");
+ const_for_struct = ((option[CONST] && option[TYPE]) ? "const " : "");
+ }
+ else
+ {
+ const_always = "";
+ const_readonly_array = "";
+ const_for_struct = "";
+ }
+
+ if (!option[TYPE])
+ {
+ return_type = (const_always[0] ? "const char *" : "char *");
+ struct_tag = (const_always[0] ? "const char *" : "char *");
+ }
+
+ char_to_index = (option[SEVENBIT] ? "" : "(unsigned char)");
+
+ printf ("/* ");
+ if (option[KRC])
+ printf ("KR-C");
+ else if (option[C])
+ printf ("C");
+ else if (option[ANSIC])
+ printf ("ANSI-C");
+ else if (option[CPLUSPLUS])
+ printf ("C++");
+ printf (" code produced by gperf version %s */\n", version_string);
+ Options::print_options ();
+
+ printf ("%s\n", include_src);
+
+ if (option[TYPE] && !option[NOTYPE]) /* Output type declaration now, reference it later on.... */
+ printf ("%s;\n", array_type);
+
+ if (option[INCLUDE])
+ printf ("#include <string.h>\n"); /* Declare strlen(), strcmp(), strncmp(). */
+
+ if (!option[ENUM])
+ {
+ Output_Defines style;
+ output_constants (style);
+ }
+ else if (option[GLOBAL])
+ {
+ Output_Enum style ("");
+ output_constants (style);
+ }
+
+ printf ("/* maximum key range = %d, duplicates = %d */\n\n",
+ max_hash_value - min_hash_value + 1, total_duplicates);
+
+ if (option[CPLUSPLUS])
+ printf ("class %s\n"
+ "{\n"
+ "private:\n"
+ " static inline unsigned int %s (const char *str, unsigned int len);\n"
+ "public:\n"
+ " static %s%s%s (const char *str, unsigned int len);\n"
+ "};\n"
+ "\n",
+ option.get_class_name (), option.get_hash_name (),
+ const_for_struct, return_type, option.get_function_name ());
+
+ output_hash_function ();
+
+ if (option[GLOBAL])
+ output_lookup_tables ();
+
+ output_lookup_function ();
+
+ if (additional_code)
+ for (int c; (c = getchar ()) != EOF; putchar (c))
+ ;
+
+ fflush (stdout);
+}
+
+/* ========================= End of Output routines ========================= */
+
+/* Sorts the keys by hash value. */
+
+void
+Key_List::sort (void)
+{
+ T (Trace t ("Key_List::sort");)
+ hash_sort = 1;
+ occurrence_sort = 0;
+
+ head = merge_sort (head);
+}
+
+/* Dumps the key list to stderr stream. */
+
+void
+Key_List::dump ()
+{
+ T (Trace t ("Key_List::dump");)
+ int field_width = option.get_max_keysig_size ();
+
+ fprintf (stderr, "\nList contents are:\n(hash value, key length, index, %*s, keyword):\n",
+ field_width, "char_set");
+
+ for (List_Node *ptr = head; ptr; ptr = ptr->next)
+ fprintf (stderr, "%11d,%11d,%6d, %*s, %s\n",
+ ptr->hash_value, ptr->length, ptr->index,
+ field_width, ptr->char_set, ptr->key);
+}
+
+/* Simple-minded constructor action here... */
+
+Key_List::Key_List (void)
+{
+ T (Trace t ("Key_List::Key_List");)
+ total_keys = 1;
+ max_key_len = INT_MIN;
+ min_key_len = INT_MAX;
+ array_type = 0;
+ return_type = 0;
+ struct_tag = 0;
+ head = 0;
+ total_duplicates = 0;
+ additional_code = 0;
+}
+
+/* Returns the length of entire key list. */
+
+int
+Key_List::keyword_list_length (void)
+{
+ T (Trace t ("Key_List::keyword_list_length");)
+ return list_len;
+}
+
+/* Returns length of longest key read. */
+
+int
+Key_List::max_key_length (void)
+{
+ T (Trace t ("Key_List::max_key_length");)
+ return max_key_len;
+}
+
diff --git a/contrib/gperf/src/key-list.h b/contrib/gperf/src/key-list.h
new file mode 100644
index 0000000..98b8fa5
--- /dev/null
+++ b/contrib/gperf/src/key-list.h
@@ -0,0 +1,96 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Data and function member declarations for the keyword list class.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+/* The key word list is a useful abstraction that keeps track of
+ various pieces of information that enable that fast generation
+ of the Gen_Perf.hash function. A Key_List is a singly-linked
+ list of List_Nodes. */
+
+#ifndef key_list_h
+#define key_list_h 1
+
+#include "list-node.h"
+#include "vectors.h"
+#include "read-line.h"
+
+/* OSF/1 cxx needs these forward declarations. */
+struct Output_Constants;
+struct Output_Compare;
+
+class Key_List : private Read_Line, public Vectors
+{
+private:
+ const char *array_type; /* Pointer to the type for word list. */
+ const char *return_type; /* Pointer to return type for lookup function. */
+ const char *struct_tag; /* Shorthand for user-defined struct tag type. */
+ const char *include_src; /* C source code to be included verbatim. */
+ int max_key_len; /* Maximum length of the longest keyword. */
+ int min_key_len; /* Minimum length of the shortest keyword. */
+ int min_hash_value; /* Minimum hash value for all keywords. */
+ int max_hash_value; /* Maximum hash value for all keywords. */
+ int occurrence_sort; /* True if sorting by occurrence. */
+ int hash_sort; /* True if sorting by hash value. */
+ int additional_code; /* True if any additional C code is included. */
+ int list_len; /* Length of head's Key_List, not counting duplicates. */
+ int total_keys; /* Total number of keys, counting duplicates. */
+ static int determined[MAX_ALPHA_SIZE]; /* Used in function reorder, below. */
+ static int get_occurrence (List_Node *ptr);
+#ifndef strcspn
+ static int strcspn (const char *s, const char *reject);
+#endif
+ static int already_determined (List_Node *ptr);
+ static void set_determined (List_Node *ptr);
+ void compute_min_max (void);
+ int num_hash_values (void);
+ void output_constants (struct Output_Constants&);
+ void output_hash_function (void);
+ void output_keylength_table (void);
+ void output_keyword_table (void);
+ void output_lookup_array (void);
+ void output_lookup_tables (void);
+ void output_lookup_function_body (const struct Output_Compare&);
+ void output_lookup_function (void);
+ void set_output_types (void);
+ void dump (void);
+ const char *get_array_type (void);
+ const char *save_include_src (void);
+ const char *get_special_input (char delimiter);
+ List_Node *merge (List_Node *list1, List_Node *list2);
+ List_Node *merge_sort (List_Node *head);
+
+protected:
+ List_Node *head; /* Points to the head of the linked list. */
+ int total_duplicates; /* Total number of duplicate hash values. */
+
+public:
+ Key_List (void);
+ ~Key_List (void);
+ int keyword_list_length (void);
+ int max_key_length (void);
+ void reorder (void);
+ void sort (void);
+ void read_keys (void);
+ void output (void);
+};
+
+#endif
diff --git a/contrib/gperf/src/list-node.cc b/contrib/gperf/src/list-node.cc
new file mode 100644
index 0000000..6c78889
--- /dev/null
+++ b/contrib/gperf/src/list-node.cc
@@ -0,0 +1,101 @@
+/* Creates and initializes a new list node.
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "list-node.h"
+
+#include <stdio.h>
+#include <stdlib.h> /* declares exit() */
+#include "options.h"
+#include "trace.h"
+
+/* Sorts the key set alphabetically to speed up subsequent operations.
+ Uses insertion sort since the set is probably quite small. */
+
+inline void
+List_Node::set_sort (char *base, int len)
+{
+ T (Trace t ("List_Node::set_sort");)
+ int i, j;
+
+ for (i = 0, j = len - 1; i < j; i++)
+ {
+ char curr, tmp;
+
+ for (curr = i + 1, tmp = base[curr]; curr > 0 && tmp < base[curr-1]; curr--)
+ base[curr] = base[curr - 1];
+
+ base[curr] = tmp;
+
+ }
+}
+
+/* Initializes a List_Node. This requires obtaining memory for the CHAR_SET
+ initializing them using the information stored in the KEY_POSITIONS array in Options,
+ and checking for simple errors. It's important to note that KEY and REST are
+ both pointers to the different offsets into the same block of dynamic memory pointed
+ to by parameter K. The data member REST is used to store any additional fields
+ of the input file (it is set to the "" string if Option[TYPE] is not enabled).
+ This is useful if the user wishes to incorporate a lookup structure,
+ rather than just an array of keys. Finally, KEY_NUMBER contains a count
+ of the total number of keys seen so far. This is used to initialize
+ the INDEX field to some useful value. */
+
+List_Node::List_Node (char *k, int len): link (0), next (0),
+ key (k), rest (option[TYPE] ? k + len + 1 : ""), length (len), index (0)
+{
+ T (Trace t ("List_Node::List_Node");)
+ char *ptr = new char[(option[ALLCHARS] ? len : option.get_max_keysig_size ()) + 1];
+ char *key_set = ptr;
+ k[len] = '\0'; /* Null terminate KEY to separate it from REST. */
+
+ if (option[ALLCHARS]) /* Use all the character position in the KEY. */
+ for (; *k; k++, ptr++)
+ ++occurrences[(unsigned char)(*ptr = *k)];
+ else /* Only use those character positions specified by the user. */
+ {
+ int i;
+
+ /* Iterate thru the list of key_positions, initializing occurrences table
+ and char_set (via char * pointer ptr). */
+
+ for (option.reset (); (i = option.get ()) != EOS; )
+ {
+ if (i == WORD_END) /* Special notation for last KEY position, i.e. '$'. */
+ *ptr = key[len - 1];
+ else if (i <= len) /* Within range of KEY length, so we'll keep it. */
+ *ptr = key[i - 1];
+ else /* Out of range of KEY length, so we'll just skip it. */
+ continue;
+ ++occurrences[(unsigned char)(*ptr++)];
+ }
+
+ /* Didn't get any hits and user doesn't want to consider the
+ keylength, so there are essentially no usable hash positions! */
+ if (ptr == char_set && option[NOLENGTH])
+ {
+ fprintf (stderr, "Can't hash keyword %s with chosen key positions.\n", key);
+ exit (1);
+ }
+ }
+ *ptr = '\0'; /* Terminate this bastard.... */
+ /* Sort the KEY_SET items alphabetically. */
+ set_sort (key_set, ptr - key_set);
+ char_set = key_set;
+}
diff --git a/contrib/gperf/src/list-node.h b/contrib/gperf/src/list-node.h
new file mode 100644
index 0000000..630d91a
--- /dev/null
+++ b/contrib/gperf/src/list-node.h
@@ -0,0 +1,45 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Data and function members for defining values and operations of a list node.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#ifndef list_node_h
+#define list_node_h 1
+
+#include "vectors.h"
+
+struct List_Node : private Vectors
+{
+ List_Node *link; /* TRUE if key has an identical KEY_SET as another key. */
+ List_Node *next; /* Points to next element on the list. */
+ const char *key; /* Each keyword string stored here. */
+ const char *rest; /* Additional information for building hash function. */
+ const char *char_set; /* Set of characters to hash, specified by user. */
+ int length; /* Length of the key. */
+ int hash_value; /* Hash value for the key. */
+ int occurrence; /* A metric for frequency of key set occurrences. */
+ int index; /* Position of this node relative to other nodes. */
+
+ List_Node (char *key, int len);
+ static void set_sort (char *base, int len);
+};
+
+#endif
diff --git a/contrib/gperf/src/main.cc b/contrib/gperf/src/main.cc
new file mode 100644
index 0000000..4e08633
--- /dev/null
+++ b/contrib/gperf/src/main.cc
@@ -0,0 +1,72 @@
+/* Driver program for the Gen_Perf hash function generator
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+/* Simple driver program for the Gen_Perf.hash function generator.
+ Most of the hard work is done in class Gen_Perf and its class methods. */
+
+#include "config.h"
+#include <sys/types.h>
+#if LARGE_STACK_ARRAYS && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT)
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#endif
+
+#include <stdio.h>
+#include "options.h"
+#include "gen-perf.h"
+#include "trace.h"
+
+int
+main (int argc, char *argv[])
+{
+ T (Trace t ("main");)
+
+#if LARGE_STACK_ARRAYS && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) && defined(RLIMIT_STACK)
+ /* Get rid of any avoidable limit on stack size. */
+ {
+ struct rlimit rlim;
+ if (getrlimit (RLIMIT_STACK, &rlim) == 0)
+ if (rlim.rlim_cur < rlim.rlim_max)
+ {
+ rlim.rlim_cur = rlim.rlim_max;
+ setrlimit (RLIMIT_STACK, &rlim);
+ }
+ }
+#endif /* RLIMIT_STACK */
+
+ /* Sets the Options. */
+ option (argc, argv);
+
+ /* Initializes the key word list. */
+ Gen_Perf generate_table;
+
+ /* Generates and prints the Gen_Perf hash table. */
+ int status = generate_table ();
+
+ /* Don't use exit() here, it skips the destructors. */
+ return status;
+}
diff --git a/contrib/gperf/src/new.cc b/contrib/gperf/src/new.cc
new file mode 100644
index 0000000..8c6728e
--- /dev/null
+++ b/contrib/gperf/src/new.cc
@@ -0,0 +1,87 @@
+/* Defines a buffered memory allocation abstraction that reduces calls to
+ malloc.
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h> /* declares malloc(), exit() */
+#include "trace.h"
+
+/* Determine default alignment. If your C++ compiler does not
+ like this then try something like #define DEFAULT_ALIGNMENT 8. */
+struct fooalign {char x; double d;};
+const int ALIGNMENT = ((char *)&((struct fooalign *) 0)->d - (char *)0);
+
+/* Provide an abstraction that cuts down on the number of
+ calls to NEW by buffering the memory pool from which
+ strings are allocated. */
+
+void *
+operator new (size_t size)
+{
+ T (Trace t ("operator new");)
+ static char *buf_start = 0; /* Large array used to reduce calls to NEW. */
+ static char *buf_end = 0; /* Indicates end of BUF_START. */
+ static size_t buf_size = 4096; /* Size of buffer pointed to by BUF_START. */
+ char *temp;
+
+ /* Align this on correct boundaries, just to be safe... */
+ size = ((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT;
+
+ /* If we are about to overflow our buffer we'll just grab another
+ chunk of memory. Since we never free the original memory it
+ doesn't matter that no one points to the beginning of that
+ chunk. Note we use a heuristic that grows the buffer either by
+ size of the request or by twice the previous size, whichever is
+ larger. */
+
+ if (buf_start + size >= buf_end)
+ {
+ buf_size *= 2;
+ if (buf_size < size)
+ buf_size = size;
+ if ((buf_start = (char *)malloc (buf_size)) != (char *)0)
+ buf_end = buf_start + buf_size;
+ else
+ {
+ fprintf (stderr, "Virtual memory exhausted in `operator new'\n");
+ exit (1);
+ }
+ }
+
+ temp = buf_start;
+ buf_start += size;
+ return temp;
+}
+
+/* We need this deletion operator in order to make the linker happy.
+ Because `operator new' and `operator delete' always come together. */
+
+void
+operator delete (void *ptr)
+#ifdef HAVE_THROW_DECL
+ throw()
+#endif
+{
+ T (Trace t ("operator delete");)
+ // We cannot call free here, as it doesn't match the mallocs.
+ // free ((char *) ptr);
+ (void) ptr;
+}
diff --git a/contrib/gperf/src/options.cc b/contrib/gperf/src/options.cc
new file mode 100644
index 0000000..7be9746
--- /dev/null
+++ b/contrib/gperf/src/options.cc
@@ -0,0 +1,668 @@
+/* Handles parsing the Options provided to the user.
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include <stdio.h>
+#include <stdlib.h> /* declares atoi(), abs(), exit() */
+#include <string.h> /* declares strcmp() */
+#include "getopt.h"
+#include "options.h"
+#include "iterator.h"
+#include "trace.h"
+#include "vectors.h"
+#include "version.h"
+
+/* Global option coordinator for the entire program. */
+Options option;
+
+/* Records the program name. */
+const char *program_name;
+
+/* Size to jump on a collision. */
+static const int DEFAULT_JUMP_VALUE = 5;
+
+/* Default name for generated lookup function. */
+static const char *const DEFAULT_NAME = "in_word_set";
+
+/* Default name for the key component. */
+static const char *const DEFAULT_KEY = "name";
+
+/* Default name for the generated class. */
+static const char *const DEFAULT_CLASS_NAME = "Perfect_Hash";
+
+/* Default name for generated hash function. */
+static const char *const DEFAULT_HASH_NAME = "hash";
+
+/* Default name for generated hash table array. */
+static const char *const DEFAULT_WORDLIST_NAME = "wordlist";
+
+/* Default delimiters that separate keywords from their attributes. */
+static const char *const DEFAULT_DELIMITERS = ",\n";
+
+int Options::option_word;
+int Options::total_switches;
+int Options::total_keysig_size;
+int Options::size;
+int Options::key_pos;
+int Options::jump;
+int Options::initial_asso_value;
+int Options::argument_count;
+int Options::iterations;
+char **Options::argument_vector;
+const char *Options::function_name;
+const char *Options::key_name;
+const char *Options::class_name;
+const char *Options::hash_name;
+const char *Options::wordlist_name;
+const char *Options::delimiters;
+char Options::key_positions[MAX_KEY_POS];
+
+/* Prints program usage to given stream. */
+
+void
+Options::short_usage (FILE * strm)
+{
+ T (Trace t ("Options::short_usage");)
+ fprintf (strm, "Usage: %s [-cCdDef[num]GhH<hashname>i<init>Ijk<keys>K<keyname>lL<language>nN<function name>ors<size>S<switches>tTvW<wordlistname>Z<class name>7] [input-file]\n"
+ "Try `%s --help' for more information.\n",
+ program_name, program_name);
+}
+
+void
+Options::long_usage (FILE * strm)
+{
+ T (Trace t ("Options::long_usage");)
+ fprintf (strm,
+ "GNU `gperf' generates perfect hash functions.\n"
+ "\n"
+ "Usage: %s [OPTION]... [INPUT-FILE]\n"
+ "\n"
+ "If a long option shows an argument as mandatory, then it is mandatory\n"
+ "for the equivalent short option also.\n"
+ "\n"
+ "Input file interpretation:\n"
+ " -e, --delimiters=DELIMITER-LIST\n"
+ " Allow user to provide a string containing delimiters\n"
+ " used to separate keywords from their attributes.\n"
+ " Default is \",\\n\".\n"
+ " -t, --struct-type Allows the user to include a structured type\n"
+ " declaration for generated code. Any text before %%%%\n"
+ " is considered part of the type declaration. Key\n"
+ " words and additional fields may follow this, one\n"
+ " group of fields per line.\n"
+ "\n"
+ "Language for the output code:\n"
+ " -L, --language=LANGUAGE-NAME\n"
+ " Generates code in the specified language. Languages\n"
+ " handled are currently C++, ANSI-C, C, and KR-C. The\n"
+ " default is C.\n"
+ "\n"
+ "Details in the output code:\n"
+ " -K, --slot-name=NAME Select name of the keyword component in the keyword\n"
+ " structure.\n"
+ " -H, --hash-fn-name=NAME\n"
+ " Specify name of generated hash function. Default is\n"
+ " `hash'.\n"
+ " -N, --lookup-fn-name=NAME\n"
+ " Specify name of generated lookup function. Default\n"
+ " name is `in_word_set'.\n"
+ " -Z, --class-name=NAME Specify name of generated C++ class. Default name is\n"
+ " `Perfect_Hash'.\n"
+ " -7, --seven-bit Assume 7-bit characters.\n"
+ " -c, --compare-strncmp Generate comparison code using strncmp rather than\n"
+ " strcmp.\n"
+ " -C, --readonly-tables Make the contents of generated lookup tables\n"
+ " constant, i.e., readonly.\n"
+ " -E, --enum Define constant values using an enum local to the\n"
+ " lookup function rather than with defines.\n"
+ " -I, --includes Include the necessary system include file <string.h>\n"
+ " at the beginning of the code.\n"
+ " -G, --global Generate the static table of keywords as a static\n"
+ " global variable, rather than hiding it inside of the\n"
+ " lookup function (which is the default behavior).\n"
+ " -W, --word-array-name=NAME\n"
+ " Specify name of word list array. Default name is\n"
+ " `wordlist'.\n"
+ " -S, --switch=COUNT Causes the generated C code to use a switch\n"
+ " statement scheme, rather than an array lookup table.\n"
+ " This can lead to a reduction in both time and space\n"
+ " requirements for some keyfiles. The COUNT argument\n"
+ " determines how many switch statements are generated.\n"
+ " A value of 1 generates 1 switch containing all the\n"
+ " elements, a value of 2 generates 2 tables with 1/2\n"
+ " the elements in each table, etc. If COUNT is very\n"
+ " large, say 1000000, the generated C code does a\n"
+ " binary search.\n"
+ " -T, --omit-struct-type\n"
+ " Prevents the transfer of the type declaration to the\n"
+ " output file. Use this option if the type is already\n"
+ " defined elsewhere.\n"
+ "\n"
+ "Algorithm employed by gperf:\n"
+ " -k, --key-positions=KEYS\n"
+ " Select the key positions used in the hash function.\n"
+ " The allowable choices range between 1-%d, inclusive.\n"
+ " The positions are separated by commas, ranges may be\n"
+ " used, and key positions may occur in any order.\n"
+ " Also, the meta-character '*' causes the generated\n"
+ " hash function to consider ALL key positions, and $\n"
+ " indicates the ``final character'' of a key, e.g.,\n"
+ " $,1,2,4,6-10.\n"
+ " -l, --compare-strlen Compare key lengths before trying a string\n"
+ " comparison. This helps cut down on the number of\n"
+ " string comparisons made during the lookup.\n"
+ " -D, --duplicates Handle keywords that hash to duplicate values. This\n"
+ " is useful for certain highly redundant keyword sets.\n"
+ " -f, --fast=ITERATIONS Generate the gen-perf.hash function ``fast''. This\n"
+ " decreases gperf's running time at the cost of\n"
+ " minimizing generated table size. The numeric\n"
+ " argument represents the number of times to iterate\n"
+ " when resolving a collision. `0' means ``iterate by\n"
+ " the number of keywords''.\n"
+ " -i, --initial-asso=N Provide an initial value for the associate values\n"
+ " array. Default is 0. Setting this value larger helps\n"
+ " inflate the size of the final table.\n"
+ " -j, --jump=JUMP-VALUE Affects the ``jump value'', i.e., how far to advance\n"
+ " the associated character value upon collisions. Must\n"
+ " be an odd number, default is %d.\n"
+ " -n, --no-strlen Do not include the length of the keyword when\n"
+ " computing the hash function.\n"
+ " -o, --occurrence-sort Reorders input keys by frequency of occurrence of\n"
+ " the key sets. This should decrease the search time\n"
+ " dramatically.\n"
+ " -r, --random Utilizes randomness to initialize the associated\n"
+ " values table.\n"
+ " -s, --size-multiple=N Affects the size of the generated hash table. The\n"
+ " numeric argument N indicates ``how many times larger\n"
+ " or smaller'' the associated value range should be,\n"
+ " in relationship to the number of keys, e.g. a value\n"
+ " of 3 means ``allow the maximum associated value to\n"
+ " be about 3 times larger than the number of input\n"
+ " keys.'' Conversely, a value of -3 means ``make the\n"
+ " maximum associated value about 3 times smaller than\n"
+ " the number of input keys. A larger table should\n"
+ " decrease the time required for an unsuccessful\n"
+ " search, at the expense of extra table space. Default\n"
+ " value is 1.\n"
+ "\n"
+ "Informative output:\n"
+ " -h, --help Print this message.\n"
+ " -v, --version Print the gperf version number.\n"
+ " -d, --debug Enables the debugging option (produces verbose\n"
+ " output to the standard error).\n"
+ "\n"
+ "Report bugs to <bug-gnu-utils@gnu.org>.\n"
+ , program_name, MAX_KEY_POS - 1, DEFAULT_JUMP_VALUE);
+}
+
+/* Output command-line Options. */
+
+void
+Options::print_options (void)
+{
+ T (Trace t ("Options::print_options");)
+ int i;
+
+ printf ("/* Command-line: ");
+
+ for (i = 0; i < argument_count; i++)
+ printf ("%s ", argument_vector[i]);
+
+ printf (" */");
+}
+
+/* Sorts the key positions *IN REVERSE ORDER!!*
+ This makes further routines more efficient. Especially when generating code.
+ Uses a simple Insertion Sort since the set is probably ordered.
+ Returns 1 if there are no duplicates, 0 otherwise. */
+
+inline int
+Options::key_sort (char *base, int len)
+{
+ T (Trace t ("Options::key_sort");)
+ int i, j;
+
+ for (i = 0, j = len - 1; i < j; i++)
+ {
+ int curr, tmp;
+
+ for (curr = i + 1,tmp = base[curr]; curr > 0 && tmp >= base[curr - 1]; curr--)
+ if ((base[curr] = base[curr - 1]) == tmp) /* oh no, a duplicate!!! */
+ return 0;
+
+ base[curr] = tmp;
+ }
+
+ return 1;
+}
+
+/* Sets the default Options. */
+
+Options::Options (void)
+{
+ T (Trace t ("Options::Options");)
+ key_positions[0] = WORD_START;
+ key_positions[1] = WORD_END;
+ key_positions[2] = EOS;
+ total_keysig_size = 2;
+ delimiters = DEFAULT_DELIMITERS;
+ jump = DEFAULT_JUMP_VALUE;
+ option_word = DEFAULTCHARS | C;
+ function_name = DEFAULT_NAME;
+ key_name = DEFAULT_KEY;
+ hash_name = DEFAULT_HASH_NAME;
+ wordlist_name = DEFAULT_WORDLIST_NAME;
+ class_name = DEFAULT_CLASS_NAME;
+ total_switches = size = 1;
+ initial_asso_value = iterations = 0;
+}
+
+/* Dumps option status when debug is set. */
+
+Options::~Options (void)
+{
+ T (Trace t ("Options::~Options");)
+ if (option_word & DEBUG)
+ {
+ char *ptr;
+
+ fprintf (stderr, "\ndumping Options:"
+ "\nDEBUG is.......: %s"
+ "\nORDER is.......: %s"
+ "\nTYPE is........: %s"
+ "\nRANDOM is......: %s"
+ "\nDEFAULTCHARS is: %s"
+ "\nSWITCH is......: %s"
+ "\nNOLENGTH is....: %s"
+ "\nLENTABLE is....: %s"
+ "\nDUP is.........: %s"
+ "\nFAST is........: %s"
+ "\nCOMP is........: %s"
+ "\nNOTYPE is......: %s"
+ "\nGLOBAL is......: %s"
+ "\nCONST is.......: %s"
+ "\nKRC is.........: %s"
+ "\nC is...........: %s"
+ "\nANSIC is.......: %s"
+ "\nCPLUSPLUS is...: %s"
+ "\nENUM is........: %s"
+ "\nINCLUDE is.....: %s"
+ "\nSEVENBIT is....: %s"
+ "\niterations = %d"
+ "\nlookup function name = %s"
+ "\nhash function name = %s"
+ "\nword list name = %s"
+ "\nkey name = %s"
+ "\njump value = %d"
+ "\nmax associated value = %d"
+ "\ninitial associated value = %d"
+ "\ndelimiters = %s"
+ "\nnumber of switch statements = %d\n",
+ option_word & DEBUG ? "enabled" : "disabled",
+ option_word & ORDER ? "enabled" : "disabled",
+ option_word & TYPE ? "enabled" : "disabled",
+ option_word & RANDOM ? "enabled" : "disabled",
+ option_word & DEFAULTCHARS ? "enabled" : "disabled",
+ option_word & SWITCH ? "enabled" : "disabled",
+ option_word & NOLENGTH ? "enabled" : "disabled",
+ option_word & LENTABLE ? "enabled" : "disabled",
+ option_word & DUP ? "enabled" : "disabled",
+ option_word & FAST ? "enabled" : "disabled",
+ option_word & COMP ? "enabled" : "disabled",
+ option_word & NOTYPE ? "enabled" : "disabled",
+ option_word & GLOBAL ? "enabled" : "disabled",
+ option_word & CONST ? "enabled" : "disabled",
+ option_word & KRC ? "enabled" : "disabled",
+ option_word & C ? "enabled" : "disabled",
+ option_word & ANSIC ? "enabled" : "disabled",
+ option_word & CPLUSPLUS ? "enabled" : "disabled",
+ option_word & ENUM ? "enabled" : "disabled",
+ option_word & INCLUDE ? "enabled" : "disabled",
+ option_word & SEVENBIT ? "enabled" : "disabled",
+ iterations,
+ function_name, hash_name, wordlist_name, key_name,
+ jump, size - 1, initial_asso_value, delimiters, total_switches);
+ if (option_word & ALLCHARS)
+ fprintf (stderr, "all characters are used in the hash function\n");
+
+ fprintf (stderr, "maximum keysig size = %d\nkey positions are: \n",
+ total_keysig_size);
+
+ for (ptr = key_positions; *ptr != EOS; ptr++)
+ if (*ptr == WORD_END)
+ fprintf (stderr, "$\n");
+ else
+ fprintf (stderr, "%d\n", *ptr);
+
+ fprintf (stderr, "finished dumping Options\n");
+ }
+}
+
+
+/* Parses the command line Options and sets appropriate flags in option_word. */
+
+static const struct option long_options[] =
+{
+ { "delimiters", required_argument, 0, 'e' },
+ { "struct-type", no_argument, 0, 't' },
+ { "language", required_argument, 0, 'L' },
+ { "slot-name", required_argument, 0, 'K' },
+ { "hash-fn-name", required_argument, 0, 'H' },
+ { "lookup-fn-name", required_argument, 0, 'N' },
+ { "class-name", required_argument, 0, 'Z' },
+ { "seven-bit", no_argument, 0, '7' },
+ { "compare-strncmp", no_argument, 0, 'c' },
+ { "readonly-tables", no_argument, 0, 'C' },
+ { "enum", no_argument, 0, 'E' },
+ { "includes", no_argument, 0, 'I' },
+ { "global", no_argument, 0, 'G' },
+ { "word-array-name", required_argument, 0, 'W' },
+ { "switch", required_argument, 0, 'S' },
+ { "omit-struct-type", no_argument, 0, 'T' },
+ { "key-positions", required_argument, 0, 'k' },
+ { "compare-strlen", no_argument, 0, 'l' },
+ { "duplicates", no_argument, 0, 'D' },
+ { "fast", required_argument, 0, 'f' },
+ { "initial-asso", required_argument, 0, 'i' },
+ { "jump", required_argument, 0, 'j' },
+ { "no-strlen", no_argument, 0, 'n' },
+ { "occurrence-sort", no_argument, 0, 'o' },
+ { "random", no_argument, 0, 'r' },
+ { "size-multiple", required_argument, 0, 's' },
+ { "help", no_argument, 0, 'h' },
+ { "version", no_argument, 0, 'v' },
+ { "debug", no_argument, 0, 'd' },
+ { 0, no_argument, 0, 0 }
+};
+
+void
+Options::operator() (int argc, char *argv[])
+{
+ T (Trace t ("Options::operator()");)
+ int option_char;
+
+ program_name = argv[0];
+ argument_count = argc;
+ argument_vector = argv;
+
+ while ((option_char =
+ getopt_long (argument_count, argument_vector,
+ "adcCDe:Ef:gGhH:i:Ij:k:K:lL:nN:oprs:S:tTvW:Z:7",
+ long_options, (int *)0))
+ != -1)
+ {
+ switch (option_char)
+ {
+ case 'a': /* Generated code uses the ANSI prototype format. */
+ break; /* This is now the default. */
+ case 'c': /* Generate strncmp rather than strcmp. */
+ {
+ option_word |= COMP;
+ break;
+ }
+ case 'C': /* Make the generated tables readonly (const). */
+ {
+ option_word |= CONST;
+ break;
+ }
+ case 'd': /* Enable debugging option. */
+ {
+ option_word |= DEBUG;
+ fprintf (stderr, "Starting program %s, version %s, with debugging on.\n",
+ program_name, version_string);
+ break;
+ }
+ case 'D': /* Enable duplicate option. */
+ {
+ option_word |= DUP;
+ break;
+ }
+ case 'e': /* Allows user to provide keyword/attribute separator */
+ {
+ option.delimiters = /*getopt*/optarg;
+ break;
+ }
+ case 'E':
+ {
+ option_word |= ENUM;
+ break;
+ }
+ case 'f': /* Generate the hash table ``fast.'' */
+ {
+ option_word |= FAST;
+ if ((iterations = atoi (/*getopt*/optarg)) < 0)
+ {
+ fprintf (stderr, "iterations value must not be negative, assuming 0\n");
+ iterations = 0;
+ }
+ break;
+ }
+ case 'g': /* Use the ``inline'' keyword for generated sub-routines, ifdef __GNUC__. */
+ break; /* This is now the default. */
+ case 'G': /* Make the keyword table a global variable. */
+ {
+ option_word |= GLOBAL;
+ break;
+ }
+ case 'h': /* Displays a list of helpful Options to the user. */
+ {
+ long_usage (stdout);
+ exit (0);
+ }
+ case 'H': /* Sets the name for the hash function */
+ {
+ hash_name = /*getopt*/optarg;
+ break;
+ }
+ case 'i': /* Sets the initial value for the associated values array. */
+ {
+ if ((initial_asso_value = atoi (/*getopt*/optarg)) < 0)
+ fprintf (stderr, "Initial value %d should be non-zero, ignoring and continuing.\n", initial_asso_value);
+ if (option[RANDOM])
+ fprintf (stderr, "warning, -r option superceeds -i, ignoring -i option and continuing\n");
+ break;
+ }
+ case 'I': /* Enable #include statements. */
+ {
+ option_word |= INCLUDE;
+ break;
+ }
+ case 'j': /* Sets the jump value, must be odd for later algorithms. */
+ {
+ if ((jump = atoi (/*getopt*/optarg)) < 0)
+ {
+ fprintf (stderr, "Jump value %d must be a positive number.\n", jump);
+ short_usage (stderr);
+ exit (1);
+ }
+ else if (jump && ((jump % 2) == 0))
+ fprintf (stderr, "Jump value %d should be odd, adding 1 and continuing...\n", jump++);
+ break;
+ }
+ case 'k': /* Sets key positions used for hash function. */
+ {
+ const int BAD_VALUE = -1;
+ int value;
+ Iterator expand (/*getopt*/optarg, 1, MAX_KEY_POS - 1, WORD_END, BAD_VALUE, EOS);
+
+ if (/*getopt*/optarg [0] == '*') /* Use all the characters for hashing!!!! */
+ option_word = (option_word & ~DEFAULTCHARS) | ALLCHARS;
+ else
+ {
+ char *key_pos;
+
+ for (key_pos = key_positions; (value = expand ()) != EOS; key_pos++)
+ if (value == BAD_VALUE)
+ {
+ fprintf (stderr, "Illegal key value or range, use 1,2,3-%d,'$' or '*'.\n",
+ MAX_KEY_POS - 1);
+ short_usage (stderr);
+ exit (1);
+ }
+ else
+ *key_pos = value;;
+
+ *key_pos = EOS;
+
+ if (! (total_keysig_size = (key_pos - key_positions)))
+ {
+ fprintf (stderr, "No keys selected.\n");
+ short_usage (stderr);
+ exit (1);
+ }
+ else if (! key_sort (key_positions, total_keysig_size))
+ {
+ fprintf (stderr, "Duplicate keys selected\n");
+ short_usage (stderr);
+ exit (1);
+ }
+
+ if (total_keysig_size != 2
+ || (key_positions[0] != 1 || key_positions[1] != WORD_END))
+ option_word &= ~DEFAULTCHARS;
+ }
+ break;
+ }
+ case 'K': /* Make this the keyname for the keyword component field. */
+ {
+ key_name = /*getopt*/optarg;
+ break;
+ }
+ case 'l': /* Create length table to avoid extra string compares. */
+ {
+ option_word |= LENTABLE;
+ break;
+ }
+ case 'L': /* Deal with different generated languages. */
+ {
+ option_word &= ~(KRC | C | ANSIC | CPLUSPLUS);
+ if (!strcmp (/*getopt*/optarg, "KR-C"))
+ option_word |= KRC;
+ else if (!strcmp (/*getopt*/optarg, "C"))
+ option_word |= C;
+ else if (!strcmp (/*getopt*/optarg, "ANSI-C"))
+ option_word |= ANSIC;
+ else if (!strcmp (/*getopt*/optarg, "C++"))
+ option_word |= CPLUSPLUS;
+ else
+ {
+ fprintf (stderr, "unsupported language option %s, defaulting to C\n", /*getopt*/optarg);
+ option_word |= C;
+ }
+ break;
+ }
+ case 'n': /* Don't include the length when computing hash function. */
+ {
+ option_word |= NOLENGTH;
+ break;
+ }
+ case 'N': /* Make generated lookup function name be optarg */
+ {
+ function_name = /*getopt*/optarg;
+ break;
+ }
+ case 'o': /* Order input by frequency of key set occurrence. */
+ {
+ option_word |= ORDER;
+ break;
+ }
+ case 'p': /* Generated lookup function a pointer instead of int. */
+ break; /* This is now the default. */
+ case 'r': /* Utilize randomness to initialize the associated values table. */
+ {
+ option_word |= RANDOM;
+ if (option.initial_asso_value != 0)
+ fprintf (stderr, "warning, -r option superceeds -i, disabling -i option and continuing\n");
+ break;
+ }
+ case 's': /* Range of associated values, determines size of final table. */
+ {
+ if (abs (size = atoi (/*getopt*/optarg)) > 50)
+ fprintf (stderr, "%d is excessive, did you really mean this?! (try `%s --help' for help)\n", size, program_name);
+ break;
+ }
+ case 'S': /* Generate switch statement output, rather than lookup table. */
+ {
+ option_word |= SWITCH;
+ if ((option.total_switches = atoi (/*getopt*/optarg)) <= 0)
+ {
+ fprintf (stderr, "number of switches %s must be a positive number\n", /*getopt*/optarg);
+ short_usage (stderr);
+ exit (1);
+ }
+ break;
+ }
+ case 't': /* Enable the TYPE mode, allowing arbitrary user structures. */
+ {
+ option_word |= TYPE;
+ break;
+ }
+ case 'T': /* Don't print structure definition. */
+ {
+ option_word |= NOTYPE;
+ break;
+ }
+ case 'v': /* Print out the version and quit. */
+ fprintf (stdout, "GNU gperf %s\n", version_string);
+ exit (0);
+ case 'W': /* Sets the name for the hash table array */
+ {
+ wordlist_name = /*getopt*/optarg;
+ break;
+ }
+ case 'Z': /* Set the class name. */
+ {
+ class_name = /*getopt*/optarg;
+ break;
+ }
+ case '7': /* Assume 7-bit characters. */
+ {
+ option_word |= SEVENBIT;
+ Vectors::ALPHA_SIZE = 128;
+ break;
+ }
+ default:
+ short_usage (stderr);
+ exit (1);
+ }
+
+ }
+
+ if (argv[/*getopt*/optind] && ! freopen (argv[/*getopt*/optind], "r", stdin))
+ {
+ fprintf (stderr, "Cannot open keyword file `%s'\n", argv[/*getopt*/optind]);
+ short_usage (stderr);
+ exit (1);
+ }
+
+ if (++/*getopt*/optind < argc)
+ {
+ fprintf (stderr, "Extra trailing arguments to %s.\n", program_name);
+ short_usage (stderr);
+ exit (1);
+ }
+}
+
+#ifndef __OPTIMIZE__
+
+#define INLINE /* not inline */
+#include "options.icc"
+#undef INLINE
+
+#endif /* not defined __OPTIMIZE__ */
diff --git a/contrib/gperf/src/options.h b/contrib/gperf/src/options.h
index 1928c73..a81afe6 100644
--- a/contrib/gperf/src/options.h
+++ b/contrib/gperf/src/options.h
@@ -1,6 +1,8 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
/* Handles parsing the Options provided to the user.
- Copyright (C) 1989 Free Software Foundation, Inc.
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
written by Douglas C. Schmidt (schmidt@ics.uci.edu)
This file is part of GNU GPERF.
@@ -16,138 +18,140 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU GPERF; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
-/* This module provides a uniform interface to the various Options available
- to a user of the Perfect.hash function generator. In addition to the
- run-time Options, found in the Option_Type below, there is also the
+/* This module provides a uniform interface to the various options available
+ to a user of the gperf hash function generator. In addition to the
+ run-time options, found in the Option_Type below, there is also the
hash table Size and the Keys to be used in the hashing.
The overall design of this module was an experiment in using C++
classes as a mechanism to enhance centralization of option and
and error handling, which tend to get out of hand in a C program. */
-#ifndef _options_h
-#define _options_h
+#ifndef options_h
+#define options_h 1
#include <stdio.h>
-#include "prototype.h"
/* Enumerate the potential debugging Options. */
-enum option_type
+enum Option_Type
{
- DEBUG = 01, /* Enable debugging (prints diagnostics to Std_Err). */
+ DEBUG = 01, /* Enable debugging (prints diagnostics to stderr). */
ORDER = 02, /* Apply ordering heuristic to speed-up search time. */
- ANSI = 04, /* Generate ANSI prototypes. */
- ALLCHARS = 010, /* Use all characters in hash function. */
- GNU = 020, /* Assume GNU extensions (primarily function inline). */
- TYPE = 040, /* Handle user-defined type structured keyword input. */
- RANDOM = 0100, /* Randomly initialize the associated values table. */
- DEFAULTCHARS = 0200, /* Make default char positions be 1,$ (end of keyword). */
- SWITCH = 0400, /* Generate switch output to save space. */
- POINTER = 01000, /* Have in_word_set function return pointer, not boolean. */
- NOLENGTH = 02000, /* Don't include keyword length in hash computations. */
- LENTABLE = 04000, /* Generate a length table for string comparison. */
- DUP = 010000, /* Handle duplicate hash values for keywords. */
- FAST = 020000, /* Generate the hash function ``fast.'' */
- NOTYPE = 040000, /* Don't include user-defined type definition
- in output -- it's already defined elsewhere. */
- COMP = 0100000, /* Generate strncmp rather than strcmp. */
- GLOBAL = 0200000, /* Make the keyword table a global variable. */
- CONST = 0400000, /* Make the generated tables readonly (const). */
+ ALLCHARS = 04, /* Use all characters in hash function. */
+ TYPE = 010, /* Handle user-defined type structured keyword input. */
+ RANDOM = 020, /* Randomly initialize the associated values table. */
+ DEFAULTCHARS = 040, /* Make default char positions be 1,$ (end of keyword). */
+ SWITCH = 0100, /* Generate switch output to save space. */
+ NOLENGTH = 0200, /* Don't include keyword length in hash computations. */
+ LENTABLE = 0400, /* Generate a length table for string comparison. */
+ DUP = 01000, /* Handle duplicate hash values for keywords. */
+ FAST = 02000, /* Generate the hash function ``fast.'' */
+ NOTYPE = 04000, /* Don't include user-defined type definition in output -- it's already defined elsewhere. */
+ COMP = 010000, /* Generate strncmp rather than strcmp. */
+ GLOBAL = 020000, /* Make the keyword table a global variable. */
+ CONST = 040000, /* Make the generated tables readonly (const). */
+ KRC = 0100000, /* Generate K&R C code: no prototypes, no const. */
+ C = 0200000, /* Generate C code: no prototypes, but const (user can #define it away). */
+ ANSIC = 0400000, /* Generate ISO/ANSI C code: prototypes and const, but no class. */
+ CPLUSPLUS = 01000000, /* Generate C++ code: prototypes, const, class, inline, enum. */
+ ENUM = 02000000, /* Use enum for constants. */
+ INCLUDE = 04000000, /* Generate #include statements. */
+ SEVENBIT = 010000000 /* Assume 7-bit, not 8-bit, characters. */
};
-/* Define some useful constants. */
-
-/* Max size of each word's key set. */
-#define MAX_KEY_POS (128 - 1)
-
-/* Signals the start of a word. */
-#define WORD_START 1
-
-/* Signals the end of a word. */
-#define WORD_END 0
-
-/* Signals end of the key list. */
-#define EOS MAX_KEY_POS
-
-/* Returns TRUE if option O is enabled. */
-#define OPTION_ENABLED(OW,O) (OW.option_word & (int)O)
-
-/* Enables option O in OPTION_WORD. */
-#define SET_OPTION(OW,O) (OW.option_word |= (int)O)
-
-/* Disable option O in OPTION_WORD. */
-#define UNSET_OPTION(OW,O) (OW.option_word &= ~(int)(O))
-
-/* Returns total distinct key positions. */
-#define GET_CHARSET_SIZE(O) (O.total_charset_size)
-
-/* Set the total distinct key positions. */
-#define SET_CHARSET_SIZE(O,S) (O.total_charset_size = (S))
+/* Define some useful constants (these don't really belong here, but I'm
+ not sure where else to put them!). These should be consts, but g++
+ doesn't seem to do the right thing with them at the moment... ;-( */
-/* Initializes the key Iterator. */
-#define RESET(O) (O.key_pos = 0)
-
-/* Returns current key_position and advances index. */
-#define GET(O) (O.key_positions[O.key_pos++])
-
-/* Sets the size of the table size. */
-#define SET_ASSO_MAX(O,R) (O.size = (R))
-
-/* Returns the size of the table size. */
-#define GET_ASSO_MAX(O) (O.size)
-
-/* Returns the jump value. */
-#define GET_JUMP(O) (O.jump)
-
-/* Returns the iteration value. */
-#define GET_ITERATIONS(O) (O.iterations)
+enum
+{
+ MAX_KEY_POS = 128 - 1, /* Max size of each word's key set. */
+ WORD_START = 1, /* Signals the start of a word. */
+ WORD_END = 0, /* Signals the end of a word. */
+ EOS = MAX_KEY_POS /* Signals end of the key list. */
+};
-/* Returns the lookup function name. */
-#define GET_FUNCTION_NAME(O) (O.function_name)
+/* Class manager for gperf program Options. */
-/* Returns the keyword key name. */
-#define GET_KEY_NAME(O) (O.key_name)
+class Options
+{
+public:
+ Options (void);
+ ~Options (void);
+ int operator[] (Option_Type option);
+ void operator() (int argc, char *argv[]);
+ void operator= (enum Option_Type);
+ void operator!= (enum Option_Type);
+ static void print_options (void);
+ static void set_asso_max (int r);
+ static int get_asso_max (void);
+ static void reset (void);
+ static int get (void);
+ static int get_iterations (void);
+ static int get_max_keysig_size (void);
+ static void set_keysig_size (int);
+ static int get_jump (void);
+ static int initial_value (void);
+ static int get_total_switches (void);
+ static const char *get_function_name (void);
+ static const char *get_key_name (void);
+ static const char *get_class_name (void);
+ static const char *get_hash_name (void);
+ static const char *get_wordlist_name (void);
+ static const char *get_delimiter (void);
+
+private:
+ static int option_word; /* Holds the user-specified Options. */
+ static int total_switches; /* Number of switch statements to generate. */
+ static int total_keysig_size; /* Total number of distinct key_positions. */
+ static int size; /* Range of the hash table. */
+ static int key_pos; /* Tracks current key position for Iterator. */
+ static int jump; /* Jump length when trying alternative values. */
+ static int initial_asso_value; /* Initial value for asso_values table. */
+ static int argument_count; /* Records count of command-line arguments. */
+ static int iterations; /* Amount to iterate when a collision occurs. */
+ static char **argument_vector; /* Stores a pointer to command-line vector. */
+ static const char *function_name; /* Names used for generated lookup function. */
+ static const char *key_name; /* Name used for keyword key. */
+ static const char *class_name; /* Name used for generated C++ class. */
+ static const char *hash_name; /* Name used for generated hash function. */
+ static const char *wordlist_name; /* Name used for hash table array. */
+ static const char *delimiters; /* Separates keywords from other attributes. */
+ static char key_positions[MAX_KEY_POS]; /* Contains user-specified key choices. */
+ static int key_sort (char *base, int len); /* Sorts key positions in REVERSE order. */
+ static void short_usage (FILE * strm); /* Prints proper program usage. */
+ static void long_usage (FILE * strm); /* Prints proper program usage. */
+};
-/* Returns the hash function name. */
-#define GET_HASH_NAME(O) (O.hash_name)
+/* Global option coordinator for the entire program. */
+extern Options option;
-/* Returns the initial associated character value. */
-#define INITIAL_VALUE(O) (O.initial_asso_value)
+/* Set to 1 if your want to stack-allocate some large arrays.
+ This requires compiler support for variable-size arrays on the stack
+ (not ANSI). */
+#ifndef LARGE_STACK_ARRAYS
+#if defined(__GNUG__) && !defined(__STRICT_ANSI__)
+#define LARGE_STACK_ARRAYS 1
+#else
+#define LARGE_STACK_ARRAYS 0
+#endif
+#endif
-/* Returns the string used to delimit keywords from other attributes. */
-#define GET_DELIMITER(O) (O.delimiters)
+/* Set to 1 if the stack is large enough for holding a text line. */
+#ifndef LARGE_STACK
+#define LARGE_STACK 1
+#endif
-/* Sets the keyword/attribute delimiters with value of D. */
-#define SET_DELIMITERS(O,D) (O.delimiters = (D))
+#ifdef __OPTIMIZE__
-/* Gets the total number of switch statements to generate. */
-#define GET_TOTAL_SWITCHES(O) (O.total_switches)
+#include "trace.h"
+#define INLINE inline
+#include "options.icc"
+#undef INLINE
-/* Class manager for gperf program options. */
+#endif
-typedef struct options
-{
- int option_word; /* Holds the user-specified Options. */
- int total_charset_size; /* Total number of distinct key_positions. */
- int size; /* Range of the hash table. */
- int key_pos; /* Tracks current key position for Iterator. */
- int jump; /* Jump length when trying alternative values. */
- int initial_asso_value; /* Initial value for asso_values table. */
- int argument_count; /* Records count of command-line arguments. */
- int iterations; /* Amount to iterate when a collision occurs. */
- int total_switches; /* Number of switch statements to generate. */
- char **argument_vector; /* Stores a pointer to command-line vector. */
- char *function_name; /* Name used for generated lookup function. */
- char *key_name; /* Name used for keyword key. */
- char *hash_name; /* Name used for generated hash function. */
- char *delimiters; /* Separates keywords from other attributes. */
- char key_positions[MAX_KEY_POS]; /* Contains user-specified key choices. */
-} OPTIONS;
-
-extern void options_init P ((int argc, char *argv[]));
-extern void options_destroy P ((void));
-extern OPTIONS option;
-#endif /* _options_h */
+#endif
diff --git a/contrib/gperf/src/options.icc b/contrib/gperf/src/options.icc
new file mode 100644
index 0000000..0d9668f
--- /dev/null
+++ b/contrib/gperf/src/options.icc
@@ -0,0 +1,175 @@
+/* Inline Functions for options.{h,cc}.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+// This needs:
+//#include "trace.h"
+
+/* TRUE if option enable, else FALSE. */
+INLINE int
+Options::operator[] (Option_Type option)
+{
+ T (Trace t ("Options::operator[]");)
+ return option_word & option;
+}
+
+/* Enables option OPT. */
+INLINE void
+Options::operator = (enum Option_Type opt)
+{
+ T (Trace t ("Options::operator=");)
+ option_word |= opt;
+}
+
+/* Disables option OPT. */
+INLINE void
+Options::operator != (enum Option_Type opt)
+{
+ T (Trace t ("Options::operator!=");)
+ option_word &= ~opt;
+}
+
+/* Initializes the key Iterator. */
+INLINE void
+Options::reset (void)
+{
+ T (Trace t ("Options::reset");)
+ key_pos = 0;
+}
+
+/* Returns current key_position and advance index. */
+INLINE int
+Options::get (void)
+{
+ T (Trace t ("Options::get");)
+ return key_positions[key_pos++];
+}
+
+/* Sets the size of the table size. */
+INLINE void
+Options::set_asso_max (int r)
+{
+ T (Trace t ("Options::set_asso_max");)
+ size = r;
+}
+
+/* Returns the size of the table size. */
+INLINE int
+Options::get_asso_max (void)
+{
+ T (Trace t ("Options::get_asso_max");)
+ return size;
+}
+
+/* Returns total distinct key positions. */
+INLINE int
+Options::get_max_keysig_size (void)
+{
+ T (Trace t ("Options::get_max_keysig_size");)
+ return total_keysig_size;
+}
+
+/* Sets total distinct key positions. */
+INLINE void
+Options::set_keysig_size (int size)
+{
+ T (Trace t ("Options::set_keysig_size");)
+ total_keysig_size = size;
+}
+
+/* Returns the jump value. */
+INLINE int
+Options::get_jump (void)
+{
+ T (Trace t ("Options::get_jump");)
+ return jump;
+}
+
+/* Returns the generated function name. */
+INLINE const char *
+Options::get_function_name (void)
+{
+ T (Trace t ("Options::get_function_name");)
+ return function_name;
+}
+
+/* Returns the keyword key name. */
+INLINE const char *
+Options::get_key_name (void)
+{
+ T (Trace t ("Options::get_key_name");)
+ return key_name;
+}
+
+/* Returns the hash function name. */
+INLINE const char *
+Options::get_hash_name (void)
+{
+ T (Trace t ("Options::get_hash_name");)
+ return hash_name;
+}
+
+/* Returns the hash table array name. */
+INLINE const char *
+Options::get_wordlist_name (void)
+{
+ T (Trace t ("Options::get_wordlist_name");)
+ return wordlist_name;
+}
+
+/* Returns the generated class name. */
+INLINE const char *
+Options::get_class_name (void)
+{
+ T (Trace t ("Options::get_class_name");)
+ return class_name;
+}
+
+/* Returns the initial associated character value. */
+INLINE int
+Options::initial_value (void)
+{
+ T (Trace t ("Options::initial_value");)
+ return initial_asso_value;
+}
+
+/* Returns the iterations value. */
+INLINE int
+Options::get_iterations (void)
+{
+ T (Trace t ("Options::get_iterations");)
+ return iterations;
+}
+
+/* Returns the string used to delimit keywords from other attributes. */
+INLINE const char *
+Options::get_delimiter ()
+{
+ T (Trace t ("Options::get_delimiter");)
+ return delimiters;
+}
+
+/* Gets the total number of switch statements to generate. */
+INLINE int
+Options::get_total_switches ()
+{
+ T (Trace t ("Options::get_total_switches");)
+ return total_switches;
+}
diff --git a/contrib/gperf/src/read-line.cc b/contrib/gperf/src/read-line.cc
new file mode 100644
index 0000000..8cb0971
--- /dev/null
+++ b/contrib/gperf/src/read-line.cc
@@ -0,0 +1,97 @@
+/* Correctly reads an arbitrarily size string.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "read-line.h"
+
+#include <stdlib.h>
+#include <string.h> /* declares memcpy() */
+#include "options.h"
+#include "trace.h"
+
+/* Recursively fills up the buffer. */
+
+#define CHUNK_SIZE 4096
+
+/* CHUNKS is the number of chunks (each of size CHUNK_SIZE) which have
+ already been read and which are temporarily stored on the stack.
+ This function reads the remainder of the line, allocates a buffer
+ for the entire line, fills the part beyond &buffer[chunks*CHUNK_SIZE],
+ and returns &buffer[chunks*CHUNK_SIZE]. */
+
+char *
+Read_Line::readln_aux (int chunks)
+{
+ T (Trace t ("Read_Line::readln_aux");)
+#if LARGE_STACK
+ char buf[CHUNK_SIZE];
+#else
+ // Note: we don't use new, because that invokes a custom operator new.
+ char *buf = (char*)malloc(CHUNK_SIZE);
+ if (buf == NULL)
+ abort ();
+#endif
+ char *bufptr = buf;
+ char *ptr;
+ int c;
+
+ while (c = getc (fp), c != EOF && c != '\n') /* fill the current buffer */
+ {
+ *bufptr++ = c;
+ if (bufptr - buf == CHUNK_SIZE)
+ {
+ if ((ptr = readln_aux (chunks + 1)) != NULL)
+
+ /* prepend remainder to ptr buffer */
+ {
+ ptr -= CHUNK_SIZE;
+ memcpy (ptr, buf, CHUNK_SIZE);
+ }
+
+ goto done;
+ }
+ }
+ if (c == EOF && bufptr == buf && chunks == 0)
+ ptr = NULL;
+ else
+ {
+ size_t s1 = chunks * CHUNK_SIZE;
+ size_t s2 = bufptr - buf;
+
+ ptr = new char[s1+s2+1];
+ ptr += s1;
+ ptr[s2] = '\0';
+ memcpy (ptr, buf, s2);
+ }
+ done:
+#if !LARGE_STACK
+ free (buf);
+#endif
+
+ return ptr;
+}
+
+#ifndef __OPTIMIZE__
+
+#define INLINE /* not inline */
+#include "read-line.icc"
+#undef INLINE
+
+#endif /* not defined __OPTIMIZE__ */
diff --git a/contrib/gperf/src/read-line.h b/contrib/gperf/src/read-line.h
new file mode 100644
index 0000000..b243c84
--- /dev/null
+++ b/contrib/gperf/src/read-line.h
@@ -0,0 +1,53 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Reads arbitrarily long string from input file, returning it as a
+ dynamically allocated buffer.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+/* Returns a pointer to an arbitrary length string. Returns NULL on error or EOF
+ The storage for the string is dynamically allocated by new. */
+
+#ifndef read_line_h
+#define read_line_h 1
+
+#include <stdio.h>
+
+class Read_Line
+{
+private:
+ char *readln_aux (int chunks);
+ FILE *fp; /* FILE pointer to the input stream. */
+
+public:
+ Read_Line (FILE *stream = stdin) : fp (stream) {}
+ char *get_line (void);
+};
+
+#ifdef __OPTIMIZE__
+
+#include "trace.h"
+#define INLINE inline
+#include "read-line.icc"
+#undef INLINE
+
+#endif
+
+#endif
diff --git a/contrib/gperf/src/read-line.icc b/contrib/gperf/src/read-line.icc
new file mode 100644
index 0000000..cdb5bf6
--- /dev/null
+++ b/contrib/gperf/src/read-line.icc
@@ -0,0 +1,47 @@
+/* Inline Functions for read-line.{h,cc}.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+// This needs:
+//#include <stdio.h>
+//#include "trace.h"
+
+/* Returns the ``next'' line, ignoring comments beginning with '#'. */
+INLINE char *
+Read_Line::get_line (void)
+{
+ T (Trace t ("Read_Line::get_line");)
+ int c;
+
+ while ((c = getc (fp)) == '#')
+ {
+ while (c = getc (fp), c != EOF && c != '\n')
+ ;
+
+ if (c == EOF)
+ return (char *)0;
+ }
+
+ if (c == EOF)
+ return (char *)0;
+
+ ungetc (c, stdin);
+ return readln_aux (0);
+}
diff --git a/contrib/gperf/src/trace.cc b/contrib/gperf/src/trace.cc
new file mode 100644
index 0000000..e571aba
--- /dev/null
+++ b/contrib/gperf/src/trace.cc
@@ -0,0 +1,35 @@
+/* Tracing function calls.
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "trace.h"
+
+#include <stdio.h>
+
+int Trace::nesting = 0;
+
+Trace::Trace (const char *n)
+{
+ fprintf (stderr, "%*scalling %s\n", 3 * nesting++, "", name = n);
+}
+
+Trace::~Trace (void)
+{
+ fprintf (stderr, "%*sleaving %s\n", 3 * --nesting, "", name);
+}
diff --git a/contrib/gperf/src/trace.h b/contrib/gperf/src/trace.h
new file mode 100644
index 0000000..f16fcc5
--- /dev/null
+++ b/contrib/gperf/src/trace.h
@@ -0,0 +1,40 @@
+/* Tracing function calls.
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#ifndef trace_h
+#define trace_h 1
+
+#ifdef TRACE
+#define T(X) X
+#else
+#define T(X)
+#endif
+
+class Trace
+{
+private:
+ static int nesting;
+ const char *name;
+public:
+ Trace (const char *n);
+ ~Trace (void);
+};
+
+#endif
diff --git a/contrib/gperf/src/vectors.cc b/contrib/gperf/src/vectors.cc
new file mode 100644
index 0000000..1da014d
--- /dev/null
+++ b/contrib/gperf/src/vectors.cc
@@ -0,0 +1,25 @@
+/* Static class data members that are shared between several classes.
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "vectors.h"
+
+int Vectors::ALPHA_SIZE = MAX_ALPHA_SIZE;
+int Vectors::occurrences[MAX_ALPHA_SIZE];
+int Vectors::asso_values[MAX_ALPHA_SIZE];
diff --git a/contrib/gperf/src/vectors.h b/contrib/gperf/src/vectors.h
new file mode 100644
index 0000000..28a1053
--- /dev/null
+++ b/contrib/gperf/src/vectors.h
@@ -0,0 +1,37 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Static class data members that are shared between several classes via
+ inheritance.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#ifndef vectors_h
+#define vectors_h 1
+
+static const int MAX_ALPHA_SIZE = 256;
+
+struct Vectors
+{
+ static int ALPHA_SIZE; /* Size of alphabet. */
+ static int occurrences[MAX_ALPHA_SIZE]; /* Counts occurrences of each key set character. */
+ static int asso_values[MAX_ALPHA_SIZE]; /* Value associated with each character. */
+};
+
+#endif
diff --git a/contrib/gperf/src/version.cc b/contrib/gperf/src/version.cc
new file mode 100644
index 0000000..2e5cf68
--- /dev/null
+++ b/contrib/gperf/src/version.cc
@@ -0,0 +1,22 @@
+/* Current program version number.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+const char *version_string = "2.7";
diff --git a/contrib/gperf/src/version.h b/contrib/gperf/src/version.h
new file mode 100644
index 0000000..4ffba2e
--- /dev/null
+++ b/contrib/gperf/src/version.h
@@ -0,0 +1,23 @@
+/* Current program version number.
+
+ Copyright (C) 1989-1998 Free Software Foundation, Inc.
+ written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+/* Current release version. */
+extern const char *version_string;
OpenPOWER on IntegriCloud